2019-09-15 16:39:01 +02:00
|
|
|
#pragma once
|
|
|
|
|
2019-09-18 12:04:02 +02:00
|
|
|
// Copyright (c) 2019 Lawnjelly
|
|
|
|
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
|
|
// in the Software without restriction, including without limitation the rights
|
|
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
|
|
// copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
// SOFTWARE.
|
|
|
|
|
|
|
|
/**
|
|
|
|
@author lawnjelly <lawnjelly@gmail.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2019-09-15 16:39:01 +02:00
|
|
|
#include "scene/3d/spatial.h"
|
|
|
|
#include "lvector.h"
|
|
|
|
#include "lportal.h"
|
|
|
|
|
|
|
|
class LRoomManager;
|
|
|
|
class LRoom;
|
2019-11-19 11:29:53 +01:00
|
|
|
class LArea;
|
2019-09-15 16:39:01 +02:00
|
|
|
class MeshInstance;
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
{
|
2019-09-15 17:16:09 +02:00
|
|
|
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;
|
2019-09-15 16:39:01 +02:00
|
|
|
}
|
|
|
|
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 LRoomConverter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
// temp rooms are used as an intermediate during conversion, because we need to convert the original portals
|
|
|
|
// and the mirror portals from 2 bits of code, and we want to end up with a final contiguous list of portals
|
|
|
|
// for efficient rendering.
|
|
|
|
class LTempRoom
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
LVector<LPortal> m_Portals;
|
|
|
|
};
|
|
|
|
|
|
|
|
// this function calls everything else in the converter
|
2019-11-20 11:31:39 +01:00
|
|
|
// single room mode enables us to emulate a room list in games that do not have rooms...
|
|
|
|
// this allows taking advantage of basic LPortal speedup without converting games / demos
|
|
|
|
void Convert(LRoomManager &manager, bool bVerbose, bool bPreparationRun, bool bDeleteLights, bool bSingleRoomMode = false);
|
2019-09-15 16:39:01 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
int CountRooms();
|
|
|
|
|
|
|
|
void Convert_Rooms();
|
2019-11-19 11:29:53 +01:00
|
|
|
int Convert_Rooms_Recursive(Node * pParent, int count, int area);
|
|
|
|
bool Convert_Room(Spatial * pNode, int lroomID, int areaID);
|
2019-09-17 10:32:18 +02:00
|
|
|
void Convert_Room_FindObjects_Recursive(Node * pParent, LRoom &lroom, LAABB &bb_room);
|
2019-10-09 12:33:19 +02:00
|
|
|
void Convert_Room_SetDefaultCullMask_Recursive(Node * pParent);
|
2020-01-27 20:56:46 +01:00
|
|
|
bool Convert_IsVisibleInRooms(const Node * pNode) const;
|
2019-09-17 10:32:18 +02:00
|
|
|
|
2019-09-15 16:39:01 +02:00
|
|
|
void Convert_Portals();
|
2019-09-17 15:30:31 +02:00
|
|
|
void Convert_Bounds();
|
2020-01-09 14:35:50 +01:00
|
|
|
bool Convert_ManualBound(LRoom &lroom, MeshInstance * pMI);
|
|
|
|
void GetWorldVertsFromMesh(const MeshInstance &mi, Vector<Vector3> &pts) const;
|
|
|
|
void Bound_FindPoints_Recursive(Node * pNode, Vector<Vector3> &pts);
|
|
|
|
bool Convert_Bound_FromPoints(LRoom &lroom, const Vector<Vector3> &points);
|
2019-09-26 09:53:15 +02:00
|
|
|
void Convert_ShadowCasters();
|
2019-10-09 12:33:19 +02:00
|
|
|
void Convert_Lights();
|
2019-11-19 11:29:53 +01:00
|
|
|
void Convert_AreaLights();
|
2019-09-15 16:39:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
void LRoom_DetectPortalMeshes(LRoom &lroom, LTempRoom &troom);
|
|
|
|
void LRoom_MakePortalsTwoWay(LRoom &lroom, LTempRoom &troom, int iRoomNum);
|
|
|
|
void LRoom_MakePortalFinalList(LRoom &lroom, LTempRoom &troom);
|
|
|
|
void LRoom_DetectedPortalMesh(LRoom &lroom, LTempRoom &troom, MeshInstance * pMeshInstance, String szLinkRoom);
|
|
|
|
LPortal * LRoom_RequestNewPortal(LRoom &lroom);
|
2019-09-24 19:33:55 +02:00
|
|
|
void LRoom_PushBackSOB(LRoom &lroom, const LSob &sob);
|
2019-09-26 19:33:40 +02:00
|
|
|
|
2019-10-09 12:33:19 +02:00
|
|
|
// lights
|
|
|
|
void LRoom_DetectedLight(LRoom &lroom, Node * pNode);
|
|
|
|
void Light_Trace(int iLightID);
|
2019-11-19 11:29:53 +01:00
|
|
|
void LRoom_DetectedArea(LRoom &lroom, Node * pNode);
|
2019-10-09 12:33:19 +02:00
|
|
|
|
2019-09-26 19:33:40 +02:00
|
|
|
// shadows
|
|
|
|
void LRoom_FindShadowCasters_FromLight(LRoom &lroom, const LLight &light);
|
|
|
|
void LRoom_FindShadowCasters_Recursive(LRoom &source_lroom, int depth, LRoom &lroom, const LLight &light, const LVector<Plane> &planes);
|
|
|
|
void LRoom_AddShadowCaster_SOB(LRoom &lroom, int sobID);
|
2019-09-15 16:39:01 +02:00
|
|
|
|
2019-10-09 12:33:19 +02:00
|
|
|
|
2019-09-15 16:39:01 +02:00
|
|
|
void TRoom_MakeOppositePortal(const LPortal &port, int iRoomOrig);
|
|
|
|
|
|
|
|
|
|
|
|
// helper
|
|
|
|
bool Node_IsRoom(Node * pNode) const;
|
2019-11-19 11:29:53 +01:00
|
|
|
bool Node_IsArea(Node * pNode) const;
|
2019-09-17 15:30:31 +02:00
|
|
|
bool Node_IsPortal(Node * pNode) const;
|
|
|
|
bool Node_IsBound(Node * pNode) const;
|
|
|
|
bool Node_IsIgnore(Node * pNode) const;
|
2019-10-09 12:33:19 +02:00
|
|
|
bool Node_IsLight(Node * pNode) const;
|
2019-09-17 15:30:31 +02:00
|
|
|
|
2019-09-15 16:39:01 +02:00
|
|
|
int FindRoom_ByName(String szName) const;
|
2019-11-19 11:29:53 +01:00
|
|
|
int Area_FindOrCreate(String szName);
|
2019-09-15 16:39:01 +02:00
|
|
|
|
2019-09-17 15:30:31 +02:00
|
|
|
|
2019-10-22 21:44:17 +02:00
|
|
|
// set up on entry
|
2019-09-15 16:39:01 +02:00
|
|
|
LRoomManager * m_pManager;
|
2019-10-22 21:44:17 +02:00
|
|
|
Spatial * m_pRoomList; // room list pointed to by the manager nodepath
|
|
|
|
|
2019-09-15 16:39:01 +02:00
|
|
|
LVector<LTempRoom> m_TempRooms;
|
|
|
|
|
2019-09-17 15:30:31 +02:00
|
|
|
bool Bound_AddPlaneIfUnique(LVector<Plane> &planes, const Plane &p);
|
|
|
|
|
2019-10-22 21:44:17 +02:00
|
|
|
|
|
|
|
// whether we are preparing the level, or doing a final run,
|
|
|
|
// in which case we should delete lights and set vis flags
|
|
|
|
bool m_bFinalRun;
|
|
|
|
bool m_bDeleteLights;
|
2019-11-20 11:31:39 +01:00
|
|
|
bool m_bSingleRoomMode;
|
2019-09-15 16:39:01 +02:00
|
|
|
};
|