diff options
author | Yehonal <yehonal.azeroth@gmail.com> | 2017-12-20 20:48:35 +0100 |
---|---|---|
committer | Yehonal <yehonal.azeroth@gmail.com> | 2017-12-21 00:20:29 +0100 |
commit | 17332304fdf129076d0196010602350d5750c808 (patch) | |
tree | d161f8845df9e5c8ec0b149bd846646c2b112d49 /src/common/Collision/Models/ModelInstance.cpp | |
parent | 0fc4a6a153ca3a09ccb6e1311131b12a59c6cba3 (diff) |
Using TC structure allowing easier patches importing
Diffstat (limited to 'src/common/Collision/Models/ModelInstance.cpp')
-rw-r--r-- | src/common/Collision/Models/ModelInstance.cpp | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/common/Collision/Models/ModelInstance.cpp b/src/common/Collision/Models/ModelInstance.cpp new file mode 100644 index 0000000000..18faf11e5d --- /dev/null +++ b/src/common/Collision/Models/ModelInstance.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license: http://github.com/azerothcore/azerothcore-wotlk/LICENSE-GPL2 + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + */ + +#include "ModelInstance.h" +#include "WorldModel.h" +#include "MapTree.h" +#include "VMapDefinitions.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::pi()*iRot.y/180.f, G3D::pi()*iRot.x/180.f, G3D::pi()*iRot.z/180.f).inverse(); + iInvScale = 1.f/iScale; + } + + bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const + { + if (!iModel) + { + //std::cout << "<object not loaded>\n"; + return false; + } + float time = pRay.intersectionTime(iBound); + if (time == G3D::inf()) + { +// 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, StopAtFirstHit); + 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); + 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); + 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; + } + +} |