From 1f66d719f2cbbcb144b5080c89dd73fcae261798 Mon Sep 17 00:00:00 2001 From: StormBytePP Date: Sat, 15 Aug 2015 02:19:10 +0200 Subject: Core/BuildSystem: Merge collision, debugging, threading, utilities and configuration into "common" which does not depend on shared anymore and moved database out of shared library These changes enables to build tools only without even having MySQL installed --- src/common/Collision/Models/GameObjectModel.cpp | 216 ++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 src/common/Collision/Models/GameObjectModel.cpp (limited to 'src/common/Collision/Models/GameObjectModel.cpp') diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp new file mode 100644 index 00000000000..dbdc0554e06 --- /dev/null +++ b/src/common/Collision/Models/GameObjectModel.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2005-2009 MaNGOS + * + * 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 . + */ + +#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 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 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 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; +} -- cgit v1.2.3