Exemplo n.º 1
0
void cBFSPieceGenerator::PlacePieces(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MaxDepth, cPlacedPieces & a_OutPieces)
{
	a_OutPieces.clear();
	cFreeConnectors ConnectorPool;
	
	// 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();
	Hitbox.Sort();
	printf("  Hitbox: {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)\n",
		Hitbox.p1.x, Hitbox.p1.y, Hitbox.p1.z,
		Hitbox.p2.x, Hitbox.p2.y, Hitbox.p2.z,
		Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1
	);
	DebugConnectorPool(ConnectorPool, 0);
	//*/
	
	// Place pieces at the available connectors:
	/*
	Instead of removing them one by one from the pool, we process them sequentially and take note of the last
	processed one. To save on memory, once the number of processed connectors reaches a big number, a chunk
	of the connectors is removed.
	*/
	size_t NumProcessed = 0;
	while (ConnectorPool.size() > NumProcessed)
	{
		cFreeConnector & Conn = ConnectorPool[NumProcessed];
		if (Conn.m_Piece->GetDepth() < a_MaxDepth)
		{
			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());
				cCuboid Hitbox = NewPiece->GetHitBox();
				Hitbox.Sort();
				printf("  Hitbox: {%d, %d, %d} - {%d, %d, %d} (%d * %d * %d)\n",
					Hitbox.p1.x, Hitbox.p1.y, Hitbox.p1.z,
					Hitbox.p2.x, Hitbox.p2.y, Hitbox.p2.z,
					Hitbox.DifX() + 1, Hitbox.DifY() + 1, Hitbox.DifZ() + 1
				);
				DebugConnectorPool(ConnectorPool, NumProcessed + 1);
				//*/
			}
		}
		NumProcessed++;
		if (NumProcessed > 1000)
		{
			ConnectorPool.erase(ConnectorPool.begin(), ConnectorPool.begin() + NumProcessed);
			NumProcessed = 0;
		}
	}
}
Exemplo n.º 2
0
	// cGridStructGen::cStructure overrides:
	virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
	{
		for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
		{
			cPrefab & Prefab = (cPrefab &)((*itr)->GetPiece());
			Prefab.Draw(a_Chunk, *itr);
		}  // for itr - m_PlacedPieces[]
	}
Exemplo n.º 3
0
void cPieceGenerator::FreePieces(cPlacedPieces & a_PlacedPieces)
{
	for (cPlacedPieces::iterator itr = a_PlacedPieces.begin(), end = a_PlacedPieces.end(); itr != end; ++itr)
	{
		delete *itr;
	}  // for itr - a_PlacedPieces[]
	a_PlacedPieces.clear();
}
Exemplo n.º 4
0
bool cPieceGenerator::CheckConnection(
	const cPiece::cConnector & a_ExistingConnector,
	const Vector3i & a_ToPos,
	const cPiece & a_Piece,
	const cPiece::cConnector & a_NewConnector,
	int a_NumCCWRotations,
	const cPlacedPieces & a_OutPieces
)
{
	// 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))
		{
			return false;
		}
	}
	return true;
}
Exemplo n.º 5
0
	// cGridStructGen::cStructure overrides:
	virtual void DrawIntoChunk(cChunkDesc & a_Chunk) override
	{
		// Iterate over all items
		// Each intersecting prefab is placed on ground, then drawn
		// Each intersecting road is drawn by replacing top soil blocks with gravel / sandstone blocks
		cChunkDef::HeightMap HeightMap;  // Heightmap for this chunk, used by roads
		m_HeightGen->GenHeightMap(a_Chunk.GetChunkX(), a_Chunk.GetChunkZ(), HeightMap);
		for (cPlacedPieces::iterator itr = m_Pieces.begin(), end = m_Pieces.end(); itr != end; ++itr)
		{
			cPrefab & Prefab = (cPrefab &)((*itr)->GetPiece());
			if ((*itr)->GetPiece().GetSize().y == 1)
			{
				// It's a road, special handling (change top terrain blocks to m_RoadBlock)
				DrawRoad(a_Chunk, **itr, HeightMap);
				continue;
			}
			if (Prefab.ShouldMoveToGround() && !(*itr)->HasBeenMovedToGround())
			{
				PlacePieceOnGround(**itr);
			}
			Prefab.Draw(a_Chunk, *itr);
		}  // for itr - m_PlacedPieces[]
	}
Exemplo n.º 6
0
	void MoveAllDescendants(cPlacedPieces & a_PlacedPieces, size_t a_Pivot, int a_HeightDifference)
	{
		size_t num = a_PlacedPieces.size();
		cPlacedPiece * Pivot = a_PlacedPieces[a_Pivot];
		for (size_t i = a_Pivot + 1; i < num; i++)
		{
			if (
				(a_PlacedPieces[i]->GetParent() == Pivot) &&  // It is a direct dependant of the pivot
				!((const cPrefab &)a_PlacedPieces[i]->GetPiece()).ShouldMoveToGround()  // It attaches strictly by connectors
			)
			{
				a_PlacedPieces[i]->MoveToGroundBy(a_HeightDifference);
				MoveAllDescendants(a_PlacedPieces, i, a_HeightDifference);
			}
		}  // for i - a_PlacedPieces[]
	}
