Пример #1
0
uint32
BaseZone::GetTerraHeightAtLoc (uint32 x, uint32 y)
{
	x -= min_.x;
	y -= min_.y;
	Assert (x < GetLengthX ());
	Assert (y < GetLengthY ());
	return (uint32)revisedHeightMap_[x + y * GetLengthX ()];
}
Пример #2
0
void
DisplayRoom::PlaceObjects( )
{
	if (rand () % 2 == 0)
	{
		S_BaseFurniture* table = (S_BaseFurniture*)GetServerEntityList()->Create( "table" );
		table->SetBOrigin( UPoint3D( min_.x + 1 + (rand () % GetLengthX() - 1), min_.y + 1 + (rand () % GetLengthY() - 1), min_.z ) );
	}
	else
	{
		S_BaseFurniture* chair = (S_BaseFurniture*)GetServerEntityList()->Create( "chair" );
		chair->SetBOrigin( UPoint3D( min_.x + 1 + (rand () % GetLengthX() - 1), min_.y + 1 + (rand () % GetLengthY() - 1), min_.z ) );
	}

	BaseRoom::PlaceObjects();
}
Пример #3
0
void
RoofTop::BuildWalls( )
{
	uint32 sCubeBuf;

	// open roof and parapet construction
	if (parentBuilding_->GetRoofType () == ROOF_OPENPARAPETS)
	{
		uint32 addVal = 0;
		if (GetLengthX () % 2 != 0 || (GetLengthX () + GetLengthY ()) % 2 != 0)
			++addVal; // helps make sure that parapet high points usually start in corners, which improves their look

		for (uint32 y = min_.y; y <= max_.y; ++y)
		{
			for (uint32 x = min_.x; x <= max_.x; ++x)
			{
				for (int32 zOff = 1; zOff < 2 + int32((x + y + addVal) % 2); ++zOff)
				{
					sCubeBuf = 0;
					if (IsPointOnExteriorWall (x, y, (int32)min_.z + zOff, min_.z, false))
					{
						SetSCubeTerrainType (&sCubeBuf, parentBuilding_->GetOuterWallMaterial ());
						GetWorld()->SetSCube(x, y, min_.z + zOff, sCubeBuf);
					}
				}
			}
		}
	}
	else
	{
		for (uint32 y = min_.y; y <= max_.y; ++y)
		{
			for (uint32 x = min_.x; x <= max_.x; ++x)
			{
				for (int32 zOff = 1; zOff < 2; ++zOff)
				{
					sCubeBuf = 0;
					if (IsPointOnExteriorWall (x, y, (int32)min_.z + zOff, min_.z, false))
					{
						SetSCubeTerrainType (&sCubeBuf, parentBuilding_->GetOuterWallMaterial ());
						GetWorld()->SetSCube(x, y, min_.z + zOff, sCubeBuf);
					}
				}
			}
		}
	}
}
Пример #4
0
BaseZone::BaseZone (uint32 xMin, uint32 yMin)
	: BaseArea(UPoint3D(xMin, yMin, 0), UPoint3D(xMin + SECTOR_BLENGTH - 1, yMin + SECTOR_BLENGTH - 1, 0))
{
	// STODO: clean up this constructor since it is doing too much work
	// STODO: expand bounding box beyond sector area if neighboring areas can support a town
	// STODO: make town bounding box not conform exactly to sector lines

	roadGenerator_ = new ZoneRoadGenerator(this);

	heightMap_			= (uint16*)malloc (GetLengthX () * GetLengthY () * sizeof (uint16));
	revisedHeightMap_	= (uint16*)malloc (GetLengthX () * GetLengthY () * sizeof (uint16));
	slopeMap_			= (float32*)malloc (GetLengthX () * GetLengthY () * sizeof (float32));

	// generate height map requires noise to be prepared.
	WorldGeneratorAPI ()->PrepTerraNoise (xMin, yMin, 0, GetLengthX (), GetLengthY (), false);
			
	WorldGeneratorAPI ()->GenerateHeightMap (xMin, yMin, heightMap_, GetLengthX (), GetLengthY ());

	GenerateRevisedHeightMap_ (xMin, yMin);
}
Пример #5
0
uint32
BaseZone::GetAverageHeightWithinBounds (const UPoint3D& min, const UPoint3D& max)
{
	// averages the height within the building bounds
	uint32 sum = 0;
	for (uint32 y = min.y; y <= max.y; ++y)
	{
		for (uint32 x = min.x; x <= max.x; ++x)
		{
			sum += revisedHeightMap_[(x - min_.x) + (y - min_.y) * GetLengthX ()];
		}
	}
	return sum / ((max.x - min.x + 1) * (max.y - min.y + 1));
}
Пример #6
0
void
LivingRoom::PlaceObjects( )
{
	UPoint3D tablePoint = UPoint3D( min_.x + 2 + (rand () % GetLengthX() - 2), min_.y + 2 + (rand () % GetLengthY() - 2), min_.z );
	
	S_BaseFurniture* table = (S_BaseFurniture*)GetServerEntityList()->Create( "table" );
	table->SetBOrigin( tablePoint );

	S_BaseFurniture* chair1 = (S_BaseFurniture*)GetServerEntityList()->Create( "chair" );
	S_BaseFurniture* chair2 = (S_BaseFurniture*)GetServerEntityList()->Create( "chair" );

	if (rand () % 2 == 0)
	{	
		chair1->SetBOrigin( UPoint3D( tablePoint.x - 1, tablePoint.y, min_.z ) );
		chair2->SetBOrigin( UPoint3D( tablePoint.x + 1, tablePoint.y, min_.z ) );
	}
	else
	{
		chair1->SetBOrigin( UPoint3D( tablePoint.x, tablePoint.y - 1, min_.z ) );
		chair2->SetBOrigin( UPoint3D( tablePoint.x, tablePoint.y + 1, min_.z ) );
	}

	BaseRoom::PlaceObjects();
}
Пример #7
0
	glm::vec3 AABB::GetCenter( void ) const
	{
		return glm::vec3(m_minX + GetLengthX() / 2, m_minY + GetLengthY() / 2, m_minZ + GetLengthZ() / 2);
	}
