diff options
Diffstat (limited to 'src/server/collision')
30 files changed, 0 insertions, 5414 deletions
diff --git a/src/server/collision/BoundingIntervalHierarchy.cpp b/src/server/collision/BoundingIntervalHierarchy.cpp deleted file mode 100644 index 12af680712e..00000000000 --- a/src/server/collision/BoundingIntervalHierarchy.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "BoundingIntervalHierarchy.h" - -#ifdef _MSC_VER - #define isnan _isnan -#else - #define isnan std::isnan -#endif - -void BIH::buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats) -{ - // create space for the first node - tempTree.push_back(uint32(3 << 30)); // dummy leaf - tempTree.insert(tempTree.end(), 2, 0); - //tempTree.add(0); - - // seed bbox - AABound gridBox = { bounds.low(), bounds.high() }; - AABound nodeBox = gridBox; - // seed subdivide function - subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats); -} - -void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats) -{ - if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE) - { - // write leaf node - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - // calculate extents - int axis = -1, prevAxis, rightOrig; - float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan(); - float split = G3D::fnan(), prevSplit; - bool wasLeft = true; - while (true) - { - prevAxis = axis; - prevSplit = split; - // perform quick consistency checks - G3D::Vector3 d( gridBox.hi - gridBox.lo ); - if (d.x < 0 || d.y < 0 || d.z < 0) - throw std::logic_error("negative node extents"); - for (int i = 0; i < 3; i++) - { - if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i]) - { - //UI.printError(Module.ACCEL, "Reached tree area in error - discarding node with: %d objects", right - left + 1); - throw std::logic_error("invalid node overlap"); - } - } - // find longest axis - axis = d.primaryAxis(); - split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]); - // partition L/R subsets - clipL = -G3D::finf(); - clipR = G3D::finf(); - rightOrig = right; // save this for later - float nodeL = G3D::finf(); - float nodeR = -G3D::finf(); - for (int i = left; i <= right;) - { - int obj = dat.indices[i]; - float minb = dat.primBound[obj].low()[axis]; - float maxb = dat.primBound[obj].high()[axis]; - float center = (minb + maxb) * 0.5f; - if (center <= split) - { - // stay left - i++; - if (clipL < maxb) - clipL = maxb; - } - else - { - // move to the right most - int t = dat.indices[i]; - dat.indices[i] = dat.indices[right]; - dat.indices[right] = t; - right--; - if (clipR > minb) - clipR = minb; - } - nodeL = std::min(nodeL, minb); - nodeR = std::max(nodeR, maxb); - } - // check for empty space - if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis]) - { - float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis]; - float nodeNewW = nodeR - nodeL; - // node box is too big compare to space occupied by primitives? - if (1.3f * nodeNewW < nodeBoxW) - { - stats.updateBVH2(); - int nextIndex = tempTree.size(); - // allocate child - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - // write bvh2 clip node - stats.updateInner(); - tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(nodeL); - tempTree[nodeIndex + 2] = floatToRawIntBits(nodeR); - // update nodebox and recurse - nodeBox.lo[axis] = nodeL; - nodeBox.hi[axis] = nodeR; - subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats); - return; - } - } - // ensure we are making progress in the subdivision - if (right == rightOrig) - { - // all left - if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split)) { - // we are stuck here - create a leaf - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - if (clipL <= split) { - // keep looping on left half - gridBox.hi[axis] = split; - prevClip = clipL; - wasLeft = true; - continue; - } - gridBox.hi[axis] = split; - prevClip = G3D::fnan(); - } - else if (left > right) - { - // all right - if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split)) { - // we are stuck here - create a leaf - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - right = rightOrig; - if (clipR >= split) { - // keep looping on right half - gridBox.lo[axis] = split; - prevClip = clipR; - wasLeft = false; - continue; - } - gridBox.lo[axis] = split; - prevClip = G3D::fnan(); - } - else - { - // we are actually splitting stuff - if (prevAxis != -1 && !isnan(prevClip)) - { - // second time through - lets create the previous split - // since it produced empty space - int nextIndex = tempTree.size(); - // allocate child node - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - if (wasLeft) { - // create a node with a left child - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip); - tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::finf()); - } else { - // create a node with a right child - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3); - tempTree[nodeIndex + 1] = floatToRawIntBits(-G3D::finf()); - tempTree[nodeIndex + 2] = floatToRawIntBits(prevClip); - } - // count stats for the unused leaf - depth++; - stats.updateLeaf(depth, 0); - // now we keep going as we are, with a new nodeIndex: - nodeIndex = nextIndex; - } - break; - } - } - // compute index of child nodes - int nextIndex = tempTree.size(); - // allocate left node - int nl = right - left + 1; - int nr = rightOrig - (right + 1) + 1; - if (nl > 0) { - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - } else - nextIndex -= 3; - // allocate right node - if (nr > 0) { - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - } - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (axis << 30) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(clipL); - tempTree[nodeIndex + 2] = floatToRawIntBits(clipR); - // prepare L/R child boxes - AABound gridBoxL(gridBox), gridBoxR(gridBox); - AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox); - gridBoxL.hi[axis] = gridBoxR.lo[axis] = split; - nodeBoxL.hi[axis] = clipL; - nodeBoxR.lo[axis] = clipR; - // recurse - if (nl > 0) - subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats); - else - stats.updateLeaf(depth + 1, 0); - if (nr > 0) - subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats); - else - stats.updateLeaf(depth + 1, 0); -} - -bool BIH::writeToFile(FILE* wf) const -{ - uint32 treeSize = tree.size(); - uint32 check=0, count; - check += fwrite(&bounds.low(), sizeof(float), 3, wf); - check += fwrite(&bounds.high(), sizeof(float), 3, wf); - check += fwrite(&treeSize, sizeof(uint32), 1, wf); - check += fwrite(&tree[0], sizeof(uint32), treeSize, wf); - count = objects.size(); - check += fwrite(&count, sizeof(uint32), 1, wf); - check += fwrite(&objects[0], sizeof(uint32), count, wf); - return check == (3 + 3 + 2 + treeSize + count); -} - -bool BIH::readFromFile(FILE* rf) -{ - uint32 treeSize; - G3D::Vector3 lo, hi; - uint32 check=0, count=0; - check += fread(&lo, sizeof(float), 3, rf); - check += fread(&hi, sizeof(float), 3, rf); - bounds = G3D::AABox(lo, hi); - check += fread(&treeSize, sizeof(uint32), 1, rf); - tree.resize(treeSize); - check += fread(&tree[0], sizeof(uint32), treeSize, rf); - check += fread(&count, sizeof(uint32), 1, rf); - objects.resize(count); // = new uint32[nObjects]; - check += fread(&objects[0], sizeof(uint32), count, rf); - return uint64(check) == uint64(3 + 3 + 1 + 1 + uint64(treeSize) + uint64(count)); -} - -void BIH::BuildStats::updateLeaf(int depth, int n) -{ - numLeaves++; - minDepth = std::min(depth, minDepth); - maxDepth = std::max(depth, maxDepth); - sumDepth += depth; - minObjects = std::min(n, minObjects); - maxObjects = std::max(n, maxObjects); - sumObjects += n; - int nl = std::min(n, 5); - ++numLeavesN[nl]; -} - -void BIH::BuildStats::printStats() -{ - printf("Tree stats:\n"); - printf(" * Nodes: %d\n", numNodes); - printf(" * Leaves: %d\n", numLeaves); - printf(" * Objects: min %d\n", minObjects); - printf(" avg %.2f\n", (float) sumObjects / numLeaves); - printf(" avg(n>0) %.2f\n", (float) sumObjects / (numLeaves - numLeavesN[0])); - printf(" max %d\n", maxObjects); - printf(" * Depth: min %d\n", minDepth); - printf(" avg %.2f\n", (float) sumDepth / numLeaves); - printf(" max %d\n", maxDepth); - printf(" * Leaves w/: N=0 %3d%%\n", 100 * numLeavesN[0] / numLeaves); - printf(" N=1 %3d%%\n", 100 * numLeavesN[1] / numLeaves); - printf(" N=2 %3d%%\n", 100 * numLeavesN[2] / numLeaves); - printf(" N=3 %3d%%\n", 100 * numLeavesN[3] / numLeaves); - printf(" N=4 %3d%%\n", 100 * numLeavesN[4] / numLeaves); - printf(" N>4 %3d%%\n", 100 * numLeavesN[5] / numLeaves); - printf(" * BVH2 nodes: %d (%3d%%)\n", numBVH2, 100 * numBVH2 / (numNodes + numLeaves - 2 * numBVH2)); -} diff --git a/src/server/collision/BoundingIntervalHierarchy.h b/src/server/collision/BoundingIntervalHierarchy.h deleted file mode 100644 index 3a09772c41f..00000000000 --- a/src/server/collision/BoundingIntervalHierarchy.h +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _BIH_H -#define _BIH_H - -#include "G3D/Vector3.h" -#include "G3D/Ray.h" -#include "G3D/AABox.h" - -#include "Define.h" - -#include <stdexcept> -#include <vector> -#include <algorithm> -#include <limits> -#include <cmath> - -#define MAX_STACK_SIZE 64 - -static inline uint32 floatToRawIntBits(float f) -{ - union - { - uint32 ival; - float fval; - } temp; - temp.fval=f; - return temp.ival; -} - -static inline float intBitsToFloat(uint32 i) -{ - union - { - uint32 ival; - float fval; - } temp; - temp.ival=i; - return temp.fval; -} - -struct AABound -{ - G3D::Vector3 lo, hi; -}; - -/** Bounding Interval Hierarchy Class. - Building and Ray-Intersection functions based on BIH from - Sunflow, a Java Raytracer, released under MIT/X11 License - http://sunflow.sourceforge.net/ - Copyright (c) 2003-2007 Christopher Kulla -*/ - -class BIH -{ - private: - void init_empty() - { - tree.clear(); - objects.clear(); - // create space for the first node - tree.push_back(3u << 30u); // dummy leaf - tree.insert(tree.end(), 2, 0); - } - public: - BIH() { init_empty(); } - template< class BoundsFunc, class PrimArray > - void build(const PrimArray &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false) - { - if (primitives.size() == 0) - { - init_empty(); - return; - } - - buildData dat; - dat.maxPrims = leafSize; - dat.numPrims = primitives.size(); - dat.indices = new uint32[dat.numPrims]; - dat.primBound = new G3D::AABox[dat.numPrims]; - getBounds(primitives[0], bounds); - for (uint32 i=0; i<dat.numPrims; ++i) - { - dat.indices[i] = i; - getBounds(primitives[i], dat.primBound[i]); - bounds.merge(dat.primBound[i]); - } - std::vector<uint32> tempTree; - BuildStats stats; - buildHierarchy(tempTree, dat, stats); - if (printStats) - stats.printStats(); - - objects.resize(dat.numPrims); - for (uint32 i=0; i<dat.numPrims; ++i) - objects[i] = dat.indices[i]; - //nObjects = dat.numPrims; - tree = tempTree; - delete[] dat.primBound; - delete[] dat.indices; - } - uint32 primCount() const { return objects.size(); } - - template<typename RayCallback> - void intersectRay(const G3D::Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const - { - float intervalMin = -1.f; - float intervalMax = -1.f; - G3D::Vector3 org = r.origin(); - G3D::Vector3 dir = r.direction(); - G3D::Vector3 invDir; - for (int i=0; i<3; ++i) - { - invDir[i] = 1.f / dir[i]; - if (G3D::fuzzyNe(dir[i], 0.0f)) - { - float t1 = (bounds.low()[i] - org[i]) * invDir[i]; - float t2 = (bounds.high()[i] - org[i]) * invDir[i]; - if (t1 > t2) - std::swap(t1, t2); - if (t1 > intervalMin) - intervalMin = t1; - if (t2 < intervalMax || intervalMax < 0.f) - intervalMax = t2; - // intervalMax can only become smaller for other axis, - // and intervalMin only larger respectively, so stop early - if (intervalMax <= 0 || intervalMin >= maxDist) - return; - } - } - - if (intervalMin > intervalMax) - return; - intervalMin = std::max(intervalMin, 0.f); - intervalMax = std::min(intervalMax, maxDist); - - uint32 offsetFront[3]; - uint32 offsetBack[3]; - uint32 offsetFront3[3]; - uint32 offsetBack3[3]; - // compute custom offsets from direction sign bit - - for (int i=0; i<3; ++i) - { - offsetFront[i] = floatToRawIntBits(dir[i]) >> 31; - offsetBack[i] = offsetFront[i] ^ 1; - offsetFront3[i] = offsetFront[i] * 3; - offsetBack3[i] = offsetBack[i] * 3; - - // avoid always adding 1 during the inner loop - ++offsetFront[i]; - ++offsetBack[i]; - } - - StackNode stack[MAX_STACK_SIZE]; - int stackPos = 0; - int node = 0; - - while (true) { - while (true) - { - uint32 tn = tree[node]; - uint32 axis = (tn & (3 << 30)) >> 30; - bool BVH2 = (tn & (1 << 29)) != 0; - int offset = tn & ~(7 << 29); - if (!BVH2) - { - if (axis < 3) - { - // "normal" interior node - float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; - float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; - // ray passes between clip zones - if (tf < intervalMin && tb > intervalMax) - break; - int back = offset + offsetBack3[axis]; - node = back; - // ray passes through far node only - if (tf < intervalMin) { - intervalMin = (tb >= intervalMin) ? tb : intervalMin; - continue; - } - node = offset + offsetFront3[axis]; // front - // ray passes through near node only - if (tb > intervalMax) { - intervalMax = (tf <= intervalMax) ? tf : intervalMax; - continue; - } - // ray passes through both nodes - // push back node - stack[stackPos].node = back; - stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin; - stack[stackPos].tfar = intervalMax; - stackPos++; - // update ray interval for front node - intervalMax = (tf <= intervalMax) ? tf : intervalMax; - continue; - } - else - { - // leaf - test some objects - int n = tree[node + 1]; - while (n > 0) { - bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirst); - if (stopAtFirst && hit) return; - --n; - ++offset; - } - break; - } - } - else - { - if (axis>2) - return; // should not happen - float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; - float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; - node = offset; - intervalMin = (tf >= intervalMin) ? tf : intervalMin; - intervalMax = (tb <= intervalMax) ? tb : intervalMax; - if (intervalMin > intervalMax) - break; - continue; - } - } // traversal loop - do - { - // stack is empty? - if (stackPos == 0) - return; - // move back up the stack - stackPos--; - intervalMin = stack[stackPos].tnear; - if (maxDist < intervalMin) - continue; - node = stack[stackPos].node; - intervalMax = stack[stackPos].tfar; - break; - } while (true); - } - } - - template<typename IsectCallback> - void intersectPoint(const G3D::Vector3 &p, IsectCallback& intersectCallback) const - { - if (!bounds.contains(p)) - return; - - StackNode stack[MAX_STACK_SIZE]; - int stackPos = 0; - int node = 0; - - while (true) { - while (true) - { - uint32 tn = tree[node]; - uint32 axis = (tn & (3 << 30)) >> 30; - bool BVH2 = (tn & (1 << 29)) != 0; - int offset = tn & ~(7 << 29); - if (!BVH2) - { - if (axis < 3) - { - // "normal" interior node - float tl = intBitsToFloat(tree[node + 1]); - float tr = intBitsToFloat(tree[node + 2]); - // point is between clip zones - if (tl < p[axis] && tr > p[axis]) - break; - int right = offset + 3; - node = right; - // point is in right node only - if (tl < p[axis]) { - continue; - } - node = offset; // left - // point is in left node only - if (tr > p[axis]) { - continue; - } - // point is in both nodes - // push back right node - stack[stackPos].node = right; - stackPos++; - continue; - } - else - { - // leaf - test some objects - int n = tree[node + 1]; - while (n > 0) { - intersectCallback(p, objects[offset]); // !!! - --n; - ++offset; - } - break; - } - } - else // BVH2 node (empty space cut off left and right) - { - if (axis>2) - return; // should not happen - float tl = intBitsToFloat(tree[node + 1]); - float tr = intBitsToFloat(tree[node + 2]); - node = offset; - if (tl > p[axis] || tr < p[axis]) - break; - continue; - } - } // traversal loop - - // stack is empty? - if (stackPos == 0) - return; - // move back up the stack - stackPos--; - node = stack[stackPos].node; - } - } - - bool writeToFile(FILE* wf) const; - bool readFromFile(FILE* rf); - - protected: - std::vector<uint32> tree; - std::vector<uint32> objects; - G3D::AABox bounds; - - struct buildData - { - uint32 *indices; - G3D::AABox *primBound; - uint32 numPrims; - int maxPrims; - }; - struct StackNode - { - uint32 node; - float tnear; - float tfar; - }; - - class BuildStats - { - private: - int numNodes; - int numLeaves; - int sumObjects; - int minObjects; - int maxObjects; - int sumDepth; - int minDepth; - int maxDepth; - int numLeavesN[6]; - int numBVH2; - - public: - BuildStats(): - numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF), - maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF), - maxDepth(0xFFFFFFFF), numBVH2(0) - { - for (int i=0; i<6; ++i) numLeavesN[i] = 0; - } - - void updateInner() { numNodes++; } - void updateBVH2() { numBVH2++; } - void updateLeaf(int depth, int n); - void printStats(); - }; - - void buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats); - - void createNode(std::vector<uint32> &tempTree, int nodeIndex, uint32 left, uint32 right) const - { - // write leaf node - tempTree[nodeIndex + 0] = (3 << 30) | left; - tempTree[nodeIndex + 1] = right - left + 1; - } - - void subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats); -}; - -#endif // _BIH_H diff --git a/src/server/collision/BoundingIntervalHierarchyWrapper.h b/src/server/collision/BoundingIntervalHierarchyWrapper.h deleted file mode 100644 index 60bb6a569df..00000000000 --- a/src/server/collision/BoundingIntervalHierarchyWrapper.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _BIH_WRAP -#define _BIH_WRAP - -#include "G3D/Table.h" -#include "G3D/Array.h" -#include "G3D/Set.h" -#include "BoundingIntervalHierarchy.h" - - -template<class T, class BoundsFunc = BoundsTrait<T> > -class BIHWrap -{ - template<class RayCallback> - struct MDLCallback - { - const T* const* objects; - RayCallback& _callback; - uint32 objects_size; - - MDLCallback(RayCallback& callback, const T* const* objects_array, uint32 objects_size ) : objects(objects_array), _callback(callback), objects_size(objects_size) { } - - /// Intersect ray - bool operator() (const G3D::Ray& ray, uint32 idx, float& maxDist, bool /*stopAtFirst*/) - { - if (idx >= objects_size) - return false; - if (const T* obj = objects[idx]) - return _callback(ray, *obj, maxDist/*, stopAtFirst*/); - return false; - } - - /// Intersect point - void operator() (const G3D::Vector3& p, uint32 idx) - { - if (idx >= objects_size) - return; - if (const T* obj = objects[idx]) - _callback(p, *obj); - } - }; - - typedef G3D::Array<const T*> ObjArray; - - BIH m_tree; - ObjArray m_objects; - G3D::Table<const T*, uint32> m_obj2Idx; - G3D::Set<const T*> m_objects_to_push; - int unbalanced_times; - -public: - BIHWrap() : unbalanced_times(0) { } - - void insert(const T& obj) - { - ++unbalanced_times; - m_objects_to_push.insert(&obj); - } - - void remove(const T& obj) - { - ++unbalanced_times; - uint32 Idx = 0; - const T * temp; - if (m_obj2Idx.getRemove(&obj, temp, Idx)) - m_objects[Idx] = NULL; - else - m_objects_to_push.remove(&obj); - } - - void balance() - { - if (unbalanced_times == 0) - return; - - unbalanced_times = 0; - m_objects.fastClear(); - m_obj2Idx.getKeys(m_objects); - m_objects_to_push.getMembers(m_objects); - //assert that m_obj2Idx has all the keys - - m_tree.build(m_objects, BoundsFunc::getBounds2); - } - - template<typename RayCallback> - void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& maxDist) - { - balance(); - MDLCallback<RayCallback> temp_cb(intersectCallback, m_objects.getCArray(), m_objects.size()); - m_tree.intersectRay(ray, temp_cb, maxDist, true); - } - - template<typename IsectCallback> - void intersectPoint(const G3D::Vector3& point, IsectCallback& intersectCallback) - { - balance(); - MDLCallback<IsectCallback> callback(intersectCallback, m_objects.getCArray(), m_objects.size()); - m_tree.intersectPoint(point, callback); - } -}; - -#endif // _BIH_WRAP diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt deleted file mode 100644 index f394fe791be..00000000000 --- a/src/server/collision/CMakeLists.txt +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -if( USE_COREPCH ) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) -endif() - -file(GLOB_RECURSE sources_Management Management/*.cpp Management/*.h) -file(GLOB_RECURSE sources_Maps Maps/*.cpp Maps/*.h) -file(GLOB_RECURSE sources_Models Models/*.cpp Models/*.h) -file(GLOB sources_localdir *.cpp *.h) - -if (USE_COREPCH) - set(collision_STAT_PCH_HDR PrecompiledHeaders/collisionPCH.h) - set(collision_STAT_PCH_SRC PrecompiledHeaders/collisionPCH.cpp) -endif () - -set(collision_STAT_SRCS - ${collision_STAT_SRCS} - ${sources_Management} - ${sources_Maps} - ${sources_Models} - ${sources_localdir} -) - -include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/Addons - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object/Updates - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Unit - ${CMAKE_SOURCE_DIR}/src/server/game/Combat - ${CMAKE_SOURCE_DIR}/src/server/game/Loot - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous - ${CMAKE_SOURCE_DIR}/src/server/game/Grids - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Notifiers - ${CMAKE_SOURCE_DIR}/src/server/game/Maps - ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline - ${CMAKE_SOURCE_DIR}/src/server/game/Movement - ${CMAKE_SOURCE_DIR}/src/server/game/Server - ${CMAKE_SOURCE_DIR}/src/server/game/Server/Protocol - ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_SOURCE_DIR}/src/server/game/Spells - ${CMAKE_SOURCE_DIR}/src/server/game/Spells/Auras - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Management - ${CMAKE_CURRENT_SOURCE_DIR}/Maps - ${CMAKE_CURRENT_SOURCE_DIR}/Models - ${MYSQL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} -) - -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) - -add_library(collision STATIC - ${collision_STAT_SRCS} - ${collision_STAT_PCH_SRC} -) - -target_link_libraries(collision - shared -) - -# Generate precompiled header -if (USE_COREPCH) - add_cxx_pch(collision ${collision_STAT_PCH_HDR} ${collision_STAT_PCH_SRC}) -endif () diff --git a/src/server/collision/DynamicTree.cpp b/src/server/collision/DynamicTree.cpp deleted file mode 100644 index 1de2543543d..00000000000 --- a/src/server/collision/DynamicTree.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "DynamicTree.h" -//#include "QuadTree.h" -//#include "RegularGrid.h" -#include "BoundingIntervalHierarchyWrapper.h" - -#include "Log.h" -#include "RegularGrid.h" -#include "Timer.h" -#include "GameObjectModel.h" -#include "ModelInstance.h" - -#include <G3D/AABox.h> -#include <G3D/Ray.h> -#include <G3D/Vector3.h> - -using VMAP::ModelInstance; - -namespace { - -int CHECK_TREE_PERIOD = 200; - -} // namespace - -template<> struct HashTrait< GameObjectModel>{ - static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; } -}; - -template<> struct PositionTrait< GameObjectModel> { - static void getPosition(const GameObjectModel& g, G3D::Vector3& p) { p = g.getPosition(); } -}; - -template<> struct BoundsTrait< GameObjectModel> { - static void getBounds(const GameObjectModel& g, G3D::AABox& out) { out = g.getBounds();} - static void getBounds2(const GameObjectModel* g, G3D::AABox& out) { out = g->getBounds();} -}; - -/* -static bool operator == (const GameObjectModel& mdl, const GameObjectModel& mdl2){ - return &mdl == &mdl2; -} -*/ - -typedef RegularGrid2D<GameObjectModel, BIHWrap<GameObjectModel> > ParentTree; - -struct DynTreeImpl : public ParentTree/*, public Intersectable*/ -{ - typedef GameObjectModel Model; - typedef ParentTree base; - - DynTreeImpl() : - rebalance_timer(CHECK_TREE_PERIOD), - unbalanced_times(0) - { - } - - void insert(const Model& mdl) - { - base::insert(mdl); - ++unbalanced_times; - } - - void remove(const Model& mdl) - { - base::remove(mdl); - ++unbalanced_times; - } - - void balance() - { - base::balance(); - unbalanced_times = 0; - } - - void update(uint32 difftime) - { - if (!size()) - return; - - rebalance_timer.Update(difftime); - if (rebalance_timer.Passed()) - { - rebalance_timer.Reset(CHECK_TREE_PERIOD); - if (unbalanced_times > 0) - balance(); - } - } - - TimeTrackerSmall rebalance_timer; - int unbalanced_times; -}; - -DynamicMapTree::DynamicMapTree() : impl(new DynTreeImpl()) { } - -DynamicMapTree::~DynamicMapTree() -{ - delete impl; -} - -void DynamicMapTree::insert(const GameObjectModel& mdl) -{ - impl->insert(mdl); -} - -void DynamicMapTree::remove(const GameObjectModel& mdl) -{ - impl->remove(mdl); -} - -bool DynamicMapTree::contains(const GameObjectModel& mdl) const -{ - return impl->contains(mdl); -} - -void DynamicMapTree::balance() -{ - impl->balance(); -} - -int DynamicMapTree::size() const -{ - return impl->size(); -} - -void DynamicMapTree::update(uint32 t_diff) -{ - impl->update(t_diff); -} - -struct DynamicTreeIntersectionCallback -{ - bool did_hit; - uint32 phase_mask; - DynamicTreeIntersectionCallback(uint32 phasemask) : did_hit(false), phase_mask(phasemask) { } - bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance) - { - did_hit = obj.intersectRay(r, distance, true, phase_mask); - return did_hit; - } - bool didHit() const { return did_hit;} -}; - -struct DynamicTreeIntersectionCallback_WithLogger -{ - bool did_hit; - uint32 phase_mask; - DynamicTreeIntersectionCallback_WithLogger(uint32 phasemask) : did_hit(false), phase_mask(phasemask) - { - TC_LOG_DEBUG("maps", "Dynamic Intersection log"); - } - bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance) - { - TC_LOG_DEBUG("maps", "testing intersection with %s", obj.name.c_str()); - bool hit = obj.intersectRay(r, distance, true, phase_mask); - if (hit) - { - did_hit = true; - TC_LOG_DEBUG("maps", "result: intersects"); - } - return hit; - } - bool didHit() const { return did_hit;} -}; - -bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray, - const G3D::Vector3& endPos, float& maxDist) const -{ - float distance = maxDist; - DynamicTreeIntersectionCallback callback(phasemask); - impl->intersectRay(ray, callback, distance, endPos); - if (callback.didHit()) - maxDist = distance; - return callback.didHit(); -} - -bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3& startPos, - const G3D::Vector3& endPos, G3D::Vector3& resultHit, - float modifyDist) const -{ - bool result = false; - float maxDist = (endPos - startPos).magnitude(); - // valid map coords should *never ever* produce float overflow, but this would produce NaNs too - ASSERT(maxDist < std::numeric_limits<float>::max()); - // prevent NaN values which can cause BIH intersection to enter infinite loop - if (maxDist < 1e-10f) - { - resultHit = endPos; - return false; - } - G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1 - G3D::Ray ray(startPos, dir); - float dist = maxDist; - if (getIntersectionTime(phasemask, ray, endPos, dist)) - { - resultHit = startPos + dir * dist; - if (modifyDist < 0) - { - if ((resultHit - startPos).magnitude() > -modifyDist) - resultHit = resultHit + dir*modifyDist; - else - resultHit = startPos; - } - else - resultHit = resultHit + dir*modifyDist; - - result = true; - } - else - { - resultHit = endPos; - result = false; - } - return result; -} - -bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const -{ - G3D::Vector3 v1(x1, y1, z1), v2(x2, y2, z2); - - float maxDist = (v2 - v1).magnitude(); - - if (!G3D::fuzzyGt(maxDist, 0) ) - return true; - - G3D::Ray r(v1, (v2-v1) / maxDist); - DynamicTreeIntersectionCallback callback(phasemask); - impl->intersectRay(r, callback, maxDist, v2); - - return !callback.did_hit; -} - -float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const -{ - G3D::Vector3 v(x, y, z); - G3D::Ray r(v, G3D::Vector3(0, 0, -1)); - DynamicTreeIntersectionCallback callback(phasemask); - impl->intersectZAllignedRay(r, callback, maxSearchDist); - - if (callback.didHit()) - return v.z - maxSearchDist; - else - return -G3D::finf(); -} diff --git a/src/server/collision/DynamicTree.h b/src/server/collision/DynamicTree.h deleted file mode 100644 index 5e905323640..00000000000 --- a/src/server/collision/DynamicTree.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DYNTREE_H -#define _DYNTREE_H - -#include "Define.h" - -namespace G3D -{ - class Ray; - class Vector3; -} - -class GameObjectModel; -struct DynTreeImpl; - -class DynamicMapTree -{ - DynTreeImpl *impl; - -public: - - DynamicMapTree(); - ~DynamicMapTree(); - - bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, - float z2, uint32 phasemask) const; - - bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray, - const G3D::Vector3& endPos, float& maxDist) const; - - bool getObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1, - const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos, - float pModifyDist) const; - - float getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const; - - void insert(const GameObjectModel&); - void remove(const GameObjectModel&); - bool contains(const GameObjectModel&) const; - int size() const; - - void balance(); - void update(uint32 diff); -}; - -#endif // _DYNTREE_H diff --git a/src/server/collision/Management/IVMapManager.h b/src/server/collision/Management/IVMapManager.h deleted file mode 100644 index b890554257c..00000000000 --- a/src/server/collision/Management/IVMapManager.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _IVMAPMANAGER_H -#define _IVMAPMANAGER_H - -#include <string> -#include "Define.h" - -//=========================================================== - -/** -This is the minimum interface to the VMapMamager. -*/ - -namespace VMAP -{ - - enum VMAP_LOAD_RESULT - { - VMAP_LOAD_RESULT_ERROR, - VMAP_LOAD_RESULT_OK, - VMAP_LOAD_RESULT_IGNORED - }; - - #define VMAP_INVALID_HEIGHT -100000.0f // for check - #define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case - - //=========================================================== - class IVMapManager - { - private: - bool iEnableLineOfSightCalc; - bool iEnableHeightCalc; - - public: - IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) { } - - virtual ~IVMapManager(void) { } - - virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; - - virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; - - virtual void unloadMap(unsigned int pMapId, int x, int y) = 0; - virtual void unloadMap(unsigned int pMapId) = 0; - - virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0; - virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist) = 0; - /** - test if we hit an object. return true if we hit one. rx, ry, rz will hold the hit position or the dest position, if no intersection was found - return a position, that is pReduceDist closer to the origin - */ - virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) = 0; - /** - send debug commands - */ - virtual bool processCommand(char *pCommand)= 0; - - /** - Enable/disable LOS calculation - It is enabled by default. If it is enabled in mid game the maps have to loaded manualy - */ - void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; } - /** - Enable/disable model height calculation - It is enabled by default. If it is enabled in mid game the maps have to loaded manualy - */ - void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; } - - bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); } - bool isHeightCalcEnabled() const { return(iEnableHeightCalc); } - bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); } - - virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0; - /** - Query world model area info. - \param z gets adjusted to the ground height for which this are info is valid - */ - virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0; - virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const=0; - }; - -} -#endif diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp deleted file mode 100644 index 667b8378c56..00000000000 --- a/src/server/collision/Management/MMapFactory.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "MMapFactory.h" -#include "Config.h" - -namespace MMAP -{ - // ######################## MMapFactory ######################## - // our global singleton copy - MMapManager* g_MMapManager = NULL; - - MMapManager* MMapFactory::createOrGetMMapManager() - { - if (g_MMapManager == NULL) - g_MMapManager = new MMapManager(); - - return g_MMapManager; - } - - void MMapFactory::clear() - { - if (g_MMapManager) - { - delete g_MMapManager; - g_MMapManager = NULL; - } - } -}
\ No newline at end of file diff --git a/src/server/collision/Management/MMapFactory.h b/src/server/collision/Management/MMapFactory.h deleted file mode 100644 index 773983f81eb..00000000000 --- a/src/server/collision/Management/MMapFactory.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _MMAP_FACTORY_H -#define _MMAP_FACTORY_H - -#include "Define.h" -#include "MMapManager.h" -#include "DetourAlloc.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" -#include <unordered_map> - -namespace MMAP -{ - enum MMAP_LOAD_RESULT - { - MMAP_LOAD_RESULT_ERROR, - MMAP_LOAD_RESULT_OK, - MMAP_LOAD_RESULT_IGNORED - }; - - // static class - // holds all mmap global data - // access point to MMapManager singleton - class MMapFactory - { - public: - static MMapManager* createOrGetMMapManager(); - static void clear(); - static bool IsPathfindingEnabled(uint32 mapId); - }; -} - -#endif - diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp deleted file mode 100644 index b71b94e3291..00000000000 --- a/src/server/collision/Management/MMapManager.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "MMapManager.h" -#include "Log.h" -#include "World.h" - -namespace MMAP -{ - // ######################## MMapManager ######################## - MMapManager::~MMapManager() - { - for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i) - delete i->second; - - // by now we should not have maps loaded - // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost! - } - - void MMapManager::InitializeThreadUnsafe(const std::vector<uint32>& mapIds) - { - // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime - for (const uint32& mapId : mapIds) - loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)); - - thread_safe_environment = false; - } - - MMapDataSet::const_iterator MMapManager::GetMMapData(uint32 mapId) const - { - // return the iterator if found or end() if not found/NULL - MMapDataSet::const_iterator itr = loadedMMaps.find(mapId); - if (itr != loadedMMaps.cend() && !itr->second) - itr = loadedMMaps.cend(); - - return itr; - } - - bool MMapManager::loadMapData(uint32 mapId) - { - // we already have this map loaded? - MMapDataSet::iterator itr = loadedMMaps.find(mapId); - if (itr != loadedMMaps.end()) - { - if (itr->second) - return true; - } - else - { - if (thread_safe_environment) - itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first; - else - ASSERT(false, "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId); - } - - // load and init dtNavMesh - read parameters from file - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap")+1; - char *fileName = new char[pathLen]; - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId); - - FILE* file = fopen(fileName, "rb"); - if (!file) - { - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName); - delete [] fileName; - return false; - } - - dtNavMeshParams params; - int count = fread(¶ms, sizeof(dtNavMeshParams), 1, file); - fclose(file); - if (count != 1) - { - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName); - delete [] fileName; - return false; - } - - dtNavMesh* mesh = dtAllocNavMesh(); - ASSERT(mesh); - if (dtStatusFailed(mesh->init(¶ms))) - { - dtFreeNavMesh(mesh); - TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); - delete [] fileName; - return false; - } - - delete [] fileName; - - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId); - - // store inside our map list - MMapData* mmap_data = new MMapData(mesh); - mmap_data->mmapLoadedTiles.clear(); - - itr->second = mmap_data; - return true; - } - - uint32 MMapManager::packTileID(int32 x, int32 y) - { - return uint32(x << 16 | y); - } - - bool MMapManager::loadMap(const std::string& /*basePath*/, uint32 mapId, int32 x, int32 y) - { - // make sure the mmap is loaded and ready to load tiles - if (!loadMapData(mapId)) - return false; - - // get this mmap data - MMapData* mmap = loadedMMaps[mapId]; - ASSERT(mmap->navMesh); - - // check if we already have this tile loaded - uint32 packedGridPos = packTileID(x, y); - if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end()) - return false; - - // load this tile :: mmaps/MMMXXYY.mmtile - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1; - char *fileName = new char[pathLen]; - - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); - - FILE* file = fopen(fileName, "rb"); - if (!file) - { - TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName); - delete [] fileName; - return false; - } - delete [] fileName; - - // read header - MmapTileHeader fileHeader; - if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC) - { - TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); - fclose(file); - return false; - } - - if (fileHeader.mmapVersion != MMAP_VERSION) - { - TC_LOG_ERROR("maps", "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", - mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); - fclose(file); - return false; - } - - unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM); - ASSERT(data); - - size_t result = fread(data, fileHeader.size, 1, file); - if (!result) - { - TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); - fclose(file); - return false; - } - - fclose(file); - - dtMeshHeader* header = (dtMeshHeader*)data; - dtTileRef tileRef = 0; - - // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed - if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef))) - { - mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef)); - ++loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y); - return true; - } - else - { - TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y); - dtFree(data); - return false; - } - } - - bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y) - { - // check if we have this map loaded - MMapDataSet::const_iterator itr = GetMMapData(mapId); - if (itr == loadedMMaps.end()) - { - // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y); - return false; - } - - MMapData* mmap = itr->second; - - // check if we have this tile loaded - uint32 packedGridPos = packTileID(x, y); - if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end()) - { - // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y); - return false; - } - - dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos]; - - // unload, and mark as non loaded - if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, NULL, NULL))) - { - // this is technically a memory leak - // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used - // we cannot recover from this error - assert out - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); - ASSERT(false); - } - else - { - mmap->mmapLoadedTiles.erase(packedGridPos); - --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); - return true; - } - - return false; - } - - bool MMapManager::unloadMap(uint32 mapId) - { - MMapDataSet::iterator itr = loadedMMaps.find(mapId); - if (itr == loadedMMaps.end() || !itr->second) - { - // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId); - return false; - } - - // unload all tiles from given map - MMapData* mmap = itr->second; - for (MMapTileSet::iterator i = mmap->mmapLoadedTiles.begin(); i != mmap->mmapLoadedTiles.end(); ++i) - { - uint32 x = (i->first >> 16); - uint32 y = (i->first & 0x0000FFFF); - if (dtStatusFailed(mmap->navMesh->removeTile(i->second, NULL, NULL))) - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); - else - { - --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); - } - } - - delete mmap; - itr->second = nullptr; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %03i.mmap", mapId); - - return true; - } - - bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId) - { - // check if we have this map loaded - MMapDataSet::const_iterator itr = GetMMapData(mapId); - if (itr == loadedMMaps.end()) - { - // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId); - return false; - } - - MMapData* mmap = itr->second; - if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) - { - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId); - return false; - } - - dtNavMeshQuery* query = mmap->navMeshQueries[instanceId]; - - dtFreeNavMeshQuery(query); - mmap->navMeshQueries.erase(instanceId); - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); - - return true; - } - - dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId) - { - MMapDataSet::const_iterator itr = GetMMapData(mapId); - if (itr == loadedMMaps.end()) - return NULL; - - return itr->second->navMesh; - } - - dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId) - { - MMapDataSet::const_iterator itr = GetMMapData(mapId); - if (itr == loadedMMaps.end()) - return NULL; - - MMapData* mmap = itr->second; - if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) - { - // allocate mesh query - dtNavMeshQuery* query = dtAllocNavMeshQuery(); - ASSERT(query); - if (dtStatusFailed(query->init(mmap->navMesh, 1024))) - { - dtFreeNavMeshQuery(query); - TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - return NULL; - } - - TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query)); - } - - return mmap->navMeshQueries[instanceId]; - } -} diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h deleted file mode 100644 index 42292b76942..00000000000 --- a/src/server/collision/Management/MMapManager.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _MMAP_MANAGER_H -#define _MMAP_MANAGER_H - -#include "Define.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" - -#include <string> -#include <unordered_map> -#include <vector> - -// move map related classes -namespace MMAP -{ - typedef std::unordered_map<uint32, dtTileRef> MMapTileSet; - typedef std::unordered_map<uint32, dtNavMeshQuery*> NavMeshQuerySet; - - // dummy struct to hold map's mmap data - struct MMapData - { - MMapData(dtNavMesh* mesh) : navMesh(mesh) { } - ~MMapData() - { - for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i) - dtFreeNavMeshQuery(i->second); - - if (navMesh) - dtFreeNavMesh(navMesh); - } - - dtNavMesh* navMesh; - - // we have to use single dtNavMeshQuery for every instance, since those are not thread safe - NavMeshQuerySet navMeshQueries; // instanceId to query - MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile] - }; - - - typedef std::unordered_map<uint32, MMapData*> MMapDataSet; - - // singleton class - // holds all all access to mmap loading unloading and meshes - class MMapManager - { - public: - MMapManager() : loadedTiles(0), thread_safe_environment(true) {} - ~MMapManager(); - - void InitializeThreadUnsafe(const std::vector<uint32>& mapIds); - bool loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y); - bool unloadMap(uint32 mapId, int32 x, int32 y); - bool unloadMap(uint32 mapId); - bool unloadMapInstance(uint32 mapId, uint32 instanceId); - - // the returned [dtNavMeshQuery const*] is NOT threadsafe - dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId); - dtNavMesh const* GetNavMesh(uint32 mapId); - - uint32 getLoadedTilesCount() const { return loadedTiles; } - uint32 getLoadedMapsCount() const { return loadedMMaps.size(); } - private: - bool loadMapData(uint32 mapId); - uint32 packTileID(int32 x, int32 y); - - MMapDataSet::const_iterator GetMMapData(uint32 mapId) const; - MMapDataSet loadedMMaps; - uint32 loadedTiles; - bool thread_safe_environment; - }; -} - -#endif
\ No newline at end of file diff --git a/src/server/collision/Management/VMapFactory.cpp b/src/server/collision/Management/VMapFactory.cpp deleted file mode 100644 index 4c2750a9e5c..00000000000 --- a/src/server/collision/Management/VMapFactory.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "VMapFactory.h" -#include "VMapManager2.h" - -namespace VMAP -{ - IVMapManager* gVMapManager = NULL; - - //=============================================== - // just return the instance - IVMapManager* VMapFactory::createOrGetVMapManager() - { - if (gVMapManager == nullptr) - gVMapManager= new VMapManager2(); // should be taken from config ... Please change if you like :-) - return gVMapManager; - } - - //=============================================== - // delete all internal data structures - void VMapFactory::clear() - { - delete gVMapManager; - gVMapManager = NULL; - } -} diff --git a/src/server/collision/Management/VMapFactory.h b/src/server/collision/Management/VMapFactory.h deleted file mode 100644 index 3067c2919d5..00000000000 --- a/src/server/collision/Management/VMapFactory.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _VMAPFACTORY_H -#define _VMAPFACTORY_H - -#include "IVMapManager.h" - -/** -This is the access point to the VMapManager. -*/ - -namespace VMAP -{ - //=========================================================== - - class VMapFactory - { - public: - static IVMapManager* createOrGetVMapManager(); - static void clear(); - }; - -} -#endif diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp deleted file mode 100644 index 9594951196f..00000000000 --- a/src/server/collision/Management/VMapManager2.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <iostream> -#include <iomanip> -#include <string> -#include <sstream> -#include "VMapManager2.h" -#include "MapTree.h" -#include "ModelInstance.h" -#include "WorldModel.h" -#include <G3D/Vector3.h> -#include "Log.h" -#include "VMapDefinitions.h" -#include "Errors.h" - -using G3D::Vector3; - -namespace VMAP -{ - VMapManager2::VMapManager2() - { - GetLiquidFlagsPtr = &GetLiquidFlagsDummy; - IsVMAPDisabledForPtr = &IsVMAPDisabledForDummy; - thread_safe_environment = true; - } - - VMapManager2::~VMapManager2(void) - { - for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i) - { - delete i->second; - } - for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i) - { - delete i->second.getModel(); - } - } - - void VMapManager2::InitializeThreadUnsafe(const std::vector<uint32>& mapIds) - { - // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime - for (const uint32& mapId : mapIds) - iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)); - - thread_safe_environment = false; - } - - Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const - { - Vector3 pos; - const float mid = 0.5f * 64.0f * 533.33333333f; - pos.x = mid - x; - pos.y = mid - y; - pos.z = z; - - return pos; - } - - // move to MapTree too? - std::string VMapManager2::getMapFileName(unsigned int mapId) - { - std::stringstream fname; - fname.width(3); - fname << std::setfill('0') << mapId << std::string(MAP_FILENAME_EXTENSION2); - - return fname.str(); - } - - int VMapManager2::loadMap(const char* basePath, unsigned int mapId, int x, int y) - { - int result = VMAP_LOAD_RESULT_IGNORED; - if (isMapLoadingEnabled()) - { - if (_loadMap(mapId, basePath, x, y)) - result = VMAP_LOAD_RESULT_OK; - else - result = VMAP_LOAD_RESULT_ERROR; - } - - return result; - } - - InstanceTreeMap::const_iterator VMapManager2::GetMapTree(uint32 mapId) const - { - // return the iterator if found or end() if not found/NULL - InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId); - if (itr != iInstanceMapTrees.cend() && !itr->second) - itr = iInstanceMapTrees.cend(); - - return itr; - } - - // load one tile (internal use only) - bool VMapManager2::_loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); - if (instanceTree == iInstanceMapTrees.end()) - { - if (thread_safe_environment) - instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first; - else - ASSERT(false, "Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment", - mapId, tileX, tileY); - } - - if (!instanceTree->second) - { - std::string mapFileName = getMapFileName(mapId); - StaticMapTree* newTree = new StaticMapTree(mapId, basePath); - if (!newTree->InitMap(mapFileName, this)) - { - delete newTree; - return false; - } - instanceTree->second = newTree; - } - - return instanceTree->second->LoadMapTile(tileX, tileY, this); - } - - void VMapManager2::unloadMap(unsigned int mapId) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); - if (instanceTree != iInstanceMapTrees.end() && instanceTree->second) - { - instanceTree->second->UnloadMap(this); - if (instanceTree->second->numLoadedTiles() == 0) - { - delete instanceTree->second; - instanceTree->second = nullptr; - } - } - } - - void VMapManager2::unloadMap(unsigned int mapId, int x, int y) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); - if (instanceTree != iInstanceMapTrees.end() && instanceTree->second) - { - instanceTree->second->UnloadMapTile(x, y, this); - if (instanceTree->second->numLoadedTiles() == 0) - { - delete instanceTree->second; - instanceTree->second = nullptr; - } - } - } - - bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) - { - if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) - return true; - - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1); - Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2); - if (pos1 != pos2) - { - return instanceTree->second->isInLineOfSight(pos1, pos2); - } - } - - return true; - } - - /** - get the hit position and return true if we hit something - otherwise the result pos will be the dest pos - */ - bool VMapManager2::getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist) - { - if (isLineOfSightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1); - Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2); - Vector3 resultPos; - bool result = instanceTree->second->getObjectHitPos(pos1, pos2, resultPos, modifyDist); - resultPos = convertPositionToInternalRep(resultPos.x, resultPos.y, resultPos.z); - rx = resultPos.x; - ry = resultPos.y; - rz = resultPos.z; - return result; - } - } - - rx = x2; - ry = y2; - rz = z2; - - return false; - } - - /** - get height or INVALID_HEIGHT if no height available - */ - - float VMapManager2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist) - { - if (isHeightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_HEIGHT)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos = convertPositionToInternalRep(x, y, z); - float height = instanceTree->second->getHeight(pos, maxSearchDist); - if (!(height < G3D::finf())) - return height = VMAP_INVALID_HEIGHT_VALUE; // No height - - return height; - } - } - - return VMAP_INVALID_HEIGHT_VALUE; - } - - bool VMapManager2::getAreaInfo(unsigned int mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const - { - if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos = convertPositionToInternalRep(x, y, z); - bool result = instanceTree->second->getAreaInfo(pos, flags, adtId, rootId, groupId); - // z is not touched by convertPositionToInternalRep(), so just copy - z = pos.z; - return result; - } - } - - return false; - } - - bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const - { - if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - LocationInfo info; - Vector3 pos = convertPositionToInternalRep(x, y, z); - if (instanceTree->second->GetLocationInfo(pos, info)) - { - floor = info.ground_Z; - ASSERT(floor < std::numeric_limits<float>::max()); - ASSERT(info.hitModel); - type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc - if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType)) - return false; - ASSERT(info.hitInstance); - if (info.hitInstance->GetLiquidLevel(pos, info, level)) - return true; - } - } - } - - return false; - } - - WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename) - { - //! Critical section, thread safe access to iLoadedModelFiles - std::lock_guard<std::mutex> lock(LoadedModelFilesLock); - - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); - if (model == iLoadedModelFiles.end()) - { - WorldModel* worldmodel = new WorldModel(); - if (!worldmodel->readFile(basepath + filename + ".vmo")) - { - VMAP_ERROR_LOG("misc", "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str()); - delete worldmodel; - return NULL; - } - VMAP_DEBUG_LOG("maps", "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); - model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first; - model->second.setModel(worldmodel); - } - model->second.incRefCount(); - return model->second.getModel(); - } - - void VMapManager2::releaseModelInstance(const std::string &filename) - { - //! Critical section, thread safe access to iLoadedModelFiles - std::lock_guard<std::mutex> lock(LoadedModelFilesLock); - - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); - if (model == iLoadedModelFiles.end()) - { - VMAP_ERROR_LOG("misc", "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str()); - return; - } - if (model->second.decRefCount() == 0) - { - VMAP_DEBUG_LOG("maps", "VMapManager2: unloading file '%s'", filename.c_str()); - delete model->second.getModel(); - iLoadedModelFiles.erase(model); - } - } - - bool VMapManager2::existsMap(const char* basePath, unsigned int mapId, int x, int y) - { - return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y); - } - -} // namespace VMAP diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h deleted file mode 100644 index a5891e9642b..00000000000 --- a/src/server/collision/Management/VMapManager2.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _VMAPMANAGER2_H -#define _VMAPMANAGER2_H - -#include <mutex> -#include <unordered_map> -#include <vector> -#include "Define.h" -#include "IVMapManager.h" - -//=========================================================== - -#define MAP_FILENAME_EXTENSION2 ".vmtree" - -#define FILENAMEBUFFER_SIZE 500 - -/** -This is the main Class to manage loading and unloading of maps, line of sight, height calculation and so on. -For each map or map tile to load it reads a directory file that contains the ModelContainer files used by this map or map tile. -Each global map or instance has its own dynamic BSP-Tree. -The loaded ModelContainers are included in one of these BSP-Trees. -Additionally a table to match map ids and map names is used. -*/ - -//=========================================================== - -namespace G3D -{ - class Vector3; -} - -namespace VMAP -{ - class StaticMapTree; - class WorldModel; - - class ManagedModel - { - public: - ManagedModel() : iModel(nullptr), iRefCount(0) { } - void setModel(WorldModel* model) { iModel = model; } - WorldModel* getModel() { return iModel; } - void incRefCount() { ++iRefCount; } - int decRefCount() { return --iRefCount; } - protected: - WorldModel* iModel; - int iRefCount; - }; - - typedef std::unordered_map<uint32, StaticMapTree*> InstanceTreeMap; - typedef std::unordered_map<std::string, ManagedModel> ModelFileMap; - - enum DisableTypes - { - VMAP_DISABLE_AREAFLAG = 0x1, - VMAP_DISABLE_HEIGHT = 0x2, - VMAP_DISABLE_LOS = 0x4, - VMAP_DISABLE_LIQUIDSTATUS = 0x8 - }; - - class VMapManager2 : public IVMapManager - { - protected: - // Tree to check collision - ModelFileMap iLoadedModelFiles; - InstanceTreeMap iInstanceMapTrees; - bool thread_safe_environment; - // Mutex for iLoadedModelFiles - std::mutex LoadedModelFilesLock; - - bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); - /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */ - - static uint32 GetLiquidFlagsDummy(uint32) { return 0; } - static bool IsVMAPDisabledForDummy(uint32 /*entry*/, uint8 /*flags*/) { return false; } - - InstanceTreeMap::const_iterator GetMapTree(uint32 mapId) const; - - public: - // public for debug - G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const; - static std::string getMapFileName(unsigned int mapId); - - VMapManager2(); - ~VMapManager2(void); - - void InitializeThreadUnsafe(const std::vector<uint32>& mapIds); - int loadMap(const char* pBasePath, unsigned int mapId, int x, int y) override; - - void unloadMap(unsigned int mapId, int x, int y) override; - void unloadMap(unsigned int mapId) override; - - bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) override ; - /** - fill the hit pos and return true, if an object was hit - */ - bool getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist) override; - float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist) override; - - bool processCommand(char* /*command*/) override { return false; } // for debug and extensions - - bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override; - bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const override; - - WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename); - void releaseModelInstance(const std::string& filename); - - // what's the use of this? o.O - virtual std::string getDirFileName(unsigned int mapId, int /*x*/, int /*y*/) const override - { - return getMapFileName(mapId); - } - virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y) override; - public: - void getInstanceMapTree(InstanceTreeMap &instanceMapTree); - - typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType); - GetLiquidFlagsFn GetLiquidFlagsPtr; - - typedef bool(*IsVMAPDisabledForFn)(uint32 entry, uint8 flags); - IsVMAPDisabledForFn IsVMAPDisabledForPtr; - }; -} - -#endif diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp deleted file mode 100644 index b493ec18f5f..00000000000 --- a/src/server/collision/Maps/MapTree.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "MapTree.h" -#include "ModelInstance.h" -#include "VMapManager2.h" -#include "VMapDefinitions.h" -#include "Log.h" -#include "Errors.h" - -#include <string> -#include <sstream> -#include <iomanip> -#include <limits> - -using G3D::Vector3; - -namespace VMAP -{ - - class MapRayCallback - { - public: - MapRayCallback(ModelInstance* val): prims(val), hit(false) { } - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true) - { - bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit); - if (result) - hit = true; - return result; - } - bool didHit() { return hit; } - protected: - ModelInstance* prims; - bool hit; - }; - - class AreaInfoCallback - { - public: - AreaInfoCallback(ModelInstance* val): prims(val) { } - void operator()(const Vector3& point, uint32 entry) - { -#ifdef VMAP_DEBUG - TC_LOG_DEBUG("maps", "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); -#endif - prims[entry].intersectPoint(point, aInfo); - } - - ModelInstance* prims; - AreaInfo aInfo; - }; - - class LocationInfoCallback - { - public: - LocationInfoCallback(ModelInstance* val, LocationInfo &info): prims(val), locInfo(info), result(false) { } - void operator()(const Vector3& point, uint32 entry) - { -#ifdef VMAP_DEBUG - TC_LOG_DEBUG("maps", "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); -#endif - if (prims[entry].GetLocationInfo(point, locInfo)) - result = true; - } - - ModelInstance* prims; - LocationInfo &locInfo; - bool result; - }; - - //========================================================= - - std::string StaticMapTree::getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY) - { - std::stringstream tilefilename; - tilefilename.fill('0'); - tilefilename << std::setw(3) << mapID << '_'; - //tilefilename << std::setw(2) << tileX << '_' << std::setw(2) << tileY << ".vmtile"; - tilefilename << std::setw(2) << tileY << '_' << std::setw(2) << tileX << ".vmtile"; - return tilefilename.str(); - } - - bool StaticMapTree::getAreaInfo(Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const - { - AreaInfoCallback intersectionCallBack(iTreeValues); - iTree.intersectPoint(pos, intersectionCallBack); - if (intersectionCallBack.aInfo.result) - { - flags = intersectionCallBack.aInfo.flags; - adtId = intersectionCallBack.aInfo.adtId; - rootId = intersectionCallBack.aInfo.rootId; - groupId = intersectionCallBack.aInfo.groupId; - pos.z = intersectionCallBack.aInfo.ground_Z; - return true; - } - return false; - } - - bool StaticMapTree::GetLocationInfo(const Vector3 &pos, LocationInfo &info) const - { - LocationInfoCallback intersectionCallBack(iTreeValues, info); - iTree.intersectPoint(pos, intersectionCallBack); - return intersectionCallBack.result; - } - - StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath) : - iMapID(mapID), iIsTiled(false), iTreeValues(NULL), - iNTreeValues(0), iBasePath(basePath) - { - if (iBasePath.length() > 0 && iBasePath[iBasePath.length()-1] != '/' && iBasePath[iBasePath.length()-1] != '\\') - { - iBasePath.push_back('/'); - } - } - - //========================================================= - //! Make sure to call unloadMap() to unregister acquired model references before destroying - StaticMapTree::~StaticMapTree() - { - delete[] iTreeValues; - } - - //========================================================= - /** - If intersection is found within pMaxDist, sets pMaxDist to intersection distance and returns true. - Else, pMaxDist is not modified and returns false; - */ - - bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const - { - float distance = pMaxDist; - MapRayCallback intersectionCallBack(iTreeValues); - iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit); - if (intersectionCallBack.didHit()) - pMaxDist = distance; - return intersectionCallBack.didHit(); - } - //========================================================= - - bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const - { - float maxDist = (pos2 - pos1).magnitude(); - // return false if distance is over max float, in case of cheater teleporting to the end of the universe - if (maxDist == std::numeric_limits<float>::max() || !std::isfinite(maxDist)) - return false; - - // valid map coords should *never ever* produce float overflow, but this would produce NaNs too - ASSERT(maxDist < std::numeric_limits<float>::max()); - // prevent NaN values which can cause BIH intersection to enter infinite loop - if (maxDist < 1e-10f) - return true; - // direction with length of 1 - G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist); - if (getIntersectionTime(ray, maxDist, true)) - return false; - - return true; - } - //========================================================= - /** - When moving from pos1 to pos2 check if we hit an object. Return true and the position if we hit one - Return the hit pos or the original dest pos - */ - - bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const - { - bool result=false; - float maxDist = (pPos2 - pPos1).magnitude(); - // valid map coords should *never ever* produce float overflow, but this would produce NaNs too - ASSERT(maxDist < std::numeric_limits<float>::max()); - // prevent NaN values which can cause BIH intersection to enter infinite loop - if (maxDist < 1e-10f) - { - pResultHitPos = pPos2; - return false; - } - Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1 - G3D::Ray ray(pPos1, dir); - float dist = maxDist; - if (getIntersectionTime(ray, dist, false)) - { - pResultHitPos = pPos1 + dir * dist; - if (pModifyDist < 0) - { - if ((pResultHitPos - pPos1).magnitude() > -pModifyDist) - { - pResultHitPos = pResultHitPos + dir*pModifyDist; - } - else - { - pResultHitPos = pPos1; - } - } - else - { - pResultHitPos = pResultHitPos + dir*pModifyDist; - } - result = true; - } - else - { - pResultHitPos = pPos2; - result = false; - } - return result; - } - - //========================================================= - - float StaticMapTree::getHeight(const Vector3& pPos, float maxSearchDist) const - { - float height = G3D::finf(); - Vector3 dir = Vector3(0, 0, -1); - G3D::Ray ray(pPos, dir); // direction with length of 1 - float maxDist = maxSearchDist; - if (getIntersectionTime(ray, maxDist, false)) - { - height = pPos.z - maxDist; - } - return(height); - } - - //========================================================= - - bool StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY) - { - std::string basePath = vmapPath; - if (basePath.length() > 0 && basePath[basePath.length()-1] != '/' && basePath[basePath.length()-1] != '\\') - basePath.push_back('/'); - std::string fullname = basePath + VMapManager2::getMapFileName(mapID); - bool success = true; - FILE* rf = fopen(fullname.c_str(), "rb"); - if (!rf) - return false; - /// @todo check magic number when implemented... - char tiled; - char chunk[8]; - if (!readChunk(rf, chunk, VMAP_MAGIC, 8) || fread(&tiled, sizeof(char), 1, rf) != 1) - { - fclose(rf); - return false; - } - if (tiled) - { - std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (!tf) - success = false; - else - { - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) - success = false; - fclose(tf); - } - } - fclose(rf); - return success; - } - - //========================================================= - - bool StaticMapTree::InitMap(const std::string &fname, VMapManager2* vm) - { - VMAP_DEBUG_LOG("maps", "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); - bool success = false; - std::string fullname = iBasePath + fname; - FILE* rf = fopen(fullname.c_str(), "rb"); - if (!rf) - return false; - - char chunk[8]; - char tiled = '\0'; - - if (readChunk(rf, chunk, VMAP_MAGIC, 8) && fread(&tiled, sizeof(char), 1, rf) == 1 && - readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf)) - { - iNTreeValues = iTree.primCount(); - iTreeValues = new ModelInstance[iNTreeValues]; - success = readChunk(rf, chunk, "GOBJ", 4); - } - - iIsTiled = tiled != '\0'; - - // global model spawns - // only non-tiled maps have them, and if so exactly one (so far at least...) - ModelSpawn spawn; -#ifdef VMAP_DEBUG - TC_LOG_DEBUG("maps", "StaticMapTree::InitMap() : map isTiled: %u", static_cast<uint32>(iIsTiled)); -#endif - if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) - { - WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); - VMAP_DEBUG_LOG("maps", "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); - if (model) - { - // assume that global model always is the first and only tree value (could be improved...) - iTreeValues[0] = ModelInstance(spawn, model); - iLoadedSpawns[0] = 1; - } - else - { - success = false; - VMAP_ERROR_LOG("misc", "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); - } - } - - fclose(rf); - return success; - } - - //========================================================= - - void StaticMapTree::UnloadMap(VMapManager2* vm) - { - for (loadedSpawnMap::iterator i = iLoadedSpawns.begin(); i != iLoadedSpawns.end(); ++i) - { - iTreeValues[i->first].setUnloaded(); - for (uint32 refCount = 0; refCount < i->second; ++refCount) - vm->releaseModelInstance(iTreeValues[i->first].name); - } - iLoadedSpawns.clear(); - iLoadedTiles.clear(); - } - - //========================================================= - - bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm) - { - if (!iIsTiled) - { - // currently, core creates grids for all maps, whether it has terrain tiles or not - // so we need "fake" tile loads to know when we can unload map geometry - iLoadedTiles[packTileID(tileX, tileY)] = false; - return true; - } - if (!iTreeValues) - { - VMAP_ERROR_LOG("misc", "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY); - return false; - } - bool result = true; - - std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (tf) - { - char chunk[8]; - - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) - result = false; - uint32 numSpawns = 0; - if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1) - result = false; - for (uint32 i=0; i<numSpawns && result; ++i) - { - // read model spawns - ModelSpawn spawn; - result = ModelSpawn::readFromFile(tf, spawn); - if (result) - { - // acquire model instance - WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); - if (!model) - VMAP_ERROR_LOG("misc", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); - - // update tree - uint32 referencedVal; - - if (fread(&referencedVal, sizeof(uint32), 1, tf) == 1) - { - if (!iLoadedSpawns.count(referencedVal)) - { - if (referencedVal > iNTreeValues) - { - VMAP_ERROR_LOG("maps", "StaticMapTree::LoadMapTile() : invalid tree element (%u/%u) referenced in tile %s", referencedVal, iNTreeValues, tilefile.c_str()); - continue; - } - - iTreeValues[referencedVal] = ModelInstance(spawn, model); - iLoadedSpawns[referencedVal] = 1; - } - else - { - ++iLoadedSpawns[referencedVal]; -#ifdef VMAP_DEBUG - if (iTreeValues[referencedVal].ID != spawn.ID) - TC_LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : trying to load wrong spawn in node"); - else if (iTreeValues[referencedVal].name != spawn.name) - TC_LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID); -#endif - } - } - else - result = false; - } - } - iLoadedTiles[packTileID(tileX, tileY)] = true; - fclose(tf); - } - else - iLoadedTiles[packTileID(tileX, tileY)] = false; - return result; - } - - //========================================================= - - void StaticMapTree::UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm) - { - uint32 tileID = packTileID(tileX, tileY); - loadedTileMap::iterator tile = iLoadedTiles.find(tileID); - if (tile == iLoadedTiles.end()) - { - VMAP_ERROR_LOG("misc", "StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY); - return; - } - if (tile->second) // file associated with tile - { - std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (tf) - { - bool result=true; - char chunk[8]; - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) - result = false; - uint32 numSpawns; - if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) - result = false; - for (uint32 i=0; i<numSpawns && result; ++i) - { - // read model spawns - ModelSpawn spawn; - result = ModelSpawn::readFromFile(tf, spawn); - if (result) - { - // release model instance - vm->releaseModelInstance(spawn.name); - - // update tree - uint32 referencedNode; - - if (fread(&referencedNode, sizeof(uint32), 1, tf) != 1) - result = false; - else - { - if (!iLoadedSpawns.count(referencedNode)) - VMAP_ERROR_LOG("misc", "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); - else if (--iLoadedSpawns[referencedNode] == 0) - { - iTreeValues[referencedNode].setUnloaded(); - iLoadedSpawns.erase(referencedNode); - } - } - } - } - fclose(tf); - } - } - iLoadedTiles.erase(tile); - } -} diff --git a/src/server/collision/Maps/MapTree.h b/src/server/collision/Maps/MapTree.h deleted file mode 100644 index 08bd5c3d3a1..00000000000 --- a/src/server/collision/Maps/MapTree.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _MAPTREE_H -#define _MAPTREE_H - -#include "Define.h" -#include "BoundingIntervalHierarchy.h" -#include <unordered_map> - -namespace VMAP -{ - class ModelInstance; - class GroupModel; - class VMapManager2; - - struct LocationInfo - { - LocationInfo(): hitInstance(nullptr), hitModel(nullptr), ground_Z(-G3D::finf()) { } - const ModelInstance* hitInstance; - const GroupModel* hitModel; - float ground_Z; - }; - - class StaticMapTree - { - typedef std::unordered_map<uint32, bool> loadedTileMap; - typedef std::unordered_map<uint32, uint32> loadedSpawnMap; - private: - uint32 iMapID; - bool iIsTiled; - BIH iTree; - ModelInstance* iTreeValues; // the tree entries - uint32 iNTreeValues; - - // Store all the map tile idents that are loaded for that map - // some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed - // empty tiles have no tile file, hence map with bool instead of just a set (consistency check) - loadedTileMap iLoadedTiles; - // stores <tree_index, reference_count> to invalidate tree values, unload map, and to be able to report errors - loadedSpawnMap iLoadedSpawns; - std::string iBasePath; - - private: - bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const; - //bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); } - public: - static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY); - static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX<<16 | tileY; } - static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY) { tileX = ID>>16; tileY = ID&0xFF; } - static bool CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY); - - StaticMapTree(uint32 mapID, const std::string &basePath); - ~StaticMapTree(); - - bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const; - bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const; - float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const; - bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; - bool GetLocationInfo(const G3D::Vector3 &pos, LocationInfo &info) const; - - bool InitMap(const std::string &fname, VMapManager2* vm); - void UnloadMap(VMapManager2* vm); - bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); - void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); - bool isTiled() const { return iIsTiled; } - uint32 numLoadedTiles() const { return iLoadedTiles.size(); } - void getModelInstances(ModelInstance* &models, uint32 &count); - - private: - StaticMapTree(StaticMapTree const& right) = delete; - StaticMapTree& operator=(StaticMapTree const& right) = delete; - }; - - struct AreaInfo - { - AreaInfo(): result(false), ground_Z(-G3D::finf()), flags(0), adtId(0), - rootId(0), groupId(0) { } - bool result; - float ground_Z; - uint32 flags; - int32 adtId; - int32 rootId; - int32 groupId; - }; -} // VMAP - -#endif // _MAPTREE_H diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp deleted file mode 100644 index ec7b759f975..00000000000 --- a/src/server/collision/Maps/TileAssembler.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "TileAssembler.h" -#include "MapTree.h" -#include "BoundingIntervalHierarchy.h" -#include "VMapDefinitions.h" - -#include <set> -#include <iomanip> -#include <sstream> - -using G3D::Vector3; -using G3D::AABox; -using G3D::inf; -using std::pair; - -template<> struct BoundsTrait<VMAP::ModelSpawn*> -{ - static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); } -}; - -namespace VMAP -{ - bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len) - { - if (fread(dest, sizeof(char), len, rf) != len) return false; - return memcmp(dest, compare, len) == 0; - } - - Vector3 ModelPosition::transform(const Vector3& pIn) const - { - Vector3 out = pIn * iScale; - out = iRotation * out; - return(out); - } - - //================================================================= - - TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName) - : iDestDir(pDestDirName), iSrcDir(pSrcDirName), iFilterMethod(NULL), iCurrentUniqueNameId(0) - { - //mkdir(iDestDir); - //init(); - } - - TileAssembler::~TileAssembler() - { - //delete iCoordModelMapping; - } - - bool TileAssembler::convertWorld2() - { - bool success = readMapSpawns(); - if (!success) - return false; - - // export Map data - for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter) - { - // build global map tree - std::vector<ModelSpawn*> mapSpawns; - UniqueEntryMap::iterator entry; - printf("Calculating model bounds for map %u...\n", map_iter->first); - for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry) - { - // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail - if (entry->second.flags & MOD_M2) - { - if (!calculateTransformedBound(entry->second)) - break; - } - else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ - { - /// @todo remove extractor hack and uncomment below line: - //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); - entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); - } - mapSpawns.push_back(&(entry->second)); - spawnedModelFiles.insert(entry->second.name); - } - - printf("Creating map tree for map %u...\n", map_iter->first); - BIH pTree; - - try - { - pTree.build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds); - } - catch (std::exception& e) - { - printf("Exception ""%s"" when calling pTree.build", e.what()); - return false; - } - - // ===> possibly move this code to StaticMapTree class - std::map<uint32, uint32> modelNodeIdx; - for (uint32 i=0; i<mapSpawns.size(); ++i) - modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i)); - - // write map tree file - std::stringstream mapfilename; - mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree"; - FILE* mapfile = fopen(mapfilename.str().c_str(), "wb"); - if (!mapfile) - { - success = false; - printf("Cannot open %s\n", mapfilename.str().c_str()); - break; - } - - //general info - if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false; - uint32 globalTileID = StaticMapTree::packTileID(65, 65); - pair<TileMap::iterator, TileMap::iterator> globalRange = map_iter->second->TileEntries.equal_range(globalTileID); - char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO - if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false; - // Nodes - if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false; - if (success) success = pTree.writeToFile(mapfile); - // global map spawns (WDT), if any (most instances) - if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false; - - for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob) - { - success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); - } - - fclose(mapfile); - - // <==== - - // write map tile files, similar to ADT files, only with extra BSP tree node info - TileMap &tileEntries = map_iter->second->TileEntries; - TileMap::iterator tile; - for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) - { - const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second]; - if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... - continue; - uint32 nSpawns = tileEntries.count(tile->first); - std::stringstream tilefilename; - tilefilename.fill('0'); - tilefilename << iDestDir << '/' << std::setw(3) << map_iter->first << '_'; - uint32 x, y; - StaticMapTree::unpackTileID(tile->first, x, y); - tilefilename << std::setw(2) << x << '_' << std::setw(2) << y << ".vmtile"; - if (FILE* tilefile = fopen(tilefilename.str().c_str(), "wb")) - { - // file header - if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) success = false; - // write number of tile spawns - if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; - // write tile spawns - for (uint32 s=0; s<nSpawns; ++s) - { - if (s) - ++tile; - const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second]; - success = success && ModelSpawn::writeToFile(tilefile, spawn2); - // MapTree nodes to update when loading tile: - std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID); - if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; - } - fclose(tilefile); - } - } - // break; //test, extract only first map; TODO: remvoe this line - } - - // add an object models, listed in temp_gameobject_models file - exportGameobjectModels(); - // export objects - std::cout << "\nConverting Model Files" << std::endl; - for (std::set<std::string>::iterator mfile = spawnedModelFiles.begin(); mfile != spawnedModelFiles.end(); ++mfile) - { - std::cout << "Converting " << *mfile << std::endl; - if (!convertRawFile(*mfile)) - { - std::cout << "error converting " << *mfile << std::endl; - success = false; - break; - } - } - - //cleanup: - for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end(); ++map_iter) - { - delete map_iter->second; - } - return success; - } - - bool TileAssembler::readMapSpawns() - { - std::string fname = iSrcDir + "/dir_bin"; - FILE* dirf = fopen(fname.c_str(), "rb"); - if (!dirf) - { - printf("Could not read dir_bin file!\n"); - return false; - } - printf("Read coordinate mapping...\n"); - uint32 mapID, tileX, tileY, check=0; - G3D::Vector3 v1, v2; - ModelSpawn spawn; - while (!feof(dirf)) - { - check = 0; - // read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name - check += fread(&mapID, sizeof(uint32), 1, dirf); - if (check == 0) // EoF... - break; - check += fread(&tileX, sizeof(uint32), 1, dirf); - check += fread(&tileY, sizeof(uint32), 1, dirf); - if (!ModelSpawn::readFromFile(dirf, spawn)) - break; - - MapSpawns *current; - MapData::iterator map_iter = mapData.find(mapID); - if (map_iter == mapData.end()) - { - printf("spawning Map %u\n", mapID); - mapData[mapID] = current = new MapSpawns(); - } - else current = (*map_iter).second; - current->UniqueEntries.insert(pair<uint32, ModelSpawn>(spawn.ID, spawn)); - current->TileEntries.insert(pair<uint32, uint32>(StaticMapTree::packTileID(tileX, tileY), spawn.ID)); - } - bool success = (ferror(dirf) == 0); - fclose(dirf); - return success; - } - - bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) - { - std::string modelFilename(iSrcDir); - modelFilename.push_back('/'); - modelFilename.append(spawn.name); - - ModelPosition modelPosition; - modelPosition.iDir = spawn.iRot; - modelPosition.iScale = spawn.iScale; - modelPosition.init(); - - WorldModel_Raw raw_model; - if (!raw_model.Read(modelFilename.c_str())) - return false; - - uint32 groups = raw_model.groupsArray.size(); - if (groups != 1) - printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); - - AABox modelBound; - bool boundEmpty=true; - - for (uint32 g=0; g<groups; ++g) // should be only one for M2 files... - { - std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray; - - if (vertices.empty()) - { - std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl; - continue; - } - - uint32 nvectors = vertices.size(); - for (uint32 i = 0; i < nvectors; ++i) - { - Vector3 v = modelPosition.transform(vertices[i]); - - if (boundEmpty) - modelBound = AABox(v, v), boundEmpty=false; - else - modelBound.merge(v); - } - } - spawn.iBound = modelBound + spawn.iPos; - spawn.flags |= MOD_HAS_BOUND; - return true; - } - - struct WMOLiquidHeader - { - int xverts, yverts, xtiles, ytiles; - float pos_x; - float pos_y; - float pos_z; - short type; - }; - //================================================================= - bool TileAssembler::convertRawFile(const std::string& pModelFilename) - { - bool success = true; - std::string filename = iSrcDir; - if (filename.length() >0) - filename.push_back('/'); - filename.append(pModelFilename); - - WorldModel_Raw raw_model; - if (!raw_model.Read(filename.c_str())) - return false; - - // write WorldModel - WorldModel model; - model.setRootWmoID(raw_model.RootWMOID); - if (!raw_model.groupsArray.empty()) - { - std::vector<GroupModel> groupsArray; - - uint32 groups = raw_model.groupsArray.size(); - for (uint32 g = 0; g < groups; ++g) - { - GroupModel_Raw& raw_group = raw_model.groupsArray[g]; - groupsArray.push_back(GroupModel(raw_group.mogpflags, raw_group.GroupWMOID, raw_group.bounds )); - groupsArray.back().setMeshData(raw_group.vertexArray, raw_group.triangles); - groupsArray.back().setLiquidData(raw_group.liquid); - } - - model.setGroupModels(groupsArray); - } - - success = model.writeFile(iDestDir + "/" + pModelFilename + ".vmo"); - //std::cout << "readRawFile2: '" << pModelFilename << "' tris: " << nElements << " nodes: " << nNodes << std::endl; - return success; - } - - void TileAssembler::exportGameobjectModels() - { - FILE* model_list = fopen((iSrcDir + "/" + "temp_gameobject_models").c_str(), "rb"); - if (!model_list) - return; - - FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb"); - if (!model_list_copy) - { - fclose(model_list); - return; - } - - uint32 name_length, displayId; - char buff[500]; - while (!feof(model_list)) - { - if (fread(&displayId, sizeof(uint32), 1, model_list) != 1 - || fread(&name_length, sizeof(uint32), 1, model_list) != 1 - || name_length >= sizeof(buff) - || fread(&buff, sizeof(char), name_length, model_list) != name_length) - { - std::cout << "\nFile 'temp_gameobject_models' seems to be corrupted" << std::endl; - break; - } - - std::string model_name(buff, name_length); - - WorldModel_Raw raw_model; - if ( !raw_model.Read((iSrcDir + "/" + model_name).c_str()) ) - continue; - - spawnedModelFiles.insert(model_name); - AABox bounds; - bool boundEmpty = true; - for (uint32 g = 0; g < raw_model.groupsArray.size(); ++g) - { - std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray; - - uint32 nvectors = vertices.size(); - for (uint32 i = 0; i < nvectors; ++i) - { - Vector3& v = vertices[i]; - if (boundEmpty) - bounds = AABox(v, v), boundEmpty = false; - else - bounds.merge(v); - } - } - - if (bounds.isEmpty()) - { - std::cout << "\nModel " << std::string(buff, name_length) << " has empty bounding box" << std::endl; - continue; - } - - if (!bounds.isFinite()) - { - std::cout << "\nModel " << std::string(buff, name_length) << " has invalid bounding box" << std::endl; - continue; - } - - fwrite(&displayId, sizeof(uint32), 1, model_list_copy); - fwrite(&name_length, sizeof(uint32), 1, model_list_copy); - fwrite(&buff, sizeof(char), name_length, model_list_copy); - fwrite(&bounds.low(), sizeof(Vector3), 1, model_list_copy); - fwrite(&bounds.high(), sizeof(Vector3), 1, model_list_copy); - } - - fclose(model_list); - fclose(model_list_copy); - } - // temporary use defines to simplify read/check code (close file and return at fail) - #define READ_OR_RETURN(V, S) if (fread((V), (S), 1, rf) != 1) { \ - fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); } - #define READ_OR_RETURN_WITH_DELETE(V, S) if (fread((V), (S), 1, rf) != 1) { \ - fclose(rf); printf("readfail, op = %i\n", readOperation); delete[] V; return(false); }; - #define CMP_OR_RETURN(V, S) if (strcmp((V), (S)) != 0) { \ - fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } - - bool GroupModel_Raw::Read(FILE* rf) - { - char blockId[5]; - blockId[4] = 0; - int blocksize; - int readOperation = 0; - - READ_OR_RETURN(&mogpflags, sizeof(uint32)); - READ_OR_RETURN(&GroupWMOID, sizeof(uint32)); - - - Vector3 vec1, vec2; - READ_OR_RETURN(&vec1, sizeof(Vector3)); - - READ_OR_RETURN(&vec2, sizeof(Vector3)); - bounds.set(vec1, vec2); - - READ_OR_RETURN(&liquidflags, sizeof(uint32)); - - // will this ever be used? what is it good for anyway?? - uint32 branches; - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "GRP "); - READ_OR_RETURN(&blocksize, sizeof(int)); - READ_OR_RETURN(&branches, sizeof(uint32)); - for (uint32 b=0; b<branches; ++b) - { - uint32 indexes; - // indexes for each branch (not used jet) - READ_OR_RETURN(&indexes, sizeof(uint32)); - } - - // ---- indexes - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "INDX"); - READ_OR_RETURN(&blocksize, sizeof(int)); - uint32 nindexes; - READ_OR_RETURN(&nindexes, sizeof(uint32)); - if (nindexes >0) - { - uint16 *indexarray = new uint16[nindexes]; - READ_OR_RETURN_WITH_DELETE(indexarray, nindexes*sizeof(uint16)); - triangles.reserve(nindexes / 3); - for (uint32 i=0; i<nindexes; i+=3) - triangles.push_back(MeshTriangle(indexarray[i], indexarray[i+1], indexarray[i+2])); - - delete[] indexarray; - } - - // ---- vectors - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "VERT"); - READ_OR_RETURN(&blocksize, sizeof(int)); - uint32 nvectors; - READ_OR_RETURN(&nvectors, sizeof(uint32)); - - if (nvectors >0) - { - float *vectorarray = new float[nvectors*3]; - READ_OR_RETURN_WITH_DELETE(vectorarray, nvectors*sizeof(float)*3); - for (uint32 i=0; i<nvectors; ++i) - vertexArray.push_back( Vector3(vectorarray + 3*i) ); - - delete[] vectorarray; - } - // ----- liquid - liquid = 0; - if (liquidflags& 1) - { - WMOLiquidHeader hlq; - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "LIQU"); - READ_OR_RETURN(&blocksize, sizeof(int)); - READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader)); - liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type); - uint32 size = hlq.xverts*hlq.yverts; - READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float)); - size = hlq.xtiles*hlq.ytiles; - READ_OR_RETURN(liquid->GetFlagsStorage(), size); - } - - return true; - } - - - GroupModel_Raw::~GroupModel_Raw() - { - delete liquid; - } - - bool WorldModel_Raw::Read(const char * path) - { - FILE* rf = fopen(path, "rb"); - if (!rf) - { - printf("ERROR: Can't open raw model file: %s\n", path); - return false; - } - - char ident[9]; - ident[8] = '\0'; - int readOperation = 0; - - READ_OR_RETURN(&ident, 8); - CMP_OR_RETURN(ident, RAW_VMAP_MAGIC); - - // we have to read one int. This is needed during the export and we have to skip it here - uint32 tempNVectors; - READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); - - uint32 groups; - READ_OR_RETURN(&groups, sizeof(uint32)); - READ_OR_RETURN(&RootWMOID, sizeof(uint32)); - - groupsArray.resize(groups); - bool succeed = true; - for (uint32 g = 0; g < groups && succeed; ++g) - succeed = groupsArray[g].Read(rf); - - if (succeed) /// rf will be freed inside Read if the function had any errors. - fclose(rf); - return succeed; - } - - // drop of temporary use defines - #undef READ_OR_RETURN - #undef CMP_OR_RETURN -} diff --git a/src/server/collision/Maps/TileAssembler.h b/src/server/collision/Maps/TileAssembler.h deleted file mode 100644 index 581622c6b73..00000000000 --- a/src/server/collision/Maps/TileAssembler.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _TILEASSEMBLER_H_ -#define _TILEASSEMBLER_H_ - -#include <G3D/Vector3.h> -#include <G3D/Matrix3.h> -#include <map> -#include <set> - -#include "ModelInstance.h" -#include "WorldModel.h" - -namespace VMAP -{ - /** - This Class is used to convert raw vector data into balanced BSP-Trees. - To start the conversion call convertWorld(). - */ - //=============================================== - - class ModelPosition - { - private: - G3D::Matrix3 iRotation; - public: - ModelPosition(): iScale(0.0f) { } - G3D::Vector3 iPos; - G3D::Vector3 iDir; - float iScale; - void init() - { - iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iDir.y/180.f, G3D::pif()*iDir.x/180.f, G3D::pif()*iDir.z/180.f); - } - G3D::Vector3 transform(const G3D::Vector3& pIn) const; - void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; } - }; - - typedef std::map<uint32, ModelSpawn> UniqueEntryMap; - typedef std::multimap<uint32, uint32> TileMap; - - struct MapSpawns - { - UniqueEntryMap UniqueEntries; - TileMap TileEntries; - }; - - typedef std::map<uint32, MapSpawns*> MapData; - //=============================================== - - struct GroupModel_Raw - { - uint32 mogpflags; - uint32 GroupWMOID; - - G3D::AABox bounds; - uint32 liquidflags; - std::vector<MeshTriangle> triangles; - std::vector<G3D::Vector3> vertexArray; - class WmoLiquid* liquid; - - GroupModel_Raw() : mogpflags(0), GroupWMOID(0), liquidflags(0), - liquid(NULL) { } - ~GroupModel_Raw(); - - bool Read(FILE* f); - }; - - struct WorldModel_Raw - { - uint32 RootWMOID; - std::vector<GroupModel_Raw> groupsArray; - - bool Read(const char * path); - }; - - class TileAssembler - { - private: - std::string iDestDir; - std::string iSrcDir; - bool (*iFilterMethod)(char *pName); - G3D::Table<std::string, unsigned int > iUniqueNameIds; - unsigned int iCurrentUniqueNameId; - MapData mapData; - std::set<std::string> spawnedModelFiles; - - public: - TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName); - virtual ~TileAssembler(); - - bool convertWorld2(); - bool readMapSpawns(); - bool calculateTransformedBound(ModelSpawn &spawn); - void exportGameobjectModels(); - - bool convertRawFile(const std::string& pModelFilename); - void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; } - std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName); - }; - -} // VMAP -#endif /*_TILEASSEMBLER_H_*/ diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp deleted file mode 100644 index dbdc0554e06..00000000000 --- a/src/server/collision/Models/GameObjectModel.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "VMapFactory.h" -#include "VMapManager2.h" -#include "VMapDefinitions.h" -#include "WorldModel.h" -#include "GameObjectModel.h" -#include "Log.h" -#include "Timer.h" - -using G3D::Vector3; -using G3D::Ray; -using G3D::AABox; - -struct GameobjectModelData -{ - GameobjectModelData(const std::string& name_, const AABox& box) : - bound(box), name(name_) { } - - AABox bound; - std::string name; -}; - -typedef std::unordered_map<uint32, GameobjectModelData> ModelList; -ModelList model_list; - -void LoadGameObjectModelList(std::string const& dataPath) -{ -#ifndef NO_CORE_FUNCS - uint32 oldMSTime = getMSTime(); -#endif - - FILE* model_list_file = fopen((dataPath + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb"); - if (!model_list_file) - { - VMAP_ERROR_LOG("misc", "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS); - return; - } - - uint32 name_length, displayId; - char buff[500]; - while (true) - { - Vector3 v1, v2; - if (fread(&displayId, sizeof(uint32), 1, model_list_file) != 1) - if (feof(model_list_file)) // EOF flag is only set after failed reading attempt - break; - - if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1 - || name_length >= sizeof(buff) - || fread(&buff, sizeof(char), name_length, model_list_file) != name_length - || fread(&v1, sizeof(Vector3), 1, model_list_file) != 1 - || fread(&v2, sizeof(Vector3), 1, model_list_file) != 1) - { - VMAP_ERROR_LOG("misc", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS); - break; - } - - if (v1.isNaN() || v2.isNaN()) - { - VMAP_ERROR_LOG("misc", "File '%s' Model '%s' has invalid v1%s v2%s values!", VMAP::GAMEOBJECT_MODELS, std::string(buff, name_length).c_str(), v1.toString().c_str(), v2.toString().c_str()); - continue; - } - - model_list.insert - ( - ModelList::value_type(displayId, GameobjectModelData(std::string(buff, name_length), AABox(v1, v2))) - ); - } - - fclose(model_list_file); - VMAP_INFO_LOG("server.loading", ">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime)); -} - -GameObjectModel::~GameObjectModel() -{ - if (iModel) - ((VMAP::VMapManager2*)VMAP::VMapFactory::createOrGetVMapManager())->releaseModelInstance(name); -} - -bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath) -{ - ModelList::const_iterator it = model_list.find(modelOwner->GetDisplayId()); - if (it == model_list.end()) - return false; - - G3D::AABox mdl_box(it->second.bound); - // ignore models with no bounds - if (mdl_box == G3D::AABox::zero()) - { - VMAP_ERROR_LOG("misc", "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str()); - return false; - } - - iModel = ((VMAP::VMapManager2*)VMAP::VMapFactory::createOrGetVMapManager())->acquireModelInstance(dataPath + "vmaps/", it->second.name); - - if (!iModel) - return false; - - name = it->second.name; - iPos = modelOwner->GetPosition(); - phasemask = modelOwner->GetPhaseMask(); - iScale = modelOwner->GetScale(); - iInvScale = 1.f / iScale; - - G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(modelOwner->GetOrientation(), 0, 0); - iInvRot = iRotation.inverse(); - // transform bounding box: - mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale); - AABox rotated_bounds; - for (int i = 0; i < 8; ++i) - rotated_bounds.merge(iRotation * mdl_box.corner(i)); - - iBound = rotated_bounds + iPos; -#ifdef SPAWN_CORNERS - // test: - for (int i = 0; i < 8; ++i) - { - Vector3 pos(iBound.corner(i)); - modelOwner->DebugVisualizeCorner(pos); - } -#endif - - owner = std::move(modelOwner); - return true; -} - -GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath) -{ - GameObjectModel* mdl = new GameObjectModel(); - if (!mdl->initialize(std::move(modelOwner), dataPath)) - { - delete mdl; - return NULL; - } - - return mdl; -} - -bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const -{ - if (!(phasemask & ph_mask) || !owner->IsSpawned()) - return false; - - float time = ray.intersectionTime(iBound); - if (time == G3D::finf()) - return false; - - // child bounds are defined in object space: - Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale; - Ray modRay(p, iInvRot * ray.direction()); - float distance = MaxDist * iInvScale; - bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit); - if (hit) - { - distance *= iScale; - MaxDist = distance; - } - return hit; -} - -bool GameObjectModel::UpdatePosition() -{ - if (!iModel) - return false; - - ModelList::const_iterator it = model_list.find(owner->GetDisplayId()); - if (it == model_list.end()) - return false; - - G3D::AABox mdl_box(it->second.bound); - // ignore models with no bounds - if (mdl_box == G3D::AABox::zero()) - { - VMAP_ERROR_LOG("misc", "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str()); - return false; - } - - iPos = owner->GetPosition(); - - G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(owner->GetOrientation(), 0, 0); - iInvRot = iRotation.inverse(); - // transform bounding box: - mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale); - AABox rotated_bounds; - for (int i = 0; i < 8; ++i) - rotated_bounds.merge(iRotation * mdl_box.corner(i)); - - iBound = rotated_bounds + iPos; -#ifdef SPAWN_CORNERS - // test: - for (int i = 0; i < 8; ++i) - { - Vector3 pos(iBound.corner(i)); - owner->DebugVisualizeCorner(pos); - } -#endif - - return true; -} diff --git a/src/server/collision/Models/GameObjectModel.h b/src/server/collision/Models/GameObjectModel.h deleted file mode 100644 index 17669189af5..00000000000 --- a/src/server/collision/Models/GameObjectModel.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _GAMEOBJECT_MODEL_H -#define _GAMEOBJECT_MODEL_H - -#include <G3D/Matrix3.h> -#include <G3D/Vector3.h> -#include <G3D/AABox.h> -#include <G3D/Ray.h> - -#include "Define.h" -#include <memory> - -namespace VMAP -{ - class WorldModel; -} - -class GameObject; -struct GameObjectDisplayInfoEntry; - -class GameObjectModelOwnerBase -{ -public: - virtual bool IsSpawned() const { return false; } - virtual uint32 GetDisplayId() const { return 0; } - virtual uint32 GetPhaseMask() const { return 0; } - virtual G3D::Vector3 GetPosition() const { return G3D::Vector3::zero(); } - virtual float GetOrientation() const { return 0.0f; } - virtual float GetScale() const { return 1.0f; } - virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const { } -}; - -class GameObjectModel /*, public Intersectable*/ -{ - GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(NULL) { } -public: - std::string name; - - const G3D::AABox& getBounds() const { return iBound; } - - ~GameObjectModel(); - - const G3D::Vector3& getPosition() const { return iPos;} - - /** Enables\disables collision. */ - void disable() { phasemask = 0;} - void enable(uint32 ph_mask) { phasemask = ph_mask;} - - bool isEnabled() const {return phasemask != 0;} - - bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const; - - static GameObjectModel* Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath); - - bool UpdatePosition(); - -private: - bool initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath); - - uint32 phasemask; - G3D::AABox iBound; - G3D::Matrix3 iInvRot; - G3D::Vector3 iPos; - float iInvScale; - float iScale; - VMAP::WorldModel* iModel; - std::unique_ptr<GameObjectModelOwnerBase> owner; -}; - -#endif // _GAMEOBJECT_MODEL_H diff --git a/src/server/collision/Models/ModelInstance.cpp b/src/server/collision/Models/ModelInstance.cpp deleted file mode 100644 index 45440a99666..00000000000 --- a/src/server/collision/Models/ModelInstance.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ModelInstance.h" -#include "WorldModel.h" -#include "MapTree.h" - -using G3D::Vector3; -using G3D::Ray; - -namespace VMAP -{ - ModelInstance::ModelInstance(const ModelSpawn &spawn, WorldModel* model): ModelSpawn(spawn), iModel(model) - { - iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iRot.y/180.f, G3D::pif()*iRot.x/180.f, G3D::pif()*iRot.z/180.f).inverse(); - iInvScale = 1.f/iScale; - } - - bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const - { - if (!iModel) - { - //std::cout << "<object not loaded>\n"; - return false; - } - float time = pRay.intersectionTime(iBound); - if (time == G3D::finf()) - { -// std::cout << "Ray does not hit '" << name << "'\n"; - - return false; - } -// std::cout << "Ray crosses bound of '" << name << "'\n"; -/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z - << " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z - << " t/tmax:" << time << '/' << pMaxDist; - std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: " - << iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */ - // child bounds are defined in object space: - Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale; - Ray modRay(p, iInvRot * pRay.direction()); - float distance = pMaxDist * iInvScale; - bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit); - if (hit) - { - distance *= iScale; - pMaxDist = distance; - } - return hit; - } - - void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const - { - if (!iModel) - { -#ifdef VMAP_DEBUG - std::cout << "<object not loaded>\n"; -#endif - return; - } - - // M2 files don't contain area info, only WMO files - if (flags & MOD_M2) - return; - if (!iBound.contains(p)) - return; - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (iModel->IntersectPoint(pModel, zDirModel, zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - // Transform back to world space. Note that: - // Mat * vec == vec * Mat.transpose() - // and for rotation matrices: Mat.inverse() == Mat.transpose() - float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; - if (info.ground_Z < world_Z) - { - info.ground_Z = world_Z; - info.adtId = adtId; - } - } - } - - bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const - { - if (!iModel) - { -#ifdef VMAP_DEBUG - std::cout << "<object not loaded>\n"; -#endif - return false; - } - - // M2 files don't contain area info, only WMO files - if (flags & MOD_M2) - return false; - if (!iBound.contains(p)) - return false; - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - // Transform back to world space. Note that: - // Mat * vec == vec * Mat.transpose() - // and for rotation matrices: Mat.inverse() == Mat.transpose() - float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; - if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection? - { - info.ground_Z = world_Z; - info.hitInstance = this; - return true; - } - } - return false; - } - - bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const - { - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (info.hitModel->GetLiquidLevel(pModel, zDist)) - { - // calculate world height (zDist in model coords): - // assume WMO not tilted (wouldn't make much sense anyway) - liqHeight = zDist * iScale + iPos.z; - return true; - } - return false; - } - - bool ModelSpawn::readFromFile(FILE* rf, ModelSpawn &spawn) - { - uint32 check = 0, nameLen; - check += fread(&spawn.flags, sizeof(uint32), 1, rf); - // EoF? - if (!check) - { - if (ferror(rf)) - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - check += fread(&spawn.adtId, sizeof(uint16), 1, rf); - check += fread(&spawn.ID, sizeof(uint32), 1, rf); - check += fread(&spawn.iPos, sizeof(float), 3, rf); - check += fread(&spawn.iRot, sizeof(float), 3, rf); - check += fread(&spawn.iScale, sizeof(float), 1, rf); - bool has_bound = (spawn.flags & MOD_HAS_BOUND) != 0; - if (has_bound) // only WMOs have bound in MPQ, only available after computation - { - Vector3 bLow, bHigh; - check += fread(&bLow, sizeof(float), 3, rf); - check += fread(&bHigh, sizeof(float), 3, rf); - spawn.iBound = G3D::AABox(bLow, bHigh); - } - check += fread(&nameLen, sizeof(uint32), 1, rf); - if (check != uint32(has_bound ? 17 : 11)) - { - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - char nameBuff[500]; - if (nameLen > 500) // file names should never be that long, must be file error - { - std::cout << "Error reading ModelSpawn, file name too long!\n"; - return false; - } - check = fread(nameBuff, sizeof(char), nameLen, rf); - if (check != nameLen) - { - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - spawn.name = std::string(nameBuff, nameLen); - return true; - } - - bool ModelSpawn::writeToFile(FILE* wf, const ModelSpawn &spawn) - { - uint32 check=0; - check += fwrite(&spawn.flags, sizeof(uint32), 1, wf); - check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf); - check += fwrite(&spawn.ID, sizeof(uint32), 1, wf); - check += fwrite(&spawn.iPos, sizeof(float), 3, wf); - check += fwrite(&spawn.iRot, sizeof(float), 3, wf); - check += fwrite(&spawn.iScale, sizeof(float), 1, wf); - bool has_bound = (spawn.flags & MOD_HAS_BOUND) != 0; - if (has_bound) // only WMOs have bound in MPQ, only available after computation - { - check += fwrite(&spawn.iBound.low(), sizeof(float), 3, wf); - check += fwrite(&spawn.iBound.high(), sizeof(float), 3, wf); - } - uint32 nameLen = spawn.name.length(); - check += fwrite(&nameLen, sizeof(uint32), 1, wf); - if (check != uint32(has_bound ? 17 : 11)) return false; - check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf); - if (check != nameLen) return false; - return true; - } - -} diff --git a/src/server/collision/Models/ModelInstance.h b/src/server/collision/Models/ModelInstance.h deleted file mode 100644 index dfdb001db0a..00000000000 --- a/src/server/collision/Models/ModelInstance.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _MODELINSTANCE_H_ -#define _MODELINSTANCE_H_ - -#include <G3D/Matrix3.h> -#include <G3D/Vector3.h> -#include <G3D/AABox.h> -#include <G3D/Ray.h> - -#include "Define.h" - -namespace VMAP -{ - class WorldModel; - struct AreaInfo; - struct LocationInfo; - - enum ModelFlags - { - MOD_M2 = 1, - MOD_WORLDSPAWN = 1<<1, - MOD_HAS_BOUND = 1<<2 - }; - - class ModelSpawn - { - public: - //mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name - uint32 flags; - uint16 adtId; - uint32 ID; - G3D::Vector3 iPos; - G3D::Vector3 iRot; - float iScale; - G3D::AABox iBound; - std::string name; - bool operator==(const ModelSpawn &other) const { return ID == other.ID; } - //uint32 hashCode() const { return ID; } - // temp? - const G3D::AABox& getBounds() const { return iBound; } - - static bool readFromFile(FILE* rf, ModelSpawn &spawn); - static bool writeToFile(FILE* rw, const ModelSpawn &spawn); - }; - - class ModelInstance: public ModelSpawn - { - public: - ModelInstance(): iInvScale(0.0f), iModel(nullptr) { } - ModelInstance(const ModelSpawn &spawn, WorldModel* model); - void setUnloaded() { iModel = nullptr; } - bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const; - void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const; - bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const; - bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const; - protected: - G3D::Matrix3 iInvRot; - float iInvScale; - WorldModel* iModel; - public: - WorldModel* getWorldModel(); - }; -} // namespace VMAP - -#endif // _MODELINSTANCE diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp deleted file mode 100644 index 86ab9366c71..00000000000 --- a/src/server/collision/Models/WorldModel.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "WorldModel.h" -#include "VMapDefinitions.h" -#include "MapTree.h" - -using G3D::Vector3; -using G3D::Ray; - -template<> struct BoundsTrait<VMAP::GroupModel> -{ - static void getBounds(const VMAP::GroupModel& obj, G3D::AABox& out) { out = obj.GetBound(); } -}; - -namespace VMAP -{ - bool IntersectTriangle(const MeshTriangle &tri, std::vector<Vector3>::const_iterator points, const G3D::Ray &ray, float &distance) - { - static const float EPS = 1e-5f; - - // See RTR2 ch. 13.7 for the algorithm. - - const Vector3 e1 = points[tri.idx1] - points[tri.idx0]; - const Vector3 e2 = points[tri.idx2] - points[tri.idx0]; - const Vector3 p(ray.direction().cross(e2)); - const float a = e1.dot(p); - - if (std::fabs(a) < EPS) { - // Determinant is ill-conditioned; abort early - return false; - } - - const float f = 1.0f / a; - const Vector3 s(ray.origin() - points[tri.idx0]); - const float u = f * s.dot(p); - - if ((u < 0.0f) || (u > 1.0f)) { - // We hit the plane of the m_geometry, but outside the m_geometry - return false; - } - - const Vector3 q(s.cross(e1)); - const float v = f * ray.direction().dot(q); - - if ((v < 0.0f) || ((u + v) > 1.0f)) { - // We hit the plane of the triangle, but outside the triangle - return false; - } - - const float t = f * e2.dot(q); - - if ((t > 0.0f) && (t < distance)) - { - // This is a new hit, closer than the previous one - distance = t; - - /* baryCoord[0] = 1.0 - u - v; - baryCoord[1] = u; - baryCoord[2] = v; */ - - return true; - } - // This hit is after the previous hit, so ignore it - return false; - } - - class TriBoundFunc - { - public: - TriBoundFunc(std::vector<Vector3> &vert): vertices(vert.begin()) { } - void operator()(const MeshTriangle &tri, G3D::AABox &out) const - { - G3D::Vector3 lo = vertices[tri.idx0]; - G3D::Vector3 hi = lo; - - lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]); - hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]); - - out = G3D::AABox(lo, hi); - } - protected: - const std::vector<Vector3>::const_iterator vertices; - }; - - // ===================== WmoLiquid ================================== - - WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type): - iTilesX(width), iTilesY(height), iCorner(corner), iType(type) - { - iHeight = new float[(width+1)*(height+1)]; - iFlags = new uint8[width*height]; - } - - WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(nullptr), iFlags(nullptr) - { - *this = other; // use assignment operator... - } - - WmoLiquid::~WmoLiquid() - { - delete[] iHeight; - delete[] iFlags; - } - - WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other) - { - if (this == &other) - return *this; - iTilesX = other.iTilesX; - iTilesY = other.iTilesY; - iCorner = other.iCorner; - iType = other.iType; - delete iHeight; - delete iFlags; - if (other.iHeight) - { - iHeight = new float[(iTilesX+1)*(iTilesY+1)]; - memcpy(iHeight, other.iHeight, (iTilesX+1)*(iTilesY+1)*sizeof(float)); - } - else - iHeight = nullptr; - if (other.iFlags) - { - iFlags = new uint8[iTilesX * iTilesY]; - memcpy(iFlags, other.iFlags, iTilesX * iTilesY); - } - else - iFlags = nullptr; - return *this; - } - - bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const - { - float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE; - uint32 tx = uint32(tx_f); - if (tx_f < 0.0f || tx >= iTilesX) - return false; - float ty_f = (pos.y - iCorner.y)/LIQUID_TILE_SIZE; - uint32 ty = uint32(ty_f); - if (ty_f < 0.0f || ty >= iTilesY) - return false; - - // check if tile shall be used for liquid level - // checking for 0x08 *might* be enough, but disabled tiles always are 0x?F: - if ((iFlags[tx + ty*iTilesX] & 0x0F) == 0x0F) - return false; - - // (dx, dy) coordinates inside tile, in [0, 1]^2 - float dx = tx_f - (float)tx; - float dy = ty_f - (float)ty; - - /* Tesselate tile to two triangles (not sure if client does it exactly like this) - - ^ dy - | - 1 x---------x (1, 1) - | (b) / | - | / | - | / | - | / (a) | - x---------x---> dx - 0 1 - */ - - const uint32 rowOffset = iTilesX + 1; - if (dx > dy) // case (a) - { - float sx = iHeight[tx+1 + ty * rowOffset] - iHeight[tx + ty * rowOffset]; - float sy = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx+1 + ty * rowOffset]; - liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy; - } - else // case (b) - { - float sx = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx + (ty+1) * rowOffset]; - float sy = iHeight[tx + (ty+1) * rowOffset] - iHeight[tx + ty * rowOffset]; - liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy; - } - return true; - } - - uint32 WmoLiquid::GetFileSize() - { - return 2 * sizeof(uint32) + - sizeof(Vector3) + - (iTilesX + 1)*(iTilesY + 1) * sizeof(float) + - iTilesX * iTilesY; - } - - bool WmoLiquid::writeToFile(FILE* wf) - { - bool result = false; - if (fwrite(&iTilesX, sizeof(uint32), 1, wf) == 1 && - fwrite(&iTilesY, sizeof(uint32), 1, wf) == 1 && - fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 && - fwrite(&iType, sizeof(uint32), 1, wf) == 1) - { - uint32 size = (iTilesX + 1) * (iTilesY + 1); - if (fwrite(iHeight, sizeof(float), size, wf) == size) - { - size = iTilesX*iTilesY; - result = fwrite(iFlags, sizeof(uint8), size, wf) == size; - } - } - - return result; - } - - bool WmoLiquid::readFromFile(FILE* rf, WmoLiquid* &out) - { - bool result = false; - WmoLiquid* liquid = new WmoLiquid(); - - if (fread(&liquid->iTilesX, sizeof(uint32), 1, rf) == 1 && - fread(&liquid->iTilesY, sizeof(uint32), 1, rf) == 1 && - fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 && - fread(&liquid->iType, sizeof(uint32), 1, rf) == 1) - { - uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1); - liquid->iHeight = new float[size]; - if (fread(liquid->iHeight, sizeof(float), size, rf) == size) - { - size = liquid->iTilesX * liquid->iTilesY; - liquid->iFlags = new uint8[size]; - result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size; - } - } - - if (!result) - delete liquid; - else - out = liquid; - - return result; - } - - // ===================== GroupModel ================================== - - GroupModel::GroupModel(const GroupModel &other): - iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID), - vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(nullptr) - { - if (other.iLiquid) - iLiquid = new WmoLiquid(*other.iLiquid); - } - - void GroupModel::setMeshData(std::vector<Vector3> &vert, std::vector<MeshTriangle> &tri) - { - vertices.swap(vert); - triangles.swap(tri); - TriBoundFunc bFunc(vertices); - meshTree.build(triangles, bFunc); - } - - bool GroupModel::writeToFile(FILE* wf) - { - bool result = true; - uint32 chunkSize, count; - - if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) result = false; - if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) result = false; - - // write vertices - if (result && fwrite("VERT", 1, 4, wf) != 4) result = false; - count = vertices.size(); - chunkSize = sizeof(uint32)+ sizeof(Vector3)*count; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - if (!count) // models without (collision) geometry end here, unsure if they are useful - return result; - if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) result = false; - - // write triangle mesh - if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false; - count = triangles.size(); - chunkSize = sizeof(uint32)+ sizeof(MeshTriangle)*count; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false; - - // write mesh BIH - if (result && fwrite("MBIH", 1, 4, wf) != 4) result = false; - if (result) result = meshTree.writeToFile(wf); - - // write liquid data - if (result && fwrite("LIQU", 1, 4, wf) != 4) result = false; - if (!iLiquid) - { - chunkSize = 0; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - return result; - } - chunkSize = iLiquid->GetFileSize(); - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result) result = iLiquid->writeToFile(wf); - - return result; - } - - bool GroupModel::readFromFile(FILE* rf) - { - char chunk[8]; - bool result = true; - uint32 chunkSize = 0; - uint32 count = 0; - triangles.clear(); - vertices.clear(); - delete iLiquid; - iLiquid = NULL; - - if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false; - if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) result = false; - - // read vertices - if (result && !readChunk(rf, chunk, "VERT", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; - if (!count) // models without (collision) geometry end here, unsure if they are useful - return result; - if (result) vertices.resize(count); - if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) result = false; - - // read triangle mesh - if (result && !readChunk(rf, chunk, "TRIM", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; - if (result) triangles.resize(count); - if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) result = false; - - // read mesh BIH - if (result && !readChunk(rf, chunk, "MBIH", 4)) result = false; - if (result) result = meshTree.readFromFile(rf); - - // write liquid data - if (result && !readChunk(rf, chunk, "LIQU", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && chunkSize > 0) - result = WmoLiquid::readFromFile(rf, iLiquid); - return result; - } - - struct GModelRayCallback - { - GModelRayCallback(const std::vector<MeshTriangle> &tris, const std::vector<Vector3> &vert): - vertices(vert.begin()), triangles(tris.begin()), hit(false) { } - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool /*pStopAtFirstHit*/) - { - bool result = IntersectTriangle(triangles[entry], vertices, ray, distance); - if (result) hit=true; - return hit; - } - std::vector<Vector3>::const_iterator vertices; - std::vector<MeshTriangle>::const_iterator triangles; - bool hit; - }; - - bool GroupModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const - { - if (triangles.empty()) - return false; - - GModelRayCallback callback(triangles, vertices); - meshTree.intersectRay(ray, callback, distance, stopAtFirstHit); - return callback.hit; - } - - bool GroupModel::IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const - { - if (triangles.empty() || !iBound.contains(pos)) - return false; - GModelRayCallback callback(triangles, vertices); - Vector3 rPos = pos - 0.1f * down; - float dist = G3D::finf(); - G3D::Ray ray(rPos, down); - bool hit = IntersectRay(ray, dist, false); - if (hit) - z_dist = dist - 0.1f; - return hit; - } - - bool GroupModel::GetLiquidLevel(const Vector3 &pos, float &liqHeight) const - { - if (iLiquid) - return iLiquid->GetLiquidHeight(pos, liqHeight); - return false; - } - - uint32 GroupModel::GetLiquidType() const - { - if (iLiquid) - return iLiquid->GetType(); - return 0; - } - - // ===================== WorldModel ================================== - - void WorldModel::setGroupModels(std::vector<GroupModel> &models) - { - groupModels.swap(models); - groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1); - } - - struct WModelRayCallBack - { - WModelRayCallBack(const std::vector<GroupModel> &mod): models(mod.begin()), hit(false) { } - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit) - { - bool result = models[entry].IntersectRay(ray, distance, pStopAtFirstHit); - if (result) hit=true; - return hit; - } - std::vector<GroupModel>::const_iterator models; - bool hit; - }; - - bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const - { - // small M2 workaround, maybe better make separate class with virtual intersection funcs - // in any case, there's no need to use a bound tree if we only have one submodel - if (groupModels.size() == 1) - return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit); - - WModelRayCallBack isc(groupModels); - groupTree.intersectRay(ray, isc, distance, stopAtFirstHit); - return isc.hit; - } - - class WModelAreaCallback { - public: - WModelAreaCallback(const std::vector<GroupModel> &vals, const Vector3 &down): - prims(vals.begin()), hit(vals.end()), minVol(G3D::finf()), zDist(G3D::finf()), zVec(down) { } - std::vector<GroupModel>::const_iterator prims; - std::vector<GroupModel>::const_iterator hit; - float minVol; - float zDist; - Vector3 zVec; - void operator()(const Vector3& point, uint32 entry) - { - float group_Z; - //float pVol = prims[entry].GetBound().volume(); - //if (pVol < minVol) - //{ - /* if (prims[entry].iBound.contains(point)) */ - if (prims[entry].IsInsideObject(point, zVec, group_Z)) - { - //minVol = pVol; - //hit = prims + entry; - if (group_Z < zDist) - { - zDist = group_Z; - hit = prims + entry; - } -#ifdef VMAP_DEBUG - const GroupModel &gm = prims[entry]; - printf("%10u %8X %7.3f, %7.3f, %7.3f | %7.3f, %7.3f, %7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(), - gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z, - gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z); -#endif - } - //} - //std::cout << "trying to intersect '" << prims[entry].name << "'\n"; - } - }; - - bool WorldModel::IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const - { - if (groupModels.empty()) - return false; - - WModelAreaCallback callback(groupModels, down); - groupTree.intersectPoint(p, callback); - if (callback.hit != groupModels.end()) - { - info.rootId = RootWMOID; - info.groupId = callback.hit->GetWmoID(); - info.flags = callback.hit->GetMogpFlags(); - info.result = true; - dist = callback.zDist; - return true; - } - return false; - } - - bool WorldModel::GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const - { - if (groupModels.empty()) - return false; - - WModelAreaCallback callback(groupModels, down); - groupTree.intersectPoint(p, callback); - if (callback.hit != groupModels.end()) - { - info.hitModel = &(*callback.hit); - dist = callback.zDist; - return true; - } - return false; - } - - bool WorldModel::writeFile(const std::string &filename) - { - FILE* wf = fopen(filename.c_str(), "wb"); - if (!wf) - return false; - - uint32 chunkSize, count; - bool result = fwrite(VMAP_MAGIC, 1, 8, wf) == 8; - if (result && fwrite("WMOD", 1, 4, wf) != 4) result = false; - chunkSize = sizeof(uint32) + sizeof(uint32); - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false; - - // write group models - count=groupModels.size(); - if (count) - { - if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false; - //chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count; - //if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - for (uint32 i=0; i<groupModels.size() && result; ++i) - result = groupModels[i].writeToFile(wf); - - // write group BIH - if (result && fwrite("GBIH", 1, 4, wf) != 4) result = false; - if (result) result = groupTree.writeToFile(wf); - } - - fclose(wf); - return result; - } - - bool WorldModel::readFile(const std::string &filename) - { - FILE* rf = fopen(filename.c_str(), "rb"); - if (!rf) - return false; - - bool result = true; - uint32 chunkSize = 0; - uint32 count = 0; - char chunk[8]; // Ignore the added magic header - if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) result = false; - - if (result && !readChunk(rf, chunk, "WMOD", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&RootWMOID, sizeof(uint32), 1, rf) != 1) result = false; - - // read group models - if (result && readChunk(rf, chunk, "GMOD", 4)) - { - //if (fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - - if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; - if (result) groupModels.resize(count); - //if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false; - for (uint32 i=0; i<count && result; ++i) - result = groupModels[i].readFromFile(rf); - - // read group BIH - if (result && !readChunk(rf, chunk, "GBIH", 4)) result = false; - if (result) result = groupTree.readFromFile(rf); - } - - fclose(rf); - return result; - } -} diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h deleted file mode 100644 index 6a901a59fdf..00000000000 --- a/src/server/collision/Models/WorldModel.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _WORLDMODEL_H -#define _WORLDMODEL_H - -#include <G3D/HashTrait.h> -#include <G3D/Vector3.h> -#include <G3D/AABox.h> -#include <G3D/Ray.h> -#include "BoundingIntervalHierarchy.h" - -#include "Define.h" - -namespace VMAP -{ - class TreeNode; - struct AreaInfo; - struct LocationInfo; - - class MeshTriangle - { - public: - MeshTriangle() : idx0(0), idx1(0), idx2(0) { } - MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) { } - - uint32 idx0; - uint32 idx1; - uint32 idx2; - }; - - class WmoLiquid - { - public: - WmoLiquid(uint32 width, uint32 height, const G3D::Vector3 &corner, uint32 type); - WmoLiquid(const WmoLiquid &other); - ~WmoLiquid(); - WmoLiquid& operator=(const WmoLiquid &other); - bool GetLiquidHeight(const G3D::Vector3 &pos, float &liqHeight) const; - uint32 GetType() const { return iType; } - float *GetHeightStorage() { return iHeight; } - uint8 *GetFlagsStorage() { return iFlags; } - uint32 GetFileSize(); - bool writeToFile(FILE* wf); - static bool readFromFile(FILE* rf, WmoLiquid* &liquid); - private: - WmoLiquid() : iTilesX(0), iTilesY(0), iCorner(), iType(0), iHeight(NULL), iFlags(NULL) { } - uint32 iTilesX; //!< number of tiles in x direction, each - uint32 iTilesY; - G3D::Vector3 iCorner; //!< the lower corner - uint32 iType; //!< liquid type - float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values - uint8 *iFlags; //!< info if liquid tile is used - public: - void getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const; - }; - - /*! holding additional info for WMO group files */ - class GroupModel - { - public: - GroupModel() : iBound(), iMogpFlags(0), iGroupWMOID(0), iLiquid(NULL) { } - GroupModel(const GroupModel &other); - GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox &bound): - iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(NULL) { } - ~GroupModel() { delete iLiquid; } - - //! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry! - void setMeshData(std::vector<G3D::Vector3> &vert, std::vector<MeshTriangle> &tri); - void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = NULL; } - bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; - bool IsInsideObject(const G3D::Vector3 &pos, const G3D::Vector3 &down, float &z_dist) const; - bool GetLiquidLevel(const G3D::Vector3 &pos, float &liqHeight) const; - uint32 GetLiquidType() const; - bool writeToFile(FILE* wf); - bool readFromFile(FILE* rf); - const G3D::AABox& GetBound() const { return iBound; } - uint32 GetMogpFlags() const { return iMogpFlags; } - uint32 GetWmoID() const { return iGroupWMOID; } - protected: - G3D::AABox iBound; - uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor - uint32 iGroupWMOID; - std::vector<G3D::Vector3> vertices; - std::vector<MeshTriangle> triangles; - BIH meshTree; - WmoLiquid* iLiquid; - public: - void getMeshData(std::vector<G3D::Vector3> &vertices, std::vector<MeshTriangle> &triangles, WmoLiquid* &liquid); - }; - /*! Holds a model (converted M2 or WMO) in its original coordinate space */ - class WorldModel - { - public: - WorldModel(): RootWMOID(0) { } - - //! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry! - void setGroupModels(std::vector<GroupModel> &models); - void setRootWmoID(uint32 id) { RootWMOID = id; } - bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; - bool IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const; - bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const; - bool writeFile(const std::string &filename); - bool readFile(const std::string &filename); - protected: - uint32 RootWMOID; - std::vector<GroupModel> groupModels; - BIH groupTree; - public: - void getGroupModels(std::vector<GroupModel> &groupModels); - }; -} // namespace VMAP - -#endif // _WORLDMODEL_H diff --git a/src/server/collision/PrecompiledHeaders/collisionPCH.cpp b/src/server/collision/PrecompiledHeaders/collisionPCH.cpp deleted file mode 100644 index 36eae8e2b0d..00000000000 --- a/src/server/collision/PrecompiledHeaders/collisionPCH.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "collisionPCH.h" diff --git a/src/server/collision/PrecompiledHeaders/collisionPCH.h b/src/server/collision/PrecompiledHeaders/collisionPCH.h deleted file mode 100644 index ece2ef1b8ef..00000000000 --- a/src/server/collision/PrecompiledHeaders/collisionPCH.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "Define.h" -#include "VMapDefinitions.h" -#include "MapTree.h" -#include "WorldModel.h" -#include "ModelInstance.h" -#include "BoundingIntervalHierarchy.h" -#include "RegularGrid.h" -#include "BoundingIntervalHierarchyWrapper.h" -#include "GameObjectModel.h" diff --git a/src/server/collision/RegularGrid.h b/src/server/collision/RegularGrid.h deleted file mode 100644 index 6a2a07968ad..00000000000 --- a/src/server/collision/RegularGrid.h +++ /dev/null @@ -1,212 +0,0 @@ -#ifndef _REGULAR_GRID_H -#define _REGULAR_GRID_H - - -#include <G3D/Ray.h> -#include <G3D/Table.h> -#include <G3D/BoundsTrait.h> -#include <G3D/PositionTrait.h> - -#include "Errors.h" - -template<class Node> -struct NodeCreator{ - static Node * makeNode(int /*x*/, int /*y*/) { return new Node();} -}; - -template<class T, -class Node, -class NodeCreatorFunc = NodeCreator<Node>, - /*class BoundsFunc = BoundsTrait<T>,*/ -class PositionFunc = PositionTrait<T> -> -class RegularGrid2D -{ -public: - - enum{ - CELL_NUMBER = 64, - }; - - #define HGRID_MAP_SIZE (533.33333f * 64.f) // shouldn't be changed - #define CELL_SIZE float(HGRID_MAP_SIZE/(float)CELL_NUMBER) - - typedef G3D::Table<const T*, Node*> MemberTable; - - MemberTable memberTable; - Node* nodes[CELL_NUMBER][CELL_NUMBER]; - - RegularGrid2D(){ - memset(nodes, 0, sizeof(nodes)); - } - - ~RegularGrid2D(){ - for (int x = 0; x < CELL_NUMBER; ++x) - for (int y = 0; y < CELL_NUMBER; ++y) - delete nodes[x][y]; - } - - void insert(const T& value) - { - G3D::Vector3 pos; - PositionFunc::getPosition(value, pos); - Node& node = getGridFor(pos.x, pos.y); - node.insert(value); - memberTable.set(&value, &node); - } - - void remove(const T& value) - { - memberTable[&value]->remove(value); - // Remove the member - memberTable.remove(&value); - } - - void balance() - { - for (int x = 0; x < CELL_NUMBER; ++x) - for (int y = 0; y < CELL_NUMBER; ++y) - if (Node* n = nodes[x][y]) - n->balance(); - } - - bool contains(const T& value) const { return memberTable.containsKey(&value); } - int size() const { return memberTable.size(); } - - struct Cell - { - int x, y; - bool operator == (const Cell& c2) const { return x == c2.x && y == c2.y;} - - static Cell ComputeCell(float fx, float fy) - { - Cell c = { int(fx * (1.f/CELL_SIZE) + (CELL_NUMBER/2)), int(fy * (1.f/CELL_SIZE) + (CELL_NUMBER/2)) }; - return c; - } - - bool isValid() const { return x >= 0 && x < CELL_NUMBER && y >= 0 && y < CELL_NUMBER;} - }; - - - Node& getGridFor(float fx, float fy) - { - Cell c = Cell::ComputeCell(fx, fy); - return getGrid(c.x, c.y); - } - - Node& getGrid(int x, int y) - { - ASSERT(x < CELL_NUMBER && y < CELL_NUMBER); - if (!nodes[x][y]) - nodes[x][y] = NodeCreatorFunc::makeNode(x, y); - return *nodes[x][y]; - } - - template<typename RayCallback> - void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float max_dist) - { - intersectRay(ray, intersectCallback, max_dist, ray.origin() + ray.direction() * max_dist); - } - - template<typename RayCallback> - void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& max_dist, const G3D::Vector3& end) - { - Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y); - if (!cell.isValid()) - return; - - Cell last_cell = Cell::ComputeCell(end.x, end.y); - - if (cell == last_cell) - { - if (Node* node = nodes[cell.x][cell.y]) - node->intersectRay(ray, intersectCallback, max_dist); - return; - } - - float voxel = (float)CELL_SIZE; - float kx_inv = ray.invDirection().x, bx = ray.origin().x; - float ky_inv = ray.invDirection().y, by = ray.origin().y; - - int stepX, stepY; - float tMaxX, tMaxY; - if (kx_inv >= 0) - { - stepX = 1; - float x_border = (cell.x+1) * voxel; - tMaxX = (x_border - bx) * kx_inv; - } - else - { - stepX = -1; - float x_border = (cell.x-1) * voxel; - tMaxX = (x_border - bx) * kx_inv; - } - - if (ky_inv >= 0) - { - stepY = 1; - float y_border = (cell.y+1) * voxel; - tMaxY = (y_border - by) * ky_inv; - } - else - { - stepY = -1; - float y_border = (cell.y-1) * voxel; - tMaxY = (y_border - by) * ky_inv; - } - - //int Cycles = std::max((int)ceilf(max_dist/tMaxX),(int)ceilf(max_dist/tMaxY)); - //int i = 0; - - float tDeltaX = voxel * std::fabs(kx_inv); - float tDeltaY = voxel * std::fabs(ky_inv); - do - { - if (Node* node = nodes[cell.x][cell.y]) - { - //float enterdist = max_dist; - node->intersectRay(ray, intersectCallback, max_dist); - } - if (cell == last_cell) - break; - if (tMaxX < tMaxY) - { - tMaxX += tDeltaX; - cell.x += stepX; - } - else - { - tMaxY += tDeltaY; - cell.y += stepY; - } - //++i; - } while (cell.isValid()); - } - - template<typename IsectCallback> - void intersectPoint(const G3D::Vector3& point, IsectCallback& intersectCallback) - { - Cell cell = Cell::ComputeCell(point.x, point.y); - if (!cell.isValid()) - return; - if (Node* node = nodes[cell.x][cell.y]) - node->intersectPoint(point, intersectCallback); - } - - // Optimized verson of intersectRay function for rays with vertical directions - template<typename RayCallback> - void intersectZAllignedRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& max_dist) - { - Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y); - if (!cell.isValid()) - return; - if (Node* node = nodes[cell.x][cell.y]) - node->intersectRay(ray, intersectCallback, max_dist); - } -}; - -#undef CELL_SIZE -#undef HGRID_MAP_SIZE - -#endif diff --git a/src/server/collision/VMapDefinitions.h b/src/server/collision/VMapDefinitions.h deleted file mode 100644 index 1035d5307cc..00000000000 --- a/src/server/collision/VMapDefinitions.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _VMAPDEFINITIONS_H -#define _VMAPDEFINITIONS_H -#include <cstring> -#include <cstdio> - -#define LIQUID_TILE_SIZE (533.333f / 128.f) - -namespace VMAP -{ - const char VMAP_MAGIC[] = "VMAP_4.1"; - const char RAW_VMAP_MAGIC[] = "VMAP041"; // used in extracted vmap files with raw data - const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; - - // defined in TileAssembler.cpp currently... - bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len); -} - -// Set of helper macros for extractors (VMAP and MMAP) -#ifndef NO_CORE_FUNCS -#define VMAP_ERROR_LOG(FILTER, ...) TC_LOG_ERROR(FILTER, __VA_ARGS__) -#define VMAP_DEBUG_LOG(FILTER, ...) TC_LOG_DEBUG(FILTER, __VA_ARGS__) -#define VMAP_INFO_LOG(FILTER, ...) TC_LOG_INFO(FILTER, __VA_ARGS__) -#else -#define VMAP_ERROR_LOG(FILTER, ...) (void)sizeof(FILTER) -#define VMAP_DEBUG_LOG(FILTER, ...) (void)sizeof(FILTER) -#define VMAP_INFO_LOG(FILTER, ...) (void)sizeof(FILTER) -#endif - -#endif diff --git a/src/server/collision/VMapTools.h b/src/server/collision/VMapTools.h deleted file mode 100644 index fa7bc394ebc..00000000000 --- a/src/server/collision/VMapTools.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _VMAPTOOLS_H -#define _VMAPTOOLS_H - -#include <G3D/CollisionDetection.h> -#include <G3D/AABox.h> - -#include "NodeValueAccess.h" - -/** -The Class is mainly taken from G3D/AABSPTree.h but modified to be able to use our internal data structure. -This is an iterator that helps us analysing the BSP-Trees. -The collision detection is modified to return true, if we are inside an object. -*/ - -namespace VMAP -{ - template<class TValue> - class IntersectionCallBack { - public: - TValue* closestEntity; - G3D::Vector3 hitLocation; - G3D::Vector3 hitNormal; - - void operator()(const G3D::Ray& ray, const TValue* entity, bool pStopAtFirstHit, float& distance) { - entity->intersect(ray, distance, pStopAtFirstHit, hitLocation, hitNormal); - } - }; - - //============================================================== - //============================================================== - //============================================================== - - class MyCollisionDetection - { - private: - public: - - static bool collisionLocationForMovingPointFixedAABox( - const G3D::Vector3& origin, - const G3D::Vector3& dir, - const G3D::AABox& box, - G3D::Vector3& location, - bool& Inside) - { - - // Integer representation of a floating-point value. -#define IR(x) (reinterpret_cast<G3D::uint32 const&>(x)) - - Inside = true; - const G3D::Vector3& MinB = box.low(); - const G3D::Vector3& MaxB = box.high(); - G3D::Vector3 MaxT(-1.0f, -1.0f, -1.0f); - - // Find candidate planes. - for (int i = 0; i < 3; ++i) - { - if (origin[i] < MinB[i]) - { - location[i] = MinB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) - { - MaxT[i] = (MinB[i] - origin[i]) / dir[i]; - } - } - else if (origin[i] > MaxB[i]) - { - location[i] = MaxB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) - { - MaxT[i] = (MaxB[i] - origin[i]) / dir[i]; - } - } - } - - if (Inside) - { - // definite hit - location = origin; - return true; - } - - // Get largest of the maxT's for final choice of intersection - int WhichPlane = 0; - if (MaxT[1] > MaxT[WhichPlane]) - { - WhichPlane = 1; - } - - if (MaxT[2] > MaxT[WhichPlane]) - { - WhichPlane = 2; - } - - // Check final candidate actually inside box - if (IR(MaxT[WhichPlane]) & 0x80000000) - { - // Miss the box - return false; - } - - for (int i = 0; i < 3; ++i) - { - if (i != WhichPlane) - { - location[i] = origin[i] + MaxT[WhichPlane] * dir[i]; - if ((location[i] < MinB[i]) || - (location[i] > MaxB[i])) - { - // On this plane we're outside the box extents, so - // we miss the box - return false; - } - } - } - /* - // Choose the normal to be the plane normal facing into the ray - normal = G3D::Vector3::zero(); - normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0; - */ - return true; - -#undef IR - } - }; -} -#endif |