Exemplo n.º 7
0
	cNetherFort(cNetherFortGen & a_ParentGen, int a_OriginX, int a_OriginZ, int a_GridSize, int a_MaxDepth, int a_Seed) :
		super(a_OriginX, a_OriginZ),
		m_ParentGen(a_ParentGen),
		m_GridSize(a_GridSize),
		m_Seed(a_Seed)
	{
		// TODO: Proper Y-coord placement
		int BlockY = 64;
		
		// Generate pieces:
		for (int i = 0; m_Pieces.size() < (size_t)(a_MaxDepth * a_MaxDepth / 8 + a_MaxDepth); i++)
		{
			cBFSPieceGenerator pg(cNetherFortGen::m_PiecePool, a_Seed + i);
			pg.PlacePieces(a_OriginX, BlockY, a_OriginZ, a_MaxDepth, m_Pieces);
		}
	}
Exemplo n.º 8
0
bool cPieceGenerator::TryPlacePieceAtConnector(
	const cPlacedPiece & a_ParentPiece,
	const cPiece::cConnector & a_Connector,
	cPlacedPieces & a_OutPieces,
	cPieceGenerator::cFreeConnectors & a_OutConnectors
)
{
	// Translation of direction - direction -> number of CCW rotations needed:
	// You need DirectionRotationTable[rot1][rot2] CCW turns to connect rot1 to rot2 (they are opposite)
	static const int DirectionRotationTable[6][6] =
	{
		/*         YM, YP, ZM, ZP, XM, XP */
		/* YM */ { 0,  0,  0,  0,  0,  0},
		/* YP */ { 0,  0,  0,  0,  0,  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:
	const int * RotTable = DirectionRotationTable[a_Connector.m_Direction];
	cConnections Connections;
	cPieces AvailablePieces = m_PiecePool.GetPiecesWithConnector(a_Connector.m_Type);
	Connections.reserve(AvailablePieces.size());
	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);
	int WeightTotal = 0;
	for (cPieces::iterator itrP = AvailablePieces.begin(), endP = AvailablePieces.end(); itrP != endP; ++itrP)
	{
		// Get the relative chance of this piece being generated in this path:
		int Weight = m_PiecePool.GetPieceWeight(a_ParentPiece, a_Connector, **itrP);
		if (Weight <= 0)
		{
			continue;
		}
		
		// Try fitting each of the piece's connector:
		cPiece::cConnectors Connectors = (*itrP)->GetConnectors();
		for (cPiece::cConnectors::iterator itrC = Connectors.begin(), endC = Connectors.end(); itrC != endC; ++itrC)
		{
			if (itrC->m_Type != a_Connector.m_Type)
			{
				continue;
			}
			// This is a same-type connector, find out how to rotate to it:
			int NumCCWRotations = RotTable[itrC->m_Direction];
			if (!(*itrP)->CanRotateCCW(NumCCWRotations))
			{
				// Doesn't support this rotation
				continue;
			}
			if (!CheckConnection(a_Connector, ConnPos, **itrP, *itrC, NumCCWRotations, a_OutPieces))
			{
				// Doesn't fit in this rotation
				continue;
			}
			// Fits, add it to list of possibile connections:
			Connections.push_back(cConnection(**itrP, *itrC, NumCCWRotations, Weight));
			WeightTotal += Weight;
		}  // for itrC - Connectors[]
	}  // for itrP - AvailablePieces[]
	if (Connections.empty())
	{
		// No available connections, bail out
		return false;
	}
	ASSERT(WeightTotal > 0);
	
	// Choose a random connection from the list, based on the weights:
	int rnd = (m_Noise.IntNoise3DInt(a_Connector.m_Pos.x, a_Connector.m_Pos.y, a_Connector.m_Pos.z) / 7) % WeightTotal;
	size_t ChosenIndex = 0;
	for (cConnections::const_iterator itr = Connections.begin(), end = Connections.end(); itr != end; ++itr, ++ChosenIndex)
	{
		rnd -= itr->m_Weight;
		if (rnd <= 0)
		{
			// This is the piece to choose
			break;
		}
	}
	cConnection & Conn = Connections[ChosenIndex];
	
	// Place the piece:
	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);
	a_OutPieces.push_back(PlacedPiece);
	
	// Add the new piece's connectors to the list of free connectors:
	cPiece::cConnectors Connectors = Conn.m_Piece->GetConnectors();
	for (cPiece::cConnectors::const_iterator itr = Connectors.begin(), end = Connectors.end(); itr != end; ++itr)
	{
		if (itr->m_Pos.Equals(Conn.m_Connector.m_Pos))
		{
			// This is the connector through which we have been connected to the parent, don't add
			continue;
		}
		a_OutConnectors.push_back(cFreeConnector(PlacedPiece, Conn.m_Piece->RotateMoveConnector(*itr, Conn.m_NumCCWRotations, ConnPos.x, ConnPos.y, ConnPos.z)));
	}
	
	return true;
}