Пример #8
0
	Rectangle AABB::GetXZRect( void ) const
	{
		return Rectangle(m_minX, m_minZ, GetLengthX(), GetLengthZ());
	}
Пример #9
0
uint32
BaseZone::GetHeightAtPoint (uint32 x, uint32 y)
{
	return (uint32)revisedHeightMap_[(x - min_.x) + (y - min_.y) * GetLengthX ()];
}
Пример #10
0
void
BaseZone::BaseGenerateHazardExtents_ (float32 slopeThreshold)
{
	Hazard hazard;
	bool isWaterType;
	uint32 x;
	uint32 y;
	uint32 i;

	for (y = 0; y < GetLengthY (); ++y)
	{
		for (x = 0; x < GetLengthX (); ++x)
		{
			if (revisedHeightMap_[y * SECTOR_BLENGTH + x] <= WorldGeneratorAPI ()->GetSeaLevel ())
				isWaterType = true;
			else
				isWaterType = false;

			// DEBUG_BASEZONE:
			float32 debugSlope = slopeMap_[y * GetLengthX () + x];

			if (slopeMap_[y * GetLengthX () + x] > slopeThreshold || isWaterType)
			{
				bool isExtentsExtended = false;
				for (i = 0; i < hazards_.GetCount (); ++i)
				{
					// check if current point is in an existing hazard box.
					UPoint3D point;
					point.x = x + min_.x;
					point.y = y + min_.y;
					point.z = revisedHeightMap_[y * SECTOR_BLENGTH + x];
					
					if (IntersectBoxWithPoint (point, hazards_[i].min, hazards_[i].max))
					{
						hazards_[i].max.y = hazards_[i].max.y + 1; // hazard boxes are only elongated in the y axis to avoid excessively large boxes.
						isExtentsExtended = true;
						break;
					}
				}

				if (!isExtentsExtended)
				{
					hazard.min.x = x + min_.x - 4;
					hazard.max.x = x + min_.x + 4;
					hazard.min.y = y + min_.y - 4;
					hazard.max.y = y + min_.y + 4;
					hazard.min.z = revisedHeightMap_[y * GetLengthX () + x] - 5;
					hazard.max.z = revisedHeightMap_[y * GetLengthX () + x] + 8;
					if (isWaterType)
						hazard.hazardType = HAZARD_WATER;
					else
						hazard.hazardType = HAZARD_SLOPE;

					hazards_.InsertBack (hazard);

					Assert (hazard.min.x < 1000000 && hazard.min.y < 1000000 && hazard.min.z < 1000000);
					Assert (hazard.max.x < 1000000 && hazard.max.y < 1000000 && hazard.max.z < 1000000);
				}

				if (x < GetLengthX () - 5)
				{
					x += 4;
				}
				else
				{
					x += GetLengthX () - x - 1;
				}	
			}
		}
	}
}
Пример #11
0
void
BaseZone::GenerateRevisedHeightMap_ (uint32 xMin, uint32 yMin, uint32 heightOffset)
{
	//OPTIMIZATION: load some/all relevant sectors into memory. dont switch back and forth between them all, this is too slow.
	uint32 oX;
	uint32 oY;
	uint32 oZ;
	uint32 x;
	uint32 y;
	uint32 minValue = 1000000000;
	uint32 maxValue = 0;
	uint32 height;
	S_Sector* sector;
	uint32* sectorData;

	oZ = WorldGeneratorAPI ()->GetSeaLevel ();
	oZ -= oZ % SECTOR_BLENGTH;
	sector = GetWorld()->GetSector (xMin, yMin, oZ); 
	oX = uint32(sector->GetTranslationX () / SCUBE_LENGTH) - SECTOR_BLENGTH / 2;
	oY = uint32(sector->GetTranslationY () / SCUBE_LENGTH) - SECTOR_BLENGTH / 2;
	sectorData = sector->BeginModify ();

	Assert (oX >= xMin);
	Assert (oY >= yMin);
	Assert (oX % SECTOR_BLENGTH == 0);
	Assert (oY % SECTOR_BLENGTH == 0);
	Assert (oZ % SECTOR_BLENGTH == 0);

	for (y = 0; y < GetLengthY (); ++y)
	{
		for (x = 0; x < GetLengthX (); ++x)
		{
			height = (uint32)heightMap_[x + y * GetLengthX ()] + heightOffset;
			while (true)
			{
				//navigate to appropriate sector
				while (oX + SECTOR_BLENGTH <= xMin + x)
				{
					sector->EndModify ();
					oX += SECTOR_BLENGTH;
					sector = GetWorld()->GetSector (oX, oY, oZ);
					sectorData = sector->BeginModify ();
				}
				while (oX > xMin + x)
				{
					sector->EndModify ();
					oX -= SECTOR_BLENGTH;
					sector = GetWorld()->GetSector (oX, oY, oZ);
					sectorData = sector->BeginModify ();
				}

				while (oY + SECTOR_BLENGTH <= yMin + y)
				{
					sector->EndModify ();
					oY += SECTOR_BLENGTH;
					sector = GetWorld()->GetSector (oX, oY, oZ);
					sectorData = sector->BeginModify ();
				}
				while (oY > yMin + y)
				{
					sector->EndModify ();
					oY -= SECTOR_BLENGTH;
					sector = GetWorld()->GetSector (oX, oY, oZ);
					sectorData = sector->BeginModify ();
				}

				while (oZ + SECTOR_BLENGTH <= height)
				{
					sector->EndModify ();
					oZ += SECTOR_BLENGTH;
					sector = GetWorld()->GetSector (oX, oY, oZ);
					sectorData = sector->BeginModify ();
				}
				while (oZ > height)
				{
					sector->EndModify ();
					oZ -= SECTOR_BLENGTH;
					sector = GetWorld()->GetSector (oX, oY, oZ);
					sectorData = sector->BeginModify ();
				}	

				// check if location in sector is an air/water/lava block, if it is keep checking downward till air is no longer found
				TERRATYPE terraType = GetSCubeTerrainType (sectorData[(x + xMin - oX) + (y + yMin - oY) * SECTOR_BLENGTH + (height - oZ) * SECTOR_BAREA]);
				if (terraType == TERRA_AIR || terraType == TERRA_OLDAIR || terraType == TERRA_WATER || terraType == TERRA_LAVA)
				{
					--height;
				}
				else
				{
					if (height < minValue)
						minValue = height;
					if (height > maxValue)
						maxValue = height;
					revisedHeightMap_[x + y * GetLengthX ()] = (uint16)height;
					break;
				}
			}
		}
	}
	sector->EndModify ();

	// set town bounding box for z axis
	min_.z = minValue;
	max_.z = maxValue + 30;
}
Пример #12
0
void
BaseZone::BaseLevelTerrain_ (float32 maxSmoothingFactor, uint32 aboveGroundHeightLimit)
{
	// SNOW: store sector locations that have had level terrain called on them. if this method is called many times over the same area, various problems in the terrain will result
	uint32 averageTerraHeight;
	uint32 minHeight = revisedHeightMap_[0];
	uint32 maxHeight = minHeight;
	{
		uint32 sum = 0;
		for (uint32 y = 0; y < GetLengthY (); ++y)
		{
			for (uint32 x = 0; x < GetLengthX (); ++x)
			{
				uint32 height = revisedHeightMap_[x + y * GetLengthX ()];
				if (height < minHeight)
					minHeight = height;
				if (height > maxHeight)
					maxHeight = height;
				sum += height;
			}
		}
		averageTerraHeight = sum / (GetLengthX () * GetLengthY ());
	}

	UPoint3D centerPoint;
	centerPoint.x = min_.x + GetLengthX () / 2;
	centerPoint.y = min_.y + GetLengthY () / 2;
	GetWorld()->BeginModify ();
	for (uint32 y = min_.y; y <= max_.y; ++y)
	{
		for (uint32 x = min_.x; x <= max_.x; ++x)
		{
			uint32 distFromCenter = Max (Abs (int32(x) - int32(min_.x + GetLengthX () / 2)), Abs (int32(y) - int32(min_.y + GetLengthY () / 2)));
			uint32 height = (uint16)revisedHeightMap_[(x - min_.x) + (y - min_.y) * GetLengthX ()];

			uint32 smoothHeight = uint32(LinearInterpolate(
											CosineInterpolate (float(averageTerraHeight), float(height), float(distFromCenter) / float(Max (GetLengthX () / 2, GetLengthY () / 2))), 
											float(height), maxSmoothingFactor) + 0.5f);
			
			// slide blocks up or down. some compression or expansion of terrain layers will occur.
			if (height < smoothHeight)
			{
				uint32 difference = smoothHeight - height;
				Vector<uint32> blockStack;
				Vector<uint32> aboveGroundBStack;
				for (uint32 z = height - difference; z <= height; ++z)
					blockStack.InsertBack (GetWorld()->GetSCube (x, y, z));
				for (uint32 z = height + 1; z <= height + aboveGroundHeightLimit; ++z)
					aboveGroundBStack.InsertBack (GetWorld()->GetSCube (x, y, z));

				// expand terrain stack
				bool incrementI = false;
				uint32 i = 0;
				for (uint32 z = height - difference; z <= smoothHeight; ++z)
				{
					GetWorld()->SetSCube (x, y, z, blockStack[i]);
					if (incrementI)
						++i;
					incrementI = !incrementI;
				}
				i = 0;
				for (uint32 z = smoothHeight + 1; z <= smoothHeight + aboveGroundHeightLimit; ++z)
				{
					GetWorld()->SetSCube (x, y, z, aboveGroundBStack[i]);
					++i;
				}
			}
			else if (height > smoothHeight)
			{
				uint32 difference = height - smoothHeight;
				Vector<uint32> blockStack;
				Vector<uint32> aboveGroundBStack;
				for (uint32 z = smoothHeight - difference; z <= height; ++z)
					blockStack.InsertBack (GetWorld()->GetSCube (x, y, z));
				for (uint32 z = height + 1; z <= height + aboveGroundHeightLimit; ++z)
					aboveGroundBStack.InsertBack (GetWorld()->GetSCube (x, y, z));

				// compress terrain stack
				uint32 i = 0;
				for (uint32 z = smoothHeight - difference; z <= height; ++z)
				{
					if (z <= smoothHeight)
					{
						if (z == height || i >= blockStack.GetCount ())
							GetWorld()->SetSCube (x, y, z, blockStack[blockStack.GetCount () - 1]);
						else
							GetWorld()->SetSCube (x, y, z, blockStack[i]);
						i += 2;
					}
					else
					{
						GetWorld()->SetSCube (x, y, z, 0);
					}
				}
				i = 0;
				for (uint32 z = smoothHeight + 1; z <= smoothHeight + aboveGroundHeightLimit; ++z)
				{
					GetWorld()->SetSCube (x, y, z, aboveGroundBStack[i]);
					++i;
				}
			}

			// correct revised height map values
			revisedHeightMap_[(x - min_.x) + (y - min_.y) * GetLengthX ()] = (uint16)smoothHeight;
		}
	}
	GetWorld()->EndModify ();
}
Пример #13
0
bool
BaseZone::AttemptToPlaceBuilding_ (BaseBuilding* building, BuildingSize size, uint32 numResidents, uint32 extentsRadius, bool attemptToCenterBuilding)
{
	uint32 xStart;
	uint32 yStart;
	uint32 xEnd;
	uint32 yEnd;

	Direction doorSide = Direction(rand () % 4);

	bool doFirstPass = true;

	for(uint32 i = 0; i < 2; ++i)
	{
		// STODO: have proximity to roads determine door side
		// STODO: have options for placing a front door outside of the center of the building extents
		// determine bounds of where the building entrance can be potentially placed, based on doorSide
		switch (doorSide)
		{
		case DIRECTION_SOUTH:
			xStart = min_.x + extentsRadius + 1;
			yStart = min_.y + 1;
			xEnd = max_.x - extentsRadius - 1;
			yEnd = max_.y - extentsRadius * 2 - 1;
			break;
		case DIRECTION_NORTH:
			xStart = min_.x + extentsRadius + 1;
			yStart = min_.y + extentsRadius * 2 + 1;
			xEnd = max_.x - extentsRadius - 1;
			yEnd = max_.y - 1;
			break;
		case DIRECTION_WEST:
			xStart = min_.x + 1;
			yStart = min_.y + extentsRadius + 1;
			xEnd = max_.x - extentsRadius * 2 - 1;
			yEnd = max_.y - extentsRadius - 1;
			break;
		case DIRECTION_EAST:
			xStart = min_.x + extentsRadius * 2 + 1;
			yStart = min_.y + extentsRadius + 1;
			xEnd = max_.x - 1;
			yEnd = max_.y - extentsRadius - 1;
			break;
		}
		
		// Note- while this code could be modified for each doorside case, this code and some of the other code in this method will no longer be needed
		//	when buildings are placed along roads
		if (i == 0)
		{
			if (attemptToCenterBuilding)
			{
				xStart += (GetLengthX () - (extentsRadius + 1) * 2) / 2;
				yStart += (GetLengthY () - (extentsRadius + 1) * 2) / 2;
			}
			else
			{
				xStart += rand () % (GetLengthX () - (extentsRadius + 1) * 2);
				yStart += rand () % (GetLengthY () - (extentsRadius + 1) * 2);
			}
		}

		// STODO: make this more random by making the iteration go forward or backward
		for (uint32 entranceY = yStart; entranceY <= yEnd; entranceY += 2)
		{
			for (uint32 entranceX = xStart; entranceX <= xEnd; entranceX += 2)
			{
				UPoint3D buildingMin;
				UPoint3D buildingMax;
				UPoint3D entrance;

				switch (doorSide)
				{
				case DIRECTION_SOUTH:
					buildingMin.x = entranceX - extentsRadius;
					buildingMin.y = entranceY;
					break;
				case DIRECTION_NORTH:
					buildingMin.x = entranceX - extentsRadius;
					buildingMin.y = entranceY - extentsRadius * 2;
					break;
				case DIRECTION_WEST:
					buildingMin.x = entranceX;
					buildingMin.y = entranceY - extentsRadius;
					break;
				case DIRECTION_EAST:
					buildingMin.x = entranceX - extentsRadius * 2;
					buildingMin.y = entranceY - extentsRadius;
					break;
				}
				buildingMax.x = buildingMin.x + extentsRadius * 2;
				buildingMax.y = buildingMin.y + extentsRadius * 2;
				buildingMin.z = revisedHeightMap_[entranceX - min_.x + (entranceY - min_.y) * GetLengthX ()] - 5;
				buildingMax.z = revisedHeightMap_[entranceX - min_.x + (entranceY - min_.y) * GetLengthX ()] + 8; // STODO: figure out proper defining technique for z
	
				entrance.x = entranceX;
				entrance.y = entranceY;
				entrance.z = revisedHeightMap_[(entrance.x - min_.x) + (entrance.y - min_.y) * GetLengthX ()];

				building->SetBounds (entrance, buildingMin, buildingMax, size, doorSide);

				if (IsBuildingBoundsPlaceable (buildingMin, buildingMax))
				{
					if (building->PlaceRooms (doorSide))
					{
						buildings_.InsertBack (building);
						return true;
					}
					return false; // Note- must delete building data after unsuccessful PlaceRooms
				}
			}
		}
	}
	return false;
}