Dynamic objects now working

Code needs cleaning up though, and replacing Vector with LVector, and adding culling for dynamics.
This commit is contained in:
lawnjelly 2019-09-13 19:15:25 +01:00 committed by GitHub
parent 811e6d984f
commit 664e8175bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 749 additions and 51 deletions

3
SCsub
View File

@ -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()

93
lbitfield_dynamic.cpp Normal file
View File

@ -0,0 +1,93 @@
#include "lbitfield_dynamic.h"
#include <string.h>
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<m_uiNumBytes; n++)
{
m_pucData[n] = ~m_pucData[n];
}
}
////////////////////////////////////////////////////////////////////////////
} // namespace end

91
lbitfield_dynamic.h Normal file
View File

@ -0,0 +1,91 @@
#pragma once
#include <assert.h>
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

2
ldob.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "ldob.h"

9
ldob.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include "scene/3d/spatial.h"
class LDob
{
public:
ObjectID m_ID;
};

View File

@ -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<nPoints; m++)
for (int m=n+1; m<nPoints; m++)
{
if (p.distance_to(verts[m]) > 0.0f)
// if (p.WhichSideNDLCompatible(m_Verts[m], 0.0f) != CoPlane::NEGATIVE_SIDE)

View File

@ -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;
};

188
lroom.cpp
View File

@ -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<Plane> &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; n<m_DOBs.size(); n++)
{
if (m_DOBs[n].m_ID == id)
{
m_DOBs.remove(n);
return true;
}
}
return false;
}
// returns -1 if no change, or the objectID of the linked room
LRoom * LRoom::UpdateDOB(Spatial * pDOB)
{
const Vector3 &pt = pDOB->get_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<nPortals; p++)
{
ObjectID id = m_portal_IDs[p];
// get the portal
Object *pObj = ObjectDB::get_instance(id);
// assuming is a portal
LPortal * pPortal = Object::cast_to<LPortal>(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<Spatial>(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<nPortals; p++)
{
ObjectID id = m_portal_IDs[p];
// get the portal
Object *pObj = ObjectDB::get_instance(id);
// assuming is a portal
LPortal * pPortal = Object::cast_to<LPortal>(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<Plane> &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; l<planes.size(); l++)
// for portals, we want to ignore the near clipping plane, as we might be right on the edge of a doorway
// and still want to look through the portal.
// So we are starting this loop from 1, ASSUMING that plane zero is the near clipping plane.
// If it isn't we would need a different strategy
for (int l=1; l<planes.size(); l++)
{
LPortal::eClipResult res = pPortal->ClipWithPlane(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);

21
lroom.h
View File

@ -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<ObjectID> m_portal_IDs;
// godot vector for now .. can be lvector
Vector<LDob> 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<Plane> &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from = 0);
void DetermineVisibility_Recursive(LRoomManager &manager, int depth, const LCamera &cam, const LVector<Plane> &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();

View File

@ -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; n<m_room_IDs.size(); n++)
{
LRoom * pRoom = GetRoomNum(n);
if (!pRoom)
continue;
float d = pt.distance_squared_to(pRoom->m_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<LRoom>(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; n<m_room_IDs.size(); n++)
{
if (m_room_IDs[n] == search_id)
return n;
}
return -1;
}
void LRoomManager::Obj_SetRoomNum(Node * pNode, int num)
{
pNode->set_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<Spatial>(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<Spatial>(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<LRoom>(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; n<nChildren; n++)
{
// reverse count
int c = nChildren - n - 1;
Node * pChild = pNode->get_child(c);
// change the transform of the child to take away the room transform
// Spatial * pSChild = Object::cast_to<Spatial>(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<VisualInstance>(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<Camera>(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<LRoom>(pObj);
// LRoom * pRoom = Object::cast_to<LRoom>(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,12 +493,8 @@ void LRoomManager::FrameUpdate()
planes.clear();
// get the camera desired and make into lcamera
if (m_cameraID)
{
Object *pObj = ObjectDB::get_instance(m_cameraID);
Camera * pCamera = Object::cast_to<Camera>(pObj);
if (pCamera)
assert (pCamera);
// if (pCamera)
{
Transform tr = pCamera->get_global_transform();
cam.m_ptPos = tr.origin;
@ -255,7 +502,6 @@ void LRoomManager::FrameUpdate()
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);
}

View File

@ -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<ObjectID> 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<int> 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();
};

View File

@ -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);
}