A working POCPiece generator.
parent
dacb6cef1d
commit
0e985293b5
|
@ -22,6 +22,7 @@
|
|||
#include "EndGen.h"
|
||||
#include "MineShafts.h"
|
||||
#include "Noise3DGenerator.h"
|
||||
#include "POCPieceGenerator.h"
|
||||
#include "Ravines.h"
|
||||
|
||||
|
||||
|
@ -364,6 +365,10 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
|||
{
|
||||
m_FinishGens.push_back(new cStructGenOreNests(Seed));
|
||||
}
|
||||
else if (NoCaseCompare(*itr, "POCPieces") == 0)
|
||||
{
|
||||
m_FinishGens.push_back(new cPOCPieceGenerator(Seed));
|
||||
}
|
||||
else if (NoCaseCompare(*itr, "PreSimulator") == 0)
|
||||
{
|
||||
m_FinishGens.push_back(new cFinishGenPreSimulator);
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
|
||||
// POCPieceGenerator.cpp
|
||||
|
||||
// Implements the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique
|
||||
// The generator generates a maze of rooms at {0, 100, 0}
|
||||
|
||||
#include "Globals.h"
|
||||
#include "POCPieceGenerator.h"
|
||||
#include "ChunkDesc.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** POC pieces are simple boxes that have connectors in the middle of their walls.
|
||||
Each wall has one connector, there are 3 connector types that get assigned semi-randomly.
|
||||
The piece also knows how to imprint itself in a cChunkDesc, each piece has a different color glass
|
||||
and each connector is uses a different color wool frame. */
|
||||
class cPOCPiece :
|
||||
public cPiece
|
||||
{
|
||||
public:
|
||||
cPOCPiece(int a_Size) :
|
||||
m_Size(a_Size)
|
||||
{
|
||||
m_Connectors.push_back(cConnector(m_Size / 2, 1, 0, 0, BLOCK_FACE_ZM));
|
||||
m_Connectors.push_back(cConnector(m_Size / 2, 1, m_Size - 1, 1, BLOCK_FACE_ZP));
|
||||
m_Connectors.push_back(cConnector(0, 1, m_Size / 2, 2, BLOCK_FACE_XM));
|
||||
m_Connectors.push_back(cConnector(m_Size - 1, 1, m_Size / 2, m_Size % 3, BLOCK_FACE_XP));
|
||||
}
|
||||
|
||||
|
||||
/** Imprints the piece in the specified chunk. Assumes they intersect. */
|
||||
void ImprintInChunk(cChunkDesc & a_ChunkDesc, const Vector3i & a_Pos, int a_NumCCWRotations)
|
||||
{
|
||||
int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
|
||||
int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
|
||||
Vector3i Min = a_Pos;
|
||||
Min.Move(-BlockX, 0, -BlockZ);
|
||||
Vector3i Max = Min;
|
||||
Max.Move(m_Size - 1, 2, m_Size - 1);
|
||||
ASSERT(Min.x < cChunkDef::Width);
|
||||
ASSERT(Min.z < cChunkDef::Width);
|
||||
ASSERT(Max.x >= 0);
|
||||
ASSERT(Max.z >= 0);
|
||||
if (Min.x >= 0)
|
||||
{
|
||||
// Draw the XM wall:
|
||||
a_ChunkDesc.FillRelCuboid(Min.x, Min.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16);
|
||||
}
|
||||
if (Min.z >= 0)
|
||||
{
|
||||
// Draw the ZM wall:
|
||||
a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Min.z, Min.z, E_BLOCK_STAINED_GLASS, m_Size % 16);
|
||||
}
|
||||
if (Max.x < cChunkDef::Width)
|
||||
{
|
||||
// Draw the XP wall:
|
||||
a_ChunkDesc.FillRelCuboid(Max.x, Max.x, Min.y, Max.y, Min.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16);
|
||||
}
|
||||
if (Max.z < cChunkDef::Width)
|
||||
{
|
||||
// Draw the ZP wall:
|
||||
a_ChunkDesc.FillRelCuboid(Min.x, Max.x, Min.y, Max.y, Max.z, Max.z, E_BLOCK_STAINED_GLASS, m_Size % 16);
|
||||
}
|
||||
|
||||
// Draw all the connectors:
|
||||
for (cConnectors::const_iterator itr = m_Connectors.begin(), end = m_Connectors.end(); itr != end; ++itr)
|
||||
{
|
||||
cConnector Conn = cPiece::RotateMoveConnector(*itr, a_NumCCWRotations, a_Pos.x, a_Pos.y, a_Pos.z);
|
||||
Conn.m_Pos.Move(-BlockX, 0, -BlockZ);
|
||||
if (
|
||||
(Conn.m_Pos.x >= 0) && (Conn.m_Pos.x < cChunkDef::Width) &&
|
||||
(Conn.m_Pos.z >= 0) && (Conn.m_Pos.z < cChunkDef::Width)
|
||||
)
|
||||
{
|
||||
a_ChunkDesc.SetBlockTypeMeta(Conn.m_Pos.x, Conn.m_Pos.y, Conn.m_Pos.z, E_BLOCK_WOOL, itr->m_Type % 16);
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: Frame the connectors
|
||||
switch (itr->m_Direction)
|
||||
{
|
||||
case BLOCK_FACE_XM:
|
||||
case BLOCK_FACE_XP:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
|
||||
case BLOCK_FACE_ZM:
|
||||
case BLOCK_FACE_ZP:
|
||||
{
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
} // for itr - m_Connectors[]
|
||||
}
|
||||
|
||||
protected:
|
||||
int m_Size;
|
||||
cConnectors m_Connectors;
|
||||
|
||||
// cPiece overrides:
|
||||
virtual cConnectors GetConnectors(void) const override
|
||||
{
|
||||
return m_Connectors;
|
||||
}
|
||||
|
||||
virtual Vector3i GetSize(void) const override
|
||||
{
|
||||
return Vector3i(m_Size, 3, m_Size);
|
||||
}
|
||||
|
||||
virtual cCuboid GetHitBox(void) const override
|
||||
{
|
||||
return cCuboid(0, 0, 0, m_Size - 1, 2, m_Size - 1);
|
||||
}
|
||||
|
||||
virtual bool CanRotateCCW(int a_NumRotations) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void DebugPieces(const cPlacedPieces & a_Pieces)
|
||||
{
|
||||
size_t idx = 0;
|
||||
for (cPlacedPieces::const_iterator itr = a_Pieces.begin(), end = a_Pieces.end(); itr != end; ++itr, ++idx)
|
||||
{
|
||||
const cCuboid & HitBox = (*itr)->GetHitBox();
|
||||
printf(" %u: %d rotations, {%d - %d, %d - %d}\n",
|
||||
idx, (*itr)->GetNumCCWRotations(),
|
||||
HitBox.p1.x, HitBox.p2.x, HitBox.p1.z, HitBox.p2.z
|
||||
);
|
||||
} // for itr - a_Pieces[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cPOCPieceGenerator:
|
||||
|
||||
cPOCPieceGenerator::cPOCPieceGenerator(int a_Seed) :
|
||||
m_Seed(a_Seed)
|
||||
{
|
||||
// Prepare a vector of available pieces:
|
||||
m_AvailPieces.push_back(new cPOCPiece(5));
|
||||
m_AvailPieces.push_back(new cPOCPiece(7));
|
||||
m_AvailPieces.push_back(new cPOCPiece(9));
|
||||
|
||||
// Generate the structure:
|
||||
cBFSPieceGenerator Gen(*this, a_Seed);
|
||||
Gen.PlacePieces(0, 50, 0, 6, m_Pieces);
|
||||
|
||||
// DebugPieces(m_Pieces);
|
||||
|
||||
// Get the smallest cuboid encompassing the entire generated structure:
|
||||
cCuboid Bounds(0, 50, 0, 0, 50, 0);
|
||||
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
|
||||
{
|
||||
Vector3i MinCoords = (*itr)->GetCoords();
|
||||
Bounds.Engulf(MinCoords);
|
||||
Bounds.Engulf(MinCoords + (*itr)->GetPiece().GetSize());
|
||||
} // for itr - m_Pieces[]
|
||||
m_Bounds = Bounds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPOCPieceGenerator::~cPOCPieceGenerator()
|
||||
{
|
||||
cPieceGenerator::FreePieces(m_Pieces);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPOCPieceGenerator::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
|
||||
int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
|
||||
if (
|
||||
(BlockX + 16 < m_Bounds.p1.x) || (BlockX > m_Bounds.p2.x) || // X coords out of bounds of the generated structure
|
||||
(BlockZ + 16 < m_Bounds.p1.z) || (BlockZ > m_Bounds.p2.z) // Z coords out of bounds of the generated structure
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Imprint each piece in the chunk:
|
||||
for (cPlacedPieces::const_iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
|
||||
{
|
||||
const Vector3i & Pos = (*itr)->GetCoords();
|
||||
Vector3i Size = (*itr)->GetPiece().GetSize();
|
||||
if (((*itr)->GetNumCCWRotations() % 2) == 1)
|
||||
{
|
||||
std::swap(Size.x, Size.z);
|
||||
}
|
||||
if (
|
||||
(Pos.x >= BlockX + 16) || (Pos.x + Size.x - 1 < BlockX) ||
|
||||
(Pos.z >= BlockZ + 16) || (Pos.z + Size.z - 1 < BlockZ)
|
||||
)
|
||||
{
|
||||
// This piece doesn't intersect the chunk
|
||||
continue;
|
||||
}
|
||||
|
||||
((cPOCPiece &)(*itr)->GetPiece()).ImprintInChunk(a_ChunkDesc, Pos, (*itr)->GetNumCCWRotations());
|
||||
} // for itr - m_Pieces[]
|
||||
a_ChunkDesc.UpdateHeightmap();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPieces cPOCPieceGenerator::GetPiecesWithConnector(int a_ConnectorType)
|
||||
{
|
||||
// Each piece has each connector
|
||||
return m_AvailPieces;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cPieces cPOCPieceGenerator::GetStartingPieces(void)
|
||||
{
|
||||
// Any piece can be a starting piece
|
||||
return m_AvailPieces;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPOCPieceGenerator::PiecePlaced(const cPiece & a_Piece)
|
||||
{
|
||||
UNUSED(a_Piece);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPOCPieceGenerator::Reset(void)
|
||||
{
|
||||
// Nothing needed
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
|
||||
// POCPieceGenerator.h
|
||||
|
||||
// Declares the cPOCPieceGenerator class representing a Proof-Of_Concept structure generator using the cPieceGenerator technique
|
||||
// The generator generates a maze of rooms at {0, 100, 0}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "PieceGenerator.h"
|
||||
#include "ComposableGenerator.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cPOCPieceGenerator :
|
||||
public cFinishGen,
|
||||
protected cPiecePool
|
||||
{
|
||||
public:
|
||||
cPOCPieceGenerator(int a_Seed);
|
||||
~cPOCPieceGenerator();
|
||||
|
||||
protected:
|
||||
int m_Seed;
|
||||
|
||||
/** The pieces from which the generated structure is built. */
|
||||
cPieces m_AvailPieces;
|
||||
|
||||
/** The placed pieces of the generated structure. */
|
||||
cPlacedPieces m_Pieces;
|
||||
|
||||
/** Bounds of the complete structure, to save on processing outside chunks. */
|
||||
cCuboid m_Bounds;
|
||||
|
||||
|
||||
// cFinishGen overrides:
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
|
||||
// cPiecePool overrides:
|
||||
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) override;
|
||||
virtual cPieces GetStartingPieces(void) override;
|
||||
virtual void PiecePlaced(const cPiece & a_Piece) override;
|
||||
virtual void Reset(void) override;
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
|
||||
|
||||
#ifdef SELF_TEST
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Self-test:
|
||||
|
||||
|
@ -132,6 +134,8 @@ protected:
|
|||
}
|
||||
} g_Test;
|
||||
|
||||
#endif // SELF_TEST
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -287,6 +291,7 @@ cPlacedPiece::cPlacedPiece(const cPlacedPiece * a_Parent, const cPiece & a_Piece
|
|||
{
|
||||
m_Depth = (m_Parent == NULL) ? 0 : (m_Parent->GetDepth() + 1);
|
||||
m_HitBox = a_Piece.RotateMoveHitBox(a_NumCCWRotations, a_Coords.x, a_Coords.y, a_Coords.z);
|
||||
m_HitBox.Sort();
|
||||
}
|
||||
|
||||
|
||||
|
@ -375,10 +380,10 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
|||
/* YM, YP, ZM, ZP, XM, XP
|
||||
/* YM */ { 0, 0, 0, 0, 0, 0},
|
||||
/* YP */ { 0, 0, 0, 0, 0, 0},
|
||||
/* ZM */ { 0, 0, 0, 2, 1, 3},
|
||||
/* ZP */ { 0, 0, 2, 0, 3, 1},
|
||||
/* XM */ { 0, 0, 3, 1, 0, 2},
|
||||
/* XP */ { 0, 0, 1, 3, 2, 0},
|
||||
/* ZM */ { 0, 0, 2, 0, 1, 3},
|
||||
/* ZP */ { 0, 0, 0, 2, 3, 1},
|
||||
/* XM */ { 0, 0, 3, 1, 2, 0},
|
||||
/* XP */ { 0, 0, 1, 3, 0, 2},
|
||||
};
|
||||
|
||||
// Get a list of available connections:
|
||||
|
@ -389,8 +394,10 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
|||
Vector3i ConnPos = a_Connector.m_Pos; // The position at which the new connector should be placed - 1 block away from the connector
|
||||
AddFaceDirection(ConnPos.x, ConnPos.y, ConnPos.z, a_Connector.m_Direction);
|
||||
|
||||
/*
|
||||
// DEBUG:
|
||||
printf("Placing piece at pos {%d, %d, %d}, direction %s\n", ConnPos.x, ConnPos.y, ConnPos.z, BlockFaceToString(a_Connector.m_Direction).c_str());
|
||||
printf("Placing piece at connector pos {%d, %d, %d}, direction %s\n", ConnPos.x, ConnPos.y, ConnPos.z, BlockFaceToString(a_Connector.m_Direction).c_str());
|
||||
//*/
|
||||
|
||||
for (cPieces::iterator itrP = AvailablePieces.begin(), endP = AvailablePieces.end(); itrP != endP; ++itrP)
|
||||
{
|
||||
|
@ -427,11 +434,15 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
|||
cConnection & Conn = Connections[rnd % Connections.size()];
|
||||
|
||||
// Place the piece:
|
||||
/*
|
||||
// DEBUG
|
||||
printf("Chosen connector at {%d, %d, %d}, direction %s, needs %d rotations\n",
|
||||
Conn.m_Connector.m_Pos.x, Conn.m_Connector.m_Pos.y, Conn.m_Connector.m_Pos.z,
|
||||
BlockFaceToString(Conn.m_Connector.m_Direction).c_str(),
|
||||
Conn.m_NumCCWRotations
|
||||
);
|
||||
//*/
|
||||
|
||||
Vector3i NewPos = Conn.m_Piece->RotatePos(Conn.m_Connector.m_Pos, Conn.m_NumCCWRotations);
|
||||
ConnPos -= NewPos;
|
||||
cPlacedPiece * PlacedPiece = new cPlacedPiece(&a_ParentPiece, *(Conn.m_Piece), ConnPos, Conn.m_NumCCWRotations);
|
||||
|
@ -440,8 +451,10 @@ bool cPieceGenerator::TryPlacePieceAtConnector(
|
|||
// Add the new piece's connectors to the list of free connectors:
|
||||
cPiece::cConnectors Connectors = Conn.m_Piece->GetConnectors();
|
||||
|
||||
/*
|
||||
// DEBUG:
|
||||
printf("Adding %u connectors to the pool\n", Connectors.size() - 1);
|
||||
//*/
|
||||
|
||||
for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr)
|
||||
{
|
||||
|
@ -471,6 +484,7 @@ bool cPieceGenerator::CheckConnection(
|
|||
{
|
||||
// For each placed piece, test the hitbox against the new piece:
|
||||
cCuboid RotatedHitBox = a_Piece.RotateHitBoxToConnector(a_NewConnector, a_ToPos, a_NumCCWRotations);
|
||||
RotatedHitBox.Sort();
|
||||
for (cPlacedPieces::const_iterator itr = a_OutPieces.begin(), end = a_OutPieces.end(); itr != end; ++itr)
|
||||
{
|
||||
if ((*itr)->GetHitBox().DoesIntersect(RotatedHitBox))
|
||||
|
@ -485,6 +499,7 @@ bool cPieceGenerator::CheckConnection(
|
|||
|
||||
|
||||
|
||||
//*
|
||||
// DEBUG:
|
||||
void cPieceGenerator::DebugConnectorPool(const cPieceGenerator::cFreeConnectors & a_ConnectorPool, size_t a_NumProcessed)
|
||||
{
|
||||
|
@ -501,6 +516,7 @@ void cPieceGenerator::DebugConnectorPool(const cPieceGenerator::cFreeConnectors
|
|||
);
|
||||
} // for itr - a_ConnectorPool[]
|
||||
}
|
||||
//*/
|
||||
|
||||
|
||||
|
||||
|
@ -553,6 +569,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
|
|||
// Place the starting piece:
|
||||
a_OutPieces.push_back(PlaceStartingPiece(a_BlockX, a_BlockY, a_BlockZ, ConnectorPool));
|
||||
|
||||
/*
|
||||
// DEBUG:
|
||||
printf("Placed the starting piece at {%d, %d, %d}\n", a_BlockX, a_BlockY, a_BlockZ);
|
||||
cCuboid Hitbox = a_OutPieces[0]->GetHitBox();
|
||||
|
@ -563,6 +580,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
|
|||
Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1
|
||||
);
|
||||
DebugConnectorPool(ConnectorPool, 0);
|
||||
//*/
|
||||
|
||||
// Place pieces at the available connectors:
|
||||
/*
|
||||
|
@ -578,6 +596,8 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
|
|||
{
|
||||
if (TryPlacePieceAtConnector(*Conn.m_Piece, Conn.m_Connector, a_OutPieces, ConnectorPool))
|
||||
{
|
||||
/*
|
||||
// DEBUG:
|
||||
const cPlacedPiece * NewPiece = a_OutPieces.back();
|
||||
const Vector3i & Coords = NewPiece->GetCoords();
|
||||
printf("Placed a new piece at {%d, %d, %d}, rotation %d\n", Coords.x, Coords.y, Coords.z, NewPiece->GetNumCCWRotations());
|
||||
|
@ -589,6 +609,7 @@ void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, i
|
|||
Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1
|
||||
);
|
||||
DebugConnectorPool(ConnectorPool, NumProcessed + 1);
|
||||
//*/
|
||||
}
|
||||
}
|
||||
NumProcessed++;
|
||||
|
|
|
@ -30,6 +30,9 @@ Each uses a slightly different approach to generating:
|
|||
class cPiece
|
||||
{
|
||||
public:
|
||||
// Force a virtual destructor in all descendants
|
||||
virtual ~cPiece() {}
|
||||
|
||||
struct cConnector
|
||||
{
|
||||
/** Position relative to the piece */
|
||||
|
@ -82,9 +85,14 @@ typedef std::vector<cPiece *> cPieces;
|
|||
|
||||
|
||||
|
||||
/** This class is an interface that provides pieces for the generator. It can keep track of what pieces were
|
||||
placed and adjust the returned piece vectors. */
|
||||
class cPiecePool
|
||||
{
|
||||
public:
|
||||
// Force a virtual destructor in all descendants:
|
||||
virtual ~cPiecePool() {}
|
||||
|
||||
/** Returns a list of pieces that contain the specified connector type.
|
||||
The cPiece pointers returned are managed by the pool and the caller doesn't free them. */
|
||||
virtual cPieces GetPiecesWithConnector(int a_ConnectorType) = 0;
|
||||
|
@ -140,7 +148,7 @@ public:
|
|||
|
||||
/** Cleans up all the memory used by the placed pieces.
|
||||
Call this utility function instead of freeing the items on your own. */
|
||||
void FreePieces(cPlacedPieces & a_PlacedPieces);
|
||||
static void FreePieces(cPlacedPieces & a_PlacedPieces);
|
||||
|
||||
protected:
|
||||
/** The type used for storing a connection from one piece to another, while building the piece tree. */
|
||||
|
|
Loading…
Reference in New Issue