mirror of
https://github.com/Relintai/godot-lportal.git
synced 2024-11-11 10:52:09 +01:00
First working test version
This commit is contained in:
parent
829dcb8e13
commit
726412a97b
93
CoBitField_Dynamic.cpp
Normal file
93
CoBitField_Dynamic.cpp
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#include "CoBitField_Dynamic.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Core { // namespace start
|
||||||
|
|
||||||
|
void CoBitField_Dynamic::Initialize() {assert (0 && "CoBitField_Dynamic : Does not support Initialize, use IT version");}
|
||||||
|
void CoBitField_Dynamic::Terminate() {assert (0 && "CoBitField_Dynamic : Does not support Terminate, use IT version");}
|
||||||
|
|
||||||
|
|
||||||
|
void CoBitField_Dynamic_IT::Initialize()
|
||||||
|
{
|
||||||
|
Initialize_Do();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoBitField_Dynamic_IT::Terminate()
|
||||||
|
{
|
||||||
|
Terminate_Do();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CoBitField_Dynamic_IT::Initialize_Do()
|
||||||
|
{
|
||||||
|
memset (this, 0, sizeof (CoBitField_Dynamic));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoBitField_Dynamic_IT::Terminate_Do()
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoBitField_Dynamic_IT::CopyFrom(const CoBitField_Dynamic_IT &source)
|
||||||
|
{
|
||||||
|
Create(source.GetNumBits(), false);
|
||||||
|
memcpy(m_pucData, source.GetData(), source.GetNumBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CoBitField_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 CoBitField_Dynamic_IT::Destroy()
|
||||||
|
{
|
||||||
|
if (m_pucData)
|
||||||
|
{
|
||||||
|
delete[] m_pucData;
|
||||||
|
m_pucData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (this, 0, sizeof (CoBitField_Dynamic));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CoBitField_Dynamic_IT::Blank(bool bSetOrZero)
|
||||||
|
{
|
||||||
|
if (bSetOrZero)
|
||||||
|
{
|
||||||
|
memset(m_pucData, 255, m_uiNumBytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(m_pucData, 0, m_uiNumBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoBitField_Dynamic_IT::Invert()
|
||||||
|
{
|
||||||
|
for (unsigned int n=0; n<m_uiNumBytes; n++)
|
||||||
|
{
|
||||||
|
m_pucData[n] = ~m_pucData[n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace end
|
91
CoBitField_Dynamic.h
Normal file
91
CoBitField_Dynamic.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
namespace Core { // namespace start
|
||||||
|
|
||||||
|
class CoBitField_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.
|
||||||
|
CoBitField_Dynamic_IT& operator=(const CoBitField_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 CoBitField_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 CoBitField_Dynamic : public CoBitField_Dynamic_IT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// call initialize and terminate automatically
|
||||||
|
CoBitField_Dynamic(unsigned int uiNumBits) {Initialize_Do(); Create(uiNumBits);}
|
||||||
|
CoBitField_Dynamic() {Initialize_Do();}
|
||||||
|
~CoBitField_Dynamic() {Terminate_Do();}
|
||||||
|
|
||||||
|
// disallow explicit calls
|
||||||
|
void Initialize();
|
||||||
|
void Terminate();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////
|
||||||
|
inline unsigned int CoBitField_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 CoBitField_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
|
1
SCsub
1
SCsub
@ -6,6 +6,7 @@ sources = [
|
|||||||
"lroom.cpp",
|
"lroom.cpp",
|
||||||
"lroom_manager.cpp",
|
"lroom_manager.cpp",
|
||||||
"lportal.cpp",
|
"lportal.cpp",
|
||||||
|
"CoBitField_Dynamic.cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
module_env = env.Clone()
|
module_env = env.Clone()
|
||||||
|
47
lportal.cpp
47
lportal.cpp
@ -22,6 +22,10 @@
|
|||||||
#include "core/engine.h"
|
#include "core/engine.h"
|
||||||
#include "lroom.h"
|
#include "lroom.h"
|
||||||
|
|
||||||
|
void LPortal::print(String sz)
|
||||||
|
{
|
||||||
|
// print_line(sz);
|
||||||
|
}
|
||||||
|
|
||||||
bool LPortal::NameStartsWith(Node * pNode, String szSearch)
|
bool LPortal::NameStartsWith(Node * pNode, String szSearch)
|
||||||
{
|
{
|
||||||
@ -50,12 +54,31 @@ String LPortal::FindNameAfter(Node * pNode, String szStart)
|
|||||||
String name = pNode->get_name();
|
String name = pNode->get_name();
|
||||||
szRes = name.substr(szStart.length());
|
szRes = name.substr(szStart.length());
|
||||||
|
|
||||||
print_line("\t\tNameAfter is " + szRes);
|
print("\t\tNameAfter is " + szRes);
|
||||||
return szRes;
|
return szRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// add clipping planes to the vector formed by each portal edge and the camera
|
||||||
|
void LPortal::AddPlanes(const Vector3 &ptCam, Vector<Plane> &planes) const
|
||||||
|
{
|
||||||
|
// short version
|
||||||
|
const Vector<Vector3> &pts = m_ptsWorld;
|
||||||
|
|
||||||
|
int nPoints = pts.size();
|
||||||
|
// ERR_FAIL_COND(nPoints < 3);
|
||||||
|
|
||||||
|
Plane p;
|
||||||
|
|
||||||
|
for (int n=1; n<nPoints; n++)
|
||||||
|
{
|
||||||
|
p = Plane(ptCam, pts[n], pts[n-1]);
|
||||||
|
planes.push_back(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LPortal::eClipResult LPortal::ClipWithPlane(const Plane &p) const
|
LPortal::eClipResult LPortal::ClipWithPlane(const Plane &p) const
|
||||||
{
|
{
|
||||||
int nOutside = 0;
|
int nOutside = 0;
|
||||||
@ -93,7 +116,7 @@ void LPortal::Link(LRoom * pParentRoom)
|
|||||||
|
|
||||||
String szRoom = FindNameAfter(this, "lportal_");
|
String szRoom = FindNameAfter(this, "lportal_");
|
||||||
|
|
||||||
print_line("LPortal::Link to room " + szRoom);
|
print("LPortal::Link to room " + szRoom);
|
||||||
|
|
||||||
// find the room group
|
// find the room group
|
||||||
Spatial * pGroup = Object::cast_to<Spatial>(pParentRoom->get_parent());
|
Spatial * pGroup = Object::cast_to<Spatial>(pParentRoom->get_parent());
|
||||||
@ -139,13 +162,13 @@ void LPortal::CreateGeometry(PoolVector<Vector3> p_vertices)
|
|||||||
m_ptsLocal.resize(nPoints);
|
m_ptsLocal.resize(nPoints);
|
||||||
m_ptsWorld.resize(nPoints);
|
m_ptsWorld.resize(nPoints);
|
||||||
|
|
||||||
print_line("\tLPortal::CreateGeometry nPoints : " + itos(nPoints));
|
print("\tLPortal::CreateGeometry nPoints : " + itos(nPoints));
|
||||||
|
|
||||||
for (int n=0; n<nPoints; n++)
|
for (int n=0; n<nPoints; n++)
|
||||||
{
|
{
|
||||||
m_ptsLocal.set(n, p_vertices[n]);
|
m_ptsLocal.set(n, p_vertices[n]);
|
||||||
Variant pt = p_vertices[n];
|
Variant pt = p_vertices[n];
|
||||||
print_line("\t\t" + itos(n) + "\t: " + pt);
|
print("\t\t" + itos(n) + "\t: " + pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
SortVertsClockwise();
|
SortVertsClockwise();
|
||||||
@ -250,12 +273,12 @@ void LPortal::CalculateLocalPoints()
|
|||||||
|
|
||||||
Transform tr = get_transform();
|
Transform tr = get_transform();
|
||||||
|
|
||||||
print_line("\tCalculateLocalPoints");
|
print("\tCalculateLocalPoints");
|
||||||
for (int n=0; n<nPoints; n++)
|
for (int n=0; n<nPoints; n++)
|
||||||
{
|
{
|
||||||
m_ptsLocal.set(n, tr.xform_inv(m_ptsWorld[n]));
|
m_ptsLocal.set(n, tr.xform_inv(m_ptsWorld[n]));
|
||||||
Variant pt = m_ptsLocal[n];
|
Variant pt = m_ptsLocal[n];
|
||||||
print_line("\t\t" + itos(n) + "\t: " + pt);
|
print("\t\t" + itos(n) + "\t: " + pt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,18 +290,18 @@ void LPortal::CalculateWorldPoints()
|
|||||||
|
|
||||||
Transform tr = get_global_transform();
|
Transform tr = get_global_transform();
|
||||||
|
|
||||||
print_line("\tCalculateWorldPoints");
|
print("\tCalculateWorldPoints");
|
||||||
for (int n=0; n<nPoints; n++)
|
for (int n=0; n<nPoints; n++)
|
||||||
{
|
{
|
||||||
m_ptsWorld.set(n, tr.xform(m_ptsLocal[n]));
|
m_ptsWorld.set(n, tr.xform(m_ptsLocal[n]));
|
||||||
Variant pt = m_ptsWorld[n];
|
Variant pt = m_ptsWorld[n];
|
||||||
print_line("\t\t" + itos(n) + "\t: " + pt);
|
print("\t\t" + itos(n) + "\t: " + pt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LPortal::CopyReversedGeometry(const LPortal &source)
|
void LPortal::CopyReversedGeometry(const LPortal &source)
|
||||||
{
|
{
|
||||||
print_line("CopyReversedGeometry");
|
print("CopyReversedGeometry");
|
||||||
// points are the same but reverse winding order
|
// points are the same but reverse winding order
|
||||||
int nPoints = source.m_ptsWorld.size();
|
int nPoints = source.m_ptsWorld.size();
|
||||||
|
|
||||||
@ -289,7 +312,7 @@ void LPortal::CopyReversedGeometry(const LPortal &source)
|
|||||||
{
|
{
|
||||||
m_ptsWorld.set(n, source.m_ptsWorld[nPoints - n - 1]);
|
m_ptsWorld.set(n, source.m_ptsWorld[nPoints - n - 1]);
|
||||||
Variant pt = m_ptsWorld[n];
|
Variant pt = m_ptsWorld[n];
|
||||||
print_line("\t\t" + itos(n) + "\t: " + pt);
|
print("\t\t" + itos(n) + "\t: " + pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
CalculateLocalPoints();
|
CalculateLocalPoints();
|
||||||
@ -306,7 +329,7 @@ void LPortal::PlaneFromPoints()
|
|||||||
// create plane from points
|
// create plane from points
|
||||||
m_Plane = Plane(m_ptsWorld[0], m_ptsWorld[1], m_ptsWorld[2]);
|
m_Plane = Plane(m_ptsWorld[0], m_ptsWorld[1], m_ptsWorld[2]);
|
||||||
|
|
||||||
print_line("Plane normal world space : " + m_Plane);
|
print("Plane normal world space : " + m_Plane);
|
||||||
|
|
||||||
// Plane opp = Plane(m_ptsWorld[2], m_ptsWorld[1], m_ptsWorld[0]);
|
// Plane opp = Plane(m_ptsWorld[2], m_ptsWorld[1], m_ptsWorld[0]);
|
||||||
// print_line("Plane opposite : " + opp);
|
// print_line("Plane opposite : " + opp);
|
||||||
@ -315,7 +338,7 @@ void LPortal::PlaneFromPoints()
|
|||||||
|
|
||||||
bool LPortal::AddRoom(NodePath path)
|
bool LPortal::AddRoom(NodePath path)
|
||||||
{
|
{
|
||||||
print_line("LPortal::AddRoom path is " + path);
|
print("LPortal::AddRoom path is " + path);
|
||||||
|
|
||||||
if (has_node(path))
|
if (has_node(path))
|
||||||
{
|
{
|
||||||
|
12
lportal.h
12
lportal.h
@ -29,16 +29,6 @@
|
|||||||
|
|
||||||
#include "scene/3d/spatial.h"
|
#include "scene/3d/spatial.h"
|
||||||
|
|
||||||
|
|
||||||
// Smooth node allows fixed timestep interpolation without having to write any code.
|
|
||||||
// It requires a proxy node (which is moved on physics tick), e.g. a rigid body or manually moved spatial..
|
|
||||||
// and instead of having MeshInstance as a child of this, you add Smooth node to another part of the scene graph,
|
|
||||||
// make the MeshInstance a child of the smooth node, then choose the proxy as the target for the smooth node.
|
|
||||||
|
|
||||||
// Note that in the special case of manually moving the proxy to a completely new location, you should call
|
|
||||||
// 'teleport' on the smooth node after setting the proxy node transform. This will ensure that the current AND
|
|
||||||
// previous transform records are reset, so it moves instantaneously.
|
|
||||||
|
|
||||||
class LRoom;
|
class LRoom;
|
||||||
|
|
||||||
class LPortal : public Spatial {
|
class LPortal : public Spatial {
|
||||||
@ -62,6 +52,7 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
LPortal::eClipResult ClipWithPlane(const Plane &p) const;
|
LPortal::eClipResult ClipWithPlane(const Plane &p) const;
|
||||||
|
void AddPlanes(const Vector3 &ptCam, Vector<Plane> &planes) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// normal determined by winding order
|
// normal determined by winding order
|
||||||
@ -93,6 +84,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
static bool NameStartsWith(Node * pNode, String szSearch);
|
static bool NameStartsWith(Node * pNode, String szSearch);
|
||||||
static String FindNameAfter(Node * pNode, String szStart);
|
static String FindNameAfter(Node * pNode, String szStart);
|
||||||
|
static void print(String sz);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
84
lroom.cpp
84
lroom.cpp
@ -22,24 +22,82 @@
|
|||||||
#include "core/engine.h"
|
#include "core/engine.h"
|
||||||
#include "scene/3d/mesh_instance.h"
|
#include "scene/3d/mesh_instance.h"
|
||||||
#include "lportal.h"
|
#include "lportal.h"
|
||||||
|
#include "CoBitField_Dynamic.h"
|
||||||
|
|
||||||
|
void LRoom::print(String sz)
|
||||||
LRoom::LRoom() {
|
{
|
||||||
|
// print_line(sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const Vector<Plane> &planes, ObjectID portalID_from)
|
LRoom::LRoom() {
|
||||||
|
m_LocalRoomID = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const Vector<Plane> &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from)
|
||||||
{
|
{
|
||||||
// prevent too much depth
|
// prevent too much depth
|
||||||
if (depth >= 8)
|
if (depth >= 8)
|
||||||
{
|
{
|
||||||
print_line("\t\t\tDEPTH LIMIT REACHED");
|
print("\t\t\tDEPTH LIMIT REACHED");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
print_line("DetermineVisibility_Recursive from " + get_name());
|
print("DetermineVisibility_Recursive from " + get_name());
|
||||||
|
|
||||||
|
// show this room and add to visible list of rooms
|
||||||
|
show();
|
||||||
|
BF_visible.SetBit(m_LocalRoomID, true);
|
||||||
|
|
||||||
// clip all objects in this room to the clipping planes
|
// clip all objects in this room to the clipping planes
|
||||||
// NYI
|
for (int n=0; n<get_child_count(); n++)
|
||||||
|
{
|
||||||
|
// ignore portals
|
||||||
|
Node * pNode = get_child(n);
|
||||||
|
LPortal * pPortal = Object::cast_to<LPortal>(pNode);
|
||||||
|
if (pPortal)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
VisualInstance * pObj = Object::cast_to<VisualInstance>(pNode);
|
||||||
|
if (pObj)
|
||||||
|
{
|
||||||
|
Vector3 pt = pObj->get_global_transform().origin;
|
||||||
|
|
||||||
|
bool bShow = true;
|
||||||
|
|
||||||
|
|
||||||
|
// estimate the radius .. for now
|
||||||
|
AABB bb = pObj->get_transformed_aabb();
|
||||||
|
|
||||||
|
print("\t\t\tculling object " + pObj->get_name());
|
||||||
|
|
||||||
|
for (int p=0; p<planes.size(); p++)
|
||||||
|
{
|
||||||
|
// float dist = planes[p].distance_to(pt);
|
||||||
|
// print("\t\t\t\t" + itos(p) + " : dist " + String(Variant(dist)));
|
||||||
|
|
||||||
|
float r_min, r_max;
|
||||||
|
bb.project_range_in_plane(planes[p], r_min, r_max);
|
||||||
|
|
||||||
|
print("\t\t\t\t" + itos(p) + " : r_min " + String(Variant(r_min)) + ", r_max " + String(Variant(r_max)));
|
||||||
|
|
||||||
|
|
||||||
|
if (r_min > 0.0f)
|
||||||
|
{
|
||||||
|
bShow = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bShow)
|
||||||
|
pObj->show();
|
||||||
|
else
|
||||||
|
pObj->hide();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// go through each portal out of here
|
// go through each portal out of here
|
||||||
int nPortals = m_portal_IDs.size();
|
int nPortals = m_portal_IDs.size();
|
||||||
@ -67,14 +125,14 @@ void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const V
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Vector3 &portal_normal = pPortal->m_Plane.normal;
|
const Vector3 &portal_normal = pPortal->m_Plane.normal;
|
||||||
print_line("\ttesting portal " + pPortal->get_name() + " normal " + portal_normal);
|
print("\ttesting portal " + pPortal->get_name() + " normal " + portal_normal);
|
||||||
|
|
||||||
// direction with the camera? (might not need to check)
|
// direction with the camera? (might not need to check)
|
||||||
float dot = cam.m_ptDir.dot(portal_normal);
|
float dot = cam.m_ptDir.dot(portal_normal);
|
||||||
if (dot <= 0.0f)
|
if (dot <= 0.0f)
|
||||||
{
|
{
|
||||||
Variant vd = dot;
|
Variant vd = dot;
|
||||||
print_line("\t\tportal culled (wrong direction) dot is " + String(vd));
|
print("\t\tportal culled (wrong direction) dot is " + String(vd));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +160,7 @@ void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const V
|
|||||||
// this portal is culled
|
// this portal is culled
|
||||||
if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE)
|
if (overall_res == LPortal::eClipResult::CLIP_OUTSIDE)
|
||||||
{
|
{
|
||||||
print_line("\t\tportal culled (outside planes)");
|
print("\t\tportal culled (outside planes)");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,12 +168,12 @@ void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const V
|
|||||||
Vector<Plane> new_planes = planes;
|
Vector<Plane> new_planes = planes;
|
||||||
|
|
||||||
// add the planes for the portal
|
// add the planes for the portal
|
||||||
// NYI
|
pPortal->AddPlanes(cam.m_ptPos, new_planes);
|
||||||
|
|
||||||
// get the room pointed to by the portal
|
// get the room pointed to by the portal
|
||||||
LRoom * pLinkedRoom = pPortal->GetLinkedRoom();
|
LRoom * pLinkedRoom = pPortal->GetLinkedRoom();
|
||||||
if (pLinkedRoom)
|
if (pLinkedRoom)
|
||||||
pLinkedRoom->DetermineVisibility_Recursive(depth + 1, cam, new_planes, id);
|
pLinkedRoom->DetermineVisibility_Recursive(depth + 1, cam, new_planes, BF_visible, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +183,7 @@ void LRoom::DetermineVisibility_Recursive(int depth, const LCamera &cam, const V
|
|||||||
// which will be auto converted to LPortals with this method
|
// which will be auto converted to LPortals with this method
|
||||||
void LRoom::DetectPortalMeshes()
|
void LRoom::DetectPortalMeshes()
|
||||||
{
|
{
|
||||||
print_line("DetectPortalMeshes");
|
print("DetectPortalMeshes");
|
||||||
|
|
||||||
bool bFoundOne = true;
|
bool bFoundOne = true;
|
||||||
|
|
||||||
@ -158,7 +216,7 @@ void LRoom::DetectPortalMeshes()
|
|||||||
|
|
||||||
void LRoom::DetectedPortalMesh(MeshInstance * pMeshInstance, String szLinkRoom)
|
void LRoom::DetectedPortalMesh(MeshInstance * pMeshInstance, String szLinkRoom)
|
||||||
{
|
{
|
||||||
print_line("\tDetected PortalMesh");
|
print("\tDetected PortalMesh");
|
||||||
|
|
||||||
Ref<Mesh> rmesh = pMeshInstance->get_mesh();
|
Ref<Mesh> rmesh = pMeshInstance->get_mesh();
|
||||||
|
|
||||||
|
16
lroom.h
16
lroom.h
@ -30,14 +30,7 @@
|
|||||||
#include "scene/3d/spatial.h"
|
#include "scene/3d/spatial.h"
|
||||||
|
|
||||||
|
|
||||||
// Smooth node allows fixed timestep interpolation without having to write any code.
|
namespace Core {class CoBitField_Dynamic;}
|
||||||
// It requires a proxy node (which is moved on physics tick), e.g. a rigid body or manually moved spatial..
|
|
||||||
// and instead of having MeshInstance as a child of this, you add Smooth node to another part of the scene graph,
|
|
||||||
// make the MeshInstance a child of the smooth node, then choose the proxy as the target for the smooth node.
|
|
||||||
|
|
||||||
// Note that in the special case of manually moving the proxy to a completely new location, you should call
|
|
||||||
// 'teleport' on the smooth node after setting the proxy node transform. This will ensure that the current AND
|
|
||||||
// previous transform records are reset, so it moves instantaneously.
|
|
||||||
|
|
||||||
class LPortal;
|
class LPortal;
|
||||||
class MeshInstance;
|
class MeshInstance;
|
||||||
@ -55,10 +48,14 @@ class LRoom : public Spatial {
|
|||||||
GDCLASS(LRoom, Spatial);
|
GDCLASS(LRoom, Spatial);
|
||||||
|
|
||||||
friend class LPortal;
|
friend class LPortal;
|
||||||
|
friend class LRoomManager;
|
||||||
private:
|
private:
|
||||||
// a quick list of object IDs of child portals of this room
|
// a quick list of object IDs of child portals of this room
|
||||||
Vector<ObjectID> m_portal_IDs;
|
Vector<ObjectID> m_portal_IDs;
|
||||||
|
|
||||||
|
// in the Room Manager, NOT the godot object ID
|
||||||
|
int m_LocalRoomID;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
@ -71,7 +68,7 @@ public:
|
|||||||
void MakePortalQuickList();
|
void MakePortalQuickList();
|
||||||
|
|
||||||
// main function
|
// main function
|
||||||
void DetermineVisibility_Recursive(int depth, const LCamera &cam, const Vector<Plane> &planes, ObjectID portalID_from = 0);
|
void DetermineVisibility_Recursive(int depth, const LCamera &cam, const Vector<Plane> &planes, Core::CoBitField_Dynamic &BF_visible, ObjectID portalID_from = 0);
|
||||||
|
|
||||||
// specific
|
// specific
|
||||||
public:
|
public:
|
||||||
@ -83,6 +80,7 @@ private:
|
|||||||
// void SetupPortal(LPortal * pPortal);
|
// void SetupPortal(LPortal * pPortal);
|
||||||
void MakeOppositePortal(LPortal * pPortalFrom, LRoom * pRoomTo);
|
void MakeOppositePortal(LPortal * pPortalFrom, LRoom * pRoomTo);
|
||||||
void DetectedPortalMesh(MeshInstance * pMeshInstance, String szLinkRoom);
|
void DetectedPortalMesh(MeshInstance * pMeshInstance, String szLinkRoom);
|
||||||
|
static void print(String sz);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,13 +22,32 @@
|
|||||||
#include "lportal.h"
|
#include "lportal.h"
|
||||||
#include "lroom.h"
|
#include "lroom.h"
|
||||||
#include "core/engine.h"
|
#include "core/engine.h"
|
||||||
|
#include "scene/3d/camera.h"
|
||||||
|
|
||||||
LRoomManager::LRoomManager()
|
LRoomManager::LRoomManager()
|
||||||
{
|
{
|
||||||
m_room_curr = 0;
|
m_room_curr = 0;
|
||||||
|
m_cameraID = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LRoomManager::set_camera(Node * pCam)
|
||||||
|
{
|
||||||
|
m_cameraID = 0;
|
||||||
|
|
||||||
|
if (!pCam)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Camera * pCamera = Object::cast_to<Camera>(pCam);
|
||||||
|
if (!pCamera)
|
||||||
|
{
|
||||||
|
WARN_PRINT("Not a camera");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cameraID = pCam->get_instance_id();
|
||||||
|
}
|
||||||
|
|
||||||
// convert empties and meshes to rooms and portals
|
// convert empties and meshes to rooms and portals
|
||||||
void LRoomManager::convert()
|
void LRoomManager::convert()
|
||||||
{
|
{
|
||||||
@ -52,7 +71,10 @@ void LRoomManager::Find_Rooms()
|
|||||||
// don't want to handle already converted rooms
|
// don't want to handle already converted rooms
|
||||||
LRoom * pRoom = Object::cast_to<LRoom>(pChild);
|
LRoom * pRoom = Object::cast_to<LRoom>(pChild);
|
||||||
if (pRoom)
|
if (pRoom)
|
||||||
|
{
|
||||||
|
pRoom->m_LocalRoomID = m_room_IDs.size();
|
||||||
m_room_IDs.push_back(pRoom->get_instance_id());
|
m_room_IDs.push_back(pRoom->get_instance_id());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_room_curr = 0;
|
m_room_curr = 0;
|
||||||
@ -63,6 +85,9 @@ void LRoomManager::Find_Rooms()
|
|||||||
m_room_curr = m_room_IDs[0];
|
m_room_curr = m_room_IDs[0];
|
||||||
print_line("first room ID is " + itos(m_room_curr));
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LRoomManager::Convert_Rooms()
|
void LRoomManager::Convert_Rooms()
|
||||||
@ -176,6 +201,12 @@ bool LRoomManager::Convert_Room(Spatial * pNode)
|
|||||||
|
|
||||||
void LRoomManager::FrameUpdate()
|
void LRoomManager::FrameUpdate()
|
||||||
{
|
{
|
||||||
|
if (Engine::get_singleton()->is_editor_hint())
|
||||||
|
{
|
||||||
|
WARN_PRINT_ONCE("LRoomManager::FrameUpdate should not be called in editor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// if not started
|
// if not started
|
||||||
if (!m_room_curr)
|
if (!m_room_curr)
|
||||||
return;
|
return;
|
||||||
@ -195,18 +226,51 @@ void LRoomManager::FrameUpdate()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_BF_visible_rooms.Blank();
|
||||||
|
|
||||||
LCamera cam;
|
LCamera cam;
|
||||||
cam.m_ptPos = Vector3(0, 0, 0);
|
cam.m_ptPos = Vector3(0, 0, 0);
|
||||||
cam.m_ptDir = Vector3 (-1, 0, 0);
|
cam.m_ptDir = Vector3 (-1, 0, 0);
|
||||||
|
|
||||||
Vector<Plane> planes;
|
Vector<Plane> planes;
|
||||||
|
|
||||||
pRoom->DetermineVisibility_Recursive(0, cam, planes);
|
// 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)
|
||||||
|
{
|
||||||
|
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 = pCamera->get_frustum();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pRoom->DetermineVisibility_Recursive(0, cam, planes, m_BF_visible_rooms);
|
||||||
|
|
||||||
|
|
||||||
|
// finally hide all the rooms that are currently visible but not in the visible bitfield as having been hit
|
||||||
|
// NOTE this could be more efficient
|
||||||
|
for (int n=0; n<m_room_IDs.size(); n++)
|
||||||
|
{
|
||||||
|
Object *pObj = ObjectDB::get_instance(m_room_IDs[n]);
|
||||||
|
|
||||||
|
LRoom * pRoom = Object::cast_to<LRoom>(pObj);
|
||||||
|
if (pRoom)
|
||||||
|
{
|
||||||
|
if (!m_BF_visible_rooms.GetBit(n))
|
||||||
|
{
|
||||||
|
pRoom->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// only do once for now
|
// only do once for now
|
||||||
m_room_curr = 0;
|
// m_room_curr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -219,6 +283,8 @@ void LRoomManager::_notification(int p_what) {
|
|||||||
// SetProcessing();
|
// SetProcessing();
|
||||||
if (!Engine::get_singleton()->is_editor_hint())
|
if (!Engine::get_singleton()->is_editor_hint())
|
||||||
set_process_internal(true);
|
set_process_internal(true);
|
||||||
|
else
|
||||||
|
set_process_internal(false);
|
||||||
|
|
||||||
// // we can't translate string name of Target to a node until we are in the tree
|
// // we can't translate string name of Target to a node until we are in the tree
|
||||||
// ResolveTargetPath();
|
// ResolveTargetPath();
|
||||||
@ -245,5 +311,6 @@ void LRoomManager::_notification(int p_what) {
|
|||||||
void LRoomManager::_bind_methods()
|
void LRoomManager::_bind_methods()
|
||||||
{
|
{
|
||||||
ClassDB::bind_method(D_METHOD("convert"), &LRoomManager::convert);
|
ClassDB::bind_method(D_METHOD("convert"), &LRoomManager::convert);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_camera"), &LRoomManager::set_camera);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scene/3d/spatial.h"
|
#include "scene/3d/spatial.h"
|
||||||
|
#include "CoBitField_Dynamic.h"
|
||||||
|
|
||||||
class LRoomManager : public Spatial {
|
class LRoomManager : public Spatial {
|
||||||
GDCLASS(LRoomManager, Spatial);
|
GDCLASS(LRoomManager, Spatial);
|
||||||
@ -35,12 +36,19 @@ class LRoomManager : public Spatial {
|
|||||||
Vector<ObjectID> m_room_IDs;
|
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;
|
||||||
|
// Vector<int> m_VisibleRoomList[2];
|
||||||
|
// int m_CurrentVisibleRoomList;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LRoomManager();
|
LRoomManager();
|
||||||
|
|
||||||
// convert empties and meshes to rooms and portals
|
// convert empties and meshes to rooms and portals
|
||||||
void convert();
|
void convert();
|
||||||
|
void set_camera(Node * pCam);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
Loading…
Reference in New Issue
Block a user