From 664e8175bf76e7a8b5cdb19d179a0ef5a0767dc9 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Fri, 13 Sep 2019 19:15:25 +0100 Subject: [PATCH] Dynamic objects now working Code needs cleaning up though, and replacing Vector with LVector, and adding culling for dynamics. --- SCsub | 3 +- lbitfield_dynamic.cpp | 93 +++++++++++++ lbitfield_dynamic.h | 91 +++++++++++++ ldob.cpp | 2 + ldob.h | 9 ++ lportal.cpp | 16 ++- lportal.h | 6 +- lroom.cpp | 188 ++++++++++++++++++++++++-- lroom.h | 21 ++- lroom_manager.cpp | 302 ++++++++++++++++++++++++++++++++++++++---- lroom_manager.h | 65 ++++++++- lvector.h | 4 +- 12 files changed, 749 insertions(+), 51 deletions(-) create mode 100644 lbitfield_dynamic.cpp create mode 100644 lbitfield_dynamic.h create mode 100644 ldob.cpp create mode 100644 ldob.h diff --git a/SCsub b/SCsub index b8f8f4e..892ae70 100644 --- a/SCsub +++ b/SCsub @@ -7,7 +7,8 @@ sources = [ "lroom_manager.cpp", "lportal.cpp", "lplanes_pool.cpp", - "CoBitField_Dynamic.cpp", + "ldob.cpp", + "lbitfield_dynamic.cpp", ] module_env = env.Clone() diff --git a/lbitfield_dynamic.cpp b/lbitfield_dynamic.cpp new file mode 100644 index 0000000..d149839 --- /dev/null +++ b/lbitfield_dynamic.cpp @@ -0,0 +1,93 @@ +#include "lbitfield_dynamic.h" + +#include + + +namespace Lawn { // namespace start + +void LBitField_Dynamic::Initialize() {assert (0 && "LBitField_Dynamic : Does not support Initialize, use IT version");} +void LBitField_Dynamic::Terminate() {assert (0 && "LBitField_Dynamic : Does not support Terminate, use IT version");} + + +void LBitField_Dynamic_IT::Initialize() +{ + Initialize_Do(); +} + +void LBitField_Dynamic_IT::Terminate() +{ + Terminate_Do(); +} + + +void LBitField_Dynamic_IT::Initialize_Do() +{ + memset (this, 0, sizeof (LBitField_Dynamic)); +} + +void LBitField_Dynamic_IT::Terminate_Do() +{ + Destroy(); +} + +void LBitField_Dynamic_IT::CopyFrom(const LBitField_Dynamic_IT &source) +{ + Create(source.GetNumBits(), false); + memcpy(m_pucData, source.GetData(), source.GetNumBytes()); +} + + +void LBitField_Dynamic_IT::Create(unsigned int uiNumBits, bool bBlank) +{ + // first delete any initial + Destroy(); + + m_uiNumBits = uiNumBits; + if (uiNumBits) + { + m_uiNumBytes = (uiNumBits / 8) + 1; + + m_pucData = new unsigned char[m_uiNumBytes]; + + if (bBlank) + Blank(false); + } +} + +void LBitField_Dynamic_IT::Destroy() +{ + if (m_pucData) + { + delete[] m_pucData; + m_pucData = 0; + } + + memset (this, 0, sizeof (LBitField_Dynamic)); +} + + +void LBitField_Dynamic_IT::Blank(bool bSetOrZero) +{ + if (bSetOrZero) + { + memset(m_pucData, 255, m_uiNumBytes); + } + else + { + memset(m_pucData, 0, m_uiNumBytes); + } +} + +void LBitField_Dynamic_IT::Invert() +{ + for (unsigned int n=0; n + +namespace Lawn { // namespace start + +class LBitField_Dynamic_IT +{ +public: + // construction + void Initialize(); + void Terminate(); + +private: + // prevent copying (see effective C++ scott meyers) + // there is no implementation for copy constructor, hence compiler will complain if you try to copy. + LBitField_Dynamic_IT& operator=(const LBitField_Dynamic_IT&); +public: + + // create automatically blanks + void Create(unsigned int uiNumBits, bool bBlank = true); + void Destroy(); + + // public funcs + inline unsigned int GetNumBits() const {return m_uiNumBits;} + inline unsigned int GetBit(unsigned int uiBit) const; + inline void SetBit(unsigned int uiBit, unsigned int bSet); + void Blank(bool bSetOrZero = false); + void Invert(); + void CopyFrom(const LBitField_Dynamic_IT &source); + + // loading / saving + unsigned char * GetData() {return m_pucData;} + const unsigned char * GetData() const {return m_pucData;} + unsigned int GetNumBytes() const {return m_uiNumBytes;} + +protected: + // member funcs + void Initialize_Do(); + void Terminate_Do(); + + // member vars + unsigned char * m_pucData; + unsigned int m_uiNumBytes; + unsigned int m_uiNumBits; +}; + +class LBitField_Dynamic : public LBitField_Dynamic_IT +{ +public: + // call initialize and terminate automatically + LBitField_Dynamic(unsigned int uiNumBits) {Initialize_Do(); Create(uiNumBits);} + LBitField_Dynamic() {Initialize_Do();} + ~LBitField_Dynamic() {Terminate_Do();} + + // disallow explicit calls + void Initialize(); + void Terminate(); +}; + + +////////////////////////////////////////////////////////// +inline unsigned int LBitField_Dynamic_IT::GetBit(unsigned int uiBit) const +{ + assert (m_pucData); + unsigned int uiByteNumber = uiBit >> 3; // divide by 8 + assert (uiByteNumber < m_uiNumBytes); + unsigned char uc = m_pucData[uiByteNumber]; + unsigned int uiBitSet = uc & (1 << (uiBit & 7)); + return uiBitSet; +} + +inline void LBitField_Dynamic_IT::SetBit(unsigned int uiBit, unsigned int bSet) +{ + assert (m_pucData); + unsigned int uiByteNumber = uiBit >> 3; // divide by 8 + assert (uiByteNumber < m_uiNumBytes); + unsigned char uc = m_pucData[uiByteNumber]; + unsigned int uiMask = 1 << (uiBit & 7); + if (bSet) + { + uc = uc | uiMask; + } + else + { + uc &= ~uiMask; + } + m_pucData[uiByteNumber] = uc; +} + +} // namespace end diff --git a/ldob.cpp b/ldob.cpp new file mode 100644 index 0000000..0e94b1d --- /dev/null +++ b/ldob.cpp @@ -0,0 +1,2 @@ +#include "ldob.h" + diff --git a/ldob.h b/ldob.h new file mode 100644 index 0000000..3c063d5 --- /dev/null +++ b/ldob.h @@ -0,0 +1,9 @@ +#pragma once + +#include "scene/3d/spatial.h" + +class LDob +{ +public: + ObjectID m_ID; +}; diff --git a/lportal.cpp b/lportal.cpp index 97e95f8..885d9fc 100644 --- a/lportal.cpp +++ b/lportal.cpp @@ -22,11 +22,21 @@ #include "core/engine.h" #include "lroom.h" + +bool LPortal::m_bRunning = false; + void LPortal::print(String sz) { -// print_line(sz); + if (m_bRunning) + { + } + else + { + print_line(sz); + } } + bool LPortal::NameStartsWith(Node * pNode, String szSearch) { int sl = szSearch.length(); @@ -99,7 +109,7 @@ LPortal::eClipResult LPortal::ClipWithPlane(const Plane &p) const { float d = p.distance_to(m_ptsWorld[n]); - if (d >= 0.0) + if (d >= 0.0f) nOutside++; } @@ -224,7 +234,7 @@ void LPortal::SortVertsClockwise() double SmallestAngle = -1; int Smallest = -1; - for (unsigned int m=n+1; m 0.0f) // if (p.WhichSideNDLCompatible(m_Verts[m], 0.0f) != CoPlane::NEGATIVE_SIDE) diff --git a/lportal.h b/lportal.h index 214b264..95a3d3d 100644 --- a/lportal.h +++ b/lportal.h @@ -36,6 +36,7 @@ class LPortal : public Spatial { GDCLASS(LPortal, Spatial); friend class LRoom; + friend class LRoomManager; private: enum eClipResult @@ -80,12 +81,13 @@ private: void SortVertsClockwise(); void ReverseWindingOrder(); - -// useful funcs public: +// useful funcs static bool NameStartsWith(Node * pNode, String szSearch); static String FindNameAfter(Node * pNode, String szStart); static void print(String sz); +protected: + static bool m_bRunning; }; diff --git a/lroom.cpp b/lroom.cpp index e9c39cd..0a48ed4 100644 --- a/lroom.cpp +++ b/lroom.cpp @@ -22,7 +22,7 @@ #include "core/engine.h" #include "scene/3d/mesh_instance.h" #include "lportal.h" -#include "CoBitField_Dynamic.h" +#include "lbitfield_dynamic.h" #include "lroom_manager.h" void LRoom::print(String sz) @@ -33,9 +33,157 @@ void LRoom::print(String sz) LRoom::LRoom() { m_LocalRoomID = -1; + m_uiFrameTouched = 0; } -void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from) + + +void LRoom::AddDOB(Spatial * pDOB) +{ + LDob dob; + dob.m_ID = pDOB->get_instance_id(); + + m_DOBs.push_back(dob); +} + +bool LRoom::RemoveDOB(Node * pDOB) +{ + ObjectID id = pDOB->get_instance_id(); + + for (int n=0; nget_global_transform().origin; + + const float slop = 0.2f; + + // the camera can't have slop because we might end up front side of a door without entering the room, + // hence can't see into the room through the portal! +// if (bCamera) +// slop = 0.0f; + + // check each portal - has the object crossed it into the neighbouring room? + int nPortals = m_portal_IDs.size(); + for (int p=0; p(pObj); + + if (!pPortal) + { + WARN_PRINT_ONCE("LRoom::UpdateDynamicObject : Not a portal"); + continue; + } + + float dist = pPortal->m_Plane.distance_to(pt); + + if (dist > slop) + { + print("DOB at pos " + pt + " ahead of portal " + pPortal->get_name() + " by " + String(Variant(dist))); + + // move into the adjoining room + return pPortal->GetLinkedRoom(); + +// LRoom * pNewRoom = pPortal->GetLinkedRoom(); +// if (pNewRoom) +// { +// // detach from this room and add to the new room +// remove_child(pDynObj); +// pNewRoom->add_child(pDynObj); +// // only allow one transition per frame +// return true; +// } +// else +// { +// WARN_PRINT_ONCE("LRoom::UpdateDynamicObject : portal linked room is NULL"); +// } + } + } + + return 0; +} + +/* +// assumes that the object is within, or just outside the bounds of the room... +// if not the results will be 'interesting'. +// Works simply by detecting crossing portals +bool LRoom::UpdateDynamicObject(Node * pDynObj) +{ + Spatial * pSpatial = Object::cast_to(pDynObj); + if (!pSpatial) + { + WARN_PRINT_ONCE("LRoom::UpdateDynamicObject : object is not a spatial"); + return false; + } + + const Vector3 &pt = pSpatial->get_global_transform().origin; + + const float slop = 0.2f; + + // check each portal - has the object crossed it into the neighbouring room? + int nPortals = m_portal_IDs.size(); + for (int p=0; p(pObj); + + if (!pPortal) + { + WARN_PRINT_ONCE("LRoom::UpdateDynamicObject : Not a portal"); + continue; + } + + float dist = pPortal->m_Plane.distance_to(pt); + + if (dist > slop) + { + print("DOB at pos " + pt + " ahead of portal " + pPortal->get_name() + " by " + String(Variant(dist))); + + // move into the adjoining room + LRoom * pNewRoom = pPortal->GetLinkedRoom(); + if (pNewRoom) + { + // detach from this room and add to the new room + remove_child(pDynObj); + pNewRoom->add_child(pDynObj); + // only allow one transition per frame + return true; + } + else + { + WARN_PRINT_ONCE("LRoom::UpdateDynamicObject : portal linked room is NULL"); + } + } + } + + return false; +} +*/ + +void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, Lawn::LBitField_Dynamic &BF_visible, ObjectID portalID_from) { // prevent too much depth if (depth >= 8) @@ -46,6 +194,10 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons print("DetermineVisibility_Recursive from " + get_name()); + // set the frame counter + assert (manager.m_uiFrameCounter > m_uiFrameTouched); + m_uiFrameTouched = manager.m_uiFrameCounter; + // show this room and add to visible list of rooms show(); BF_visible.SetBit(m_LocalRoomID, true); @@ -126,22 +278,32 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons continue; } - const Vector3 &portal_normal = pPortal->m_Plane.normal; - print("\ttesting portal " + pPortal->get_name() + " normal " + portal_normal); + // have we already handled the room on this frame? + // get the room pointed to by the portal + LRoom * pLinkedRoom = pPortal->GetLinkedRoom(); + if (pLinkedRoom->m_uiFrameTouched == manager.m_uiFrameCounter) + continue; + +// const Vector3 &portal_normal = pPortal->m_Plane.normal; +// print("\ttesting portal " + pPortal->get_name() + " normal " + portal_normal); // direction with the camera? (might not need to check) - float dot = cam.m_ptDir.dot(portal_normal); - if (dot <= 0.0f) - { - Variant vd = dot; - print("\t\tportal culled (wrong direction) dot is " + String(vd)); - continue; - } +// float dot = cam.m_ptDir.dot(portal_normal); +// if (dot <= -0.0f) // 0.0 +// { +// Variant vd = dot; +// print("\t\tportal culled (wrong direction) dot is " + String(vd)); +// continue; +// } // is it culled by the planes? LPortal::eClipResult overall_res = LPortal::eClipResult::CLIP_INSIDE; - for (int l=0; lClipWithPlane(planes[l]); @@ -179,8 +341,6 @@ void LRoom::DetermineVisibility_Recursive(LRoomManager &manager, int depth, cons // add the planes for the portal pPortal->AddPlanes(cam.m_ptPos, new_planes); - // get the room pointed to by the portal - LRoom * pLinkedRoom = pPortal->GetLinkedRoom(); if (pLinkedRoom) pLinkedRoom->DetermineVisibility_Recursive(manager, depth + 1, cam, new_planes, BF_visible, id); diff --git a/lroom.h b/lroom.h index 3d66a76..82a131a 100644 --- a/lroom.h +++ b/lroom.h @@ -29,9 +29,10 @@ #include "scene/3d/spatial.h" #include "lvector.h" +#include "ldob.h" -namespace Core {class CoBitField_Dynamic;} +namespace Lawn {class LBitField_Dynamic;} class LPortal; class LRoomManager; @@ -55,13 +56,21 @@ private: // a quick list of object IDs of child portals of this room Vector m_portal_IDs; + // godot vector for now .. can be lvector + Vector m_DOBs; + + // Just very rough, room centre for determining start rooms of dobs + Vector3 m_ptCentre; + // in the Room Manager, NOT the godot object ID int m_LocalRoomID; + // frame counter when last touched .. prevents handling rooms multiple times + unsigned int m_uiFrameTouched; + protected: static void _bind_methods(); -public: // initial setup, allows importing portals as meshes from modelling program, // which will be auto converted to LPortals with this method void DetectPortalMeshes(); @@ -70,8 +79,14 @@ public: void MakePortalQuickList(); // main function - void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from = 0); + void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector &planes, Lawn::LBitField_Dynamic &BF_visible, ObjectID portalID_from = 0); + // dynamic objects +// bool UpdateDynamicObject(Node * pDynObj); + + void AddDOB(Spatial * pDOB); + bool RemoveDOB(Node * pDOB); + LRoom * UpdateDOB(Spatial * pDOB); // specific public: LRoom(); diff --git a/lroom_manager.cpp b/lroom_manager.cpp index f7c96f4..d427619 100644 --- a/lroom_manager.cpp +++ b/lroom_manager.cpp @@ -23,14 +23,204 @@ #include "lroom.h" #include "core/engine.h" #include "scene/3d/camera.h" +#include "scene/3d/mesh_instance.h" LRoomManager::LRoomManager() { - m_room_curr = 0; +// m_room_curr = 0; m_cameraID = 0; - + m_uiFrameCounter = 0; } +int LRoomManager::FindClosestRoom(const Vector3 &pt) const +{ + //print_line("FindClosestRoom"); + int closest = -1; + float closest_dist = FLT_MAX; + + for (int n=0; nm_ptCentre); +// print_line("\troom " + itos(n) + " dist " + String(Variant(d))); + + if (d < closest_dist) + { + closest = n; + closest_dist = d; + } + } + + return closest; +} + + +LRoom * LRoomManager::GetRoomNum(int i) const +{ + assert (i < m_room_IDs.size()); + Object *pObj = ObjectDB::get_instance(m_room_IDs[i]); + if (!pObj) + return 0; + + LRoom * pRoom = Object::cast_to(pObj); + if (!pRoom) + return 0; + + return pRoom; +} + +int LRoomManager::GetRoomNumFromLRoom(LRoom * pRoom) const +{ + // slow .. use metadata for this + int search_id = pRoom->get_instance_id(); + + for (int n=0; nset_meta("_lroom", num); + + assert (Obj_GetRoomNum(pNode) == num); +} + +int LRoomManager::Obj_GetRoomNum(Node * pNode) const +{ + //assert (pNode->has_meta("_lroom")); + Variant v = pNode->get_meta("_lroom"); + if (v.get_type() == Variant::NIL) + return -1; + + return v; +} + +LRoom * LRoomManager::GetRoomFromDOB(Node * pNode) const +{ + int iRoom = Obj_GetRoomNum(pNode); + if (iRoom == -1) + { + WARN_PRINT_ONCE("LRoomManager::GetRoomFromDOB : metadata is empty"); + return 0; + } + + LRoom * pRoom = GetRoomNum(iRoom); + if (pRoom == 0) + { + WARN_PRINT_ONCE("LRoomManager::GetRoomFromDOB : pRoom is NULL"); + } + return pRoom; +} + + +void LRoomManager::register_dob(Node * pDOB) +{ + print_line("register_dob " + pDOB->get_name()); + + Spatial * pSpat = Object::cast_to(pDOB); + if (!pSpat) + return; + + Vector3 pt = pSpat->get_global_transform().origin; + + int iRoomNum = FindClosestRoom(pt); + print_line("register_dob closest room " + itos(iRoomNum)); + + if (iRoomNum == -1) + return; + + LRoom * pRoom = GetRoomNum(iRoomNum); + if (!pRoom) + return; + + pRoom->AddDOB(pSpat); + + // save the room ID on the dob metadata + Obj_SetRoomNum(pSpat, iRoomNum); +} + + +bool LRoomManager::update_dob(Node * pDOB) +{ + // find the room the object is attached to + LRoom * pRoom = GetRoomFromDOB(pDOB); + if (!pRoom) + return false; + + Spatial * pSpat = Object::cast_to(pDOB); + if (!pSpat) + return false; + + // is it the camera? + //bool bCamera = pDOB->get_instance_id() == m_cameraID; + + LRoom * pNewRoom = pRoom->UpdateDOB(pSpat); + + if (pNewRoom) + { + // remove from the list in old room and add to list in new room, and change the metadata + int iRoomNum = GetRoomNumFromLRoom(pNewRoom); + + pRoom->RemoveDOB(pDOB); + pNewRoom->AddDOB(pSpat); + + // save the room ID on the dob metadata + Obj_SetRoomNum(pSpat, iRoomNum); + } + + return false; +} + +bool LRoomManager::teleport_dob(Node * pDOB) +{ + return true; +} + + + +void LRoomManager::unregister_dob(Node * pDOB) +{ + LRoom * pRoom = GetRoomFromDOB(pDOB); + pRoom->RemoveDOB(pDOB); +} + + +/* +bool LRoomManager::update_object(Node * pObj) +{ + // find the room the object is attached to + Node * pParent = pObj->get_parent(); + LRoom * pRoom = Object::cast_to(pParent); + if (!pRoom) + { + WARN_PRINT_ONCE("LRoomManager::update_object : object parent is not an LRoom"); + return false; + } + + bool bChanged = pRoom->UpdateDynamicObject(pObj); + + // special .. for camera keep the camera room ID up to date + // could alternatively just use the parent of the camera? +// if (bChanged) +// { +// if (pObj->get_instance_id() == m_cameraID) +// { +// m_room_curr = pObj->get_parent()->get_instance_id(); +// } +// } + + return bChanged; +} +*/ void LRoomManager::set_camera(Node * pCam) { @@ -47,16 +237,21 @@ void LRoomManager::set_camera(Node * pCam) } m_cameraID = pCam->get_instance_id(); + + // use this temporarily to force debug + LPortal::m_bRunning = false; } // convert empties and meshes to rooms and portals void LRoomManager::convert() { + LPortal::m_bRunning = false; print_line("running convert"); Convert_Rooms(); Convert_Portals(); Find_Rooms(); + LPortal::m_bRunning = true; } void LRoomManager::Find_Rooms() @@ -78,6 +273,7 @@ void LRoomManager::Find_Rooms() } } + /* m_room_curr = 0; // just set current room to first room @@ -86,6 +282,7 @@ void LRoomManager::Find_Rooms() m_room_curr = m_room_IDs[0]; print_line("first room ID is " + itos(m_room_curr)); } + */ // make sure bitfield is right size for number of rooms m_BF_visible_rooms.Create(m_room_IDs.size()); @@ -179,20 +376,55 @@ bool LRoomManager::Convert_Room(Spatial * pNode) // make the transform of the L room match the original spatial pNew->set_transform(pNode->get_transform()); + // New .. room is at origin, all the child nodes are now transformed + // so everything is in world space ... makes dynamic objects changing rooms easier + //Transform tr_orig = pNode->get_transform(); + int nChildren = pNode->get_child_count(); + LAABB bb_room; + bb_room.SetToMaxOpposite(); + for (int n=0; nget_child(c); + + // change the transform of the child to take away the room transform +// Spatial * pSChild = Object::cast_to(pChild); +// Transform tr_world; +// if (pSChild) +// { +// tr_world = pSChild->get_global_transform(); +// } + + // update bound to find centre of room roughly + VisualInstance * pVI = Object::cast_to(pChild); + if (pVI) + { + AABB bb = pVI->get_transformed_aabb(); + bb_room.ExpandToEnclose(bb); + } + + pNode->remove_child(pChild); // add the child to the new node pNew->add_child(pChild); + + +// if (pSChild) +// { +// pSChild->set_transform(tr_world); +// } + } + pNew->m_ptCentre = bb_room.FindCentre(); + print_line(String(pNew->get_name()) + " centre " + pNew->m_ptCentre); + // all moved .. now finally delete the empty remove_child(pNode); pNode->queue_delete(); @@ -208,22 +440,41 @@ void LRoomManager::FrameUpdate() return; } - // if not started - if (!m_room_curr) + m_uiFrameCounter++; + + // get the camera desired and make into lcamera + Camera * pCamera = 0; + if (m_cameraID) + { + Object *pObj = ObjectDB::get_instance(m_cameraID); + pCamera = Object::cast_to(pObj); + } + else + // camera not set return; + // camera not a camera?? + if (!pCamera) + return; + + // if not started +// if (!m_room_curr) +// return; + // determine visibility - Object *pObj = ObjectDB::get_instance(m_room_curr); +// Object *pObj = ObjectDB::get_instance(m_room_curr); + LRoom * pRoom = GetRoomFromDOB(pCamera); +// Node * pObj = pCamera->get_parent(); - if (!pObj) - return; +// if (!pObj) +// return; - LRoom * pRoom = Object::cast_to(pObj); +// LRoom * pRoom = Object::cast_to(pObj); if (!pRoom) { WARN_PRINT_ONCE("LRoomManager::FrameUpdate : curr room is not an LRoom"); - print_line("curr room is not an LRoom"); - m_room_curr = 0; + //print_line("LRoomManager::FrameUpdate : curr room is not an LRoom"); +// m_room_curr = 0; return; } @@ -242,19 +493,14 @@ void LRoomManager::FrameUpdate() planes.clear(); // get the camera desired and make into lcamera - if (m_cameraID) + assert (pCamera); +// if (pCamera) { - Object *pObj = ObjectDB::get_instance(m_cameraID); + Transform tr = pCamera->get_global_transform(); + cam.m_ptPos = tr.origin; + cam.m_ptDir = tr.basis.get_row(2); // or possibly get_axis .. z is what we want - Camera * pCamera = Object::cast_to(pObj); - if (pCamera) - { - Transform tr = pCamera->get_global_transform(); - cam.m_ptPos = tr.origin; - cam.m_ptDir = tr.basis.get_row(2); // or possibly get_axis .. z is what we want - - planes.copy_from(pCamera->get_frustum()); - } + planes.copy_from(pCamera->get_frustum()); } pRoom->DetermineVisibility_Recursive(*this, 0, cam, planes, m_BF_visible_rooms); @@ -276,6 +522,9 @@ void LRoomManager::FrameUpdate() } } + LPortal::m_bRunning = true; + + // only do once for now // m_room_curr = 0; } @@ -317,7 +566,14 @@ void LRoomManager::_notification(int p_what) { void LRoomManager::_bind_methods() { - ClassDB::bind_method(D_METHOD("convert"), &LRoomManager::convert); - ClassDB::bind_method(D_METHOD("set_camera"), &LRoomManager::set_camera); + ClassDB::bind_method(D_METHOD("rooms_convert"), &LRoomManager::convert); + ClassDB::bind_method(D_METHOD("rooms_set_camera"), &LRoomManager::set_camera); +// ClassDB::bind_method(D_METHOD("update_object"), &LRoomManager::update_object); + + + ClassDB::bind_method(D_METHOD("dob_register"), &LRoomManager::register_dob); + ClassDB::bind_method(D_METHOD("dob_unregister"), &LRoomManager::unregister_dob); + ClassDB::bind_method(D_METHOD("dob_update"), &LRoomManager::update_dob); + ClassDB::bind_method(D_METHOD("dob_teleport"), &LRoomManager::teleport_dob); } diff --git a/lroom_manager.h b/lroom_manager.h index 6c1da31..90fb12a 100644 --- a/lroom_manager.h +++ b/lroom_manager.h @@ -27,9 +27,46 @@ */ #include "scene/3d/spatial.h" -#include "CoBitField_Dynamic.h" +#include "lbitfield_dynamic.h" #include "lplanes_pool.h" + +class LRoom; + +// simple min max aabb +class LAABB +{ +public: + Vector3 m_ptMins; + Vector3 m_ptMaxs; + void SetToMaxOpposite() + { + float ma = FLT_MAX; + float mi = FLT_MIN; + m_ptMins = Vector3(ma, ma, ma); + m_ptMaxs = Vector3(mi, mi, mi); + } + void ExpandToEnclose(const AABB &bb) + { + if (bb.position.x < m_ptMins.x) m_ptMins.x = bb.position.x; + if (bb.position.y < m_ptMins.y) m_ptMins.y = bb.position.y; + if (bb.position.z < m_ptMins.z) m_ptMins.z = bb.position.z; + if (bb.position.x + bb.size.x > m_ptMaxs.x) m_ptMaxs.x = bb.position.x + bb.size.x; + if (bb.position.y + bb.size.y > m_ptMaxs.y) m_ptMaxs.y = bb.position.y + bb.size.y; + if (bb.position.z + bb.size.z > m_ptMaxs.z) m_ptMaxs.z = bb.position.z + bb.size.z; + } + Vector3 FindCentre() const + { + Vector3 pt; + pt.x = (m_ptMaxs.x - m_ptMins.x) * 0.5f; + pt.y = (m_ptMaxs.y - m_ptMins.y) * 0.5f; + pt.z = (m_ptMaxs.z - m_ptMins.z) * 0.5f; + pt += m_ptMins; + return pt; + } +}; + + class LRoomManager : public Spatial { GDCLASS(LRoomManager, Spatial); @@ -38,14 +75,18 @@ class LRoomManager : public Spatial { // a quick list of object IDs of child rooms Vector m_room_IDs; - ObjectID m_room_curr; +// ObjectID m_room_curr; ObjectID m_cameraID; // keep track of which rooms are visible, so we can hide ones that aren't hit that were previously on - Core::CoBitField_Dynamic m_BF_visible_rooms; + Lawn::LBitField_Dynamic m_BF_visible_rooms; Vector m_VisibleRoomList[2]; int m_CurrentVisibleRoomList; + // keep a frame counter, to mark when objects have been hit by the visiblity algorithm + // already to prevent multiple hits on rooms and objects + unsigned int m_uiFrameCounter; + public: LRoomManager(); @@ -56,17 +97,35 @@ public: // normally this will be your main camera, but you can choose another for debugging void set_camera(Node * pCam); + // updating dynamic objects in case they move out of their current room + void register_dob(Node * pDOB); + void unregister_dob(Node * pDOB); + bool update_dob(Node * pDOB); + bool teleport_dob(Node * pDOB); + + protected: static void _bind_methods(); void _notification(int p_what); LPlanesPool m_Pool; private: + // one time conversion and setup void Convert_Rooms(); bool Convert_Room(Spatial * pNode); void Convert_Portals(); void Find_Rooms(); + // helper funcs + LRoom * GetRoomNum(int i) const; + LRoom * GetRoomFromDOB(Node * pNode) const; + int GetRoomNumFromLRoom(LRoom * pRoom) const; + int FindClosestRoom(const Vector3 &pt) const; + + int Obj_GetRoomNum(Node * pNode) const; + void Obj_SetRoomNum(Node * pNode, int num); + + void FrameUpdate(); }; diff --git a/lvector.h b/lvector.h index 4b68d31..e9b2c70 100644 --- a/lvector.h +++ b/lvector.h @@ -16,7 +16,7 @@ public: } const T& operator[](unsigned int ui) const { - assert (ui < m_iSize); + assert (ui < (unsigned int) m_iSize); return m_Vec[ui]; } @@ -39,7 +39,7 @@ public: void set(unsigned int ui, const T &t) { - assert (ui < m_iSize); + assert (ui < (unsigned int) m_iSize); m_Vec.set(ui, t); }