示例#1
0
/**
 * 指定されたParcelの中に、ビルを建てる。
 */
bool generateParcelBuildings(VBORenderManager& rendManager, Block &inBlock, Parcel &inParcel, PlaceTypesMainClass &placeTypesIn)
{
	float probEmptyParcel = 0.0f;
	Loop3D pContourCpy;

	if(inParcel.getMyPlaceTypeIdx() == -1){
		return false;
	}

	//if parcel is park, process
	if(inParcel.parcelType==PAR_PARK){//park
		//printf("PARK\n");
		return false;
	}

	//Compute parcel frontage
	std::vector<int> frontEdges;
	std::vector<int> rearEdges;
	std::vector<int> sideEdges;

	pContourCpy.clear();
	pContourCpy = inParcel.parcelContour.contour;
	inParcel.parcelContour.contour.clear();


	Polygon3D::cleanLoop(pContourCpy, inParcel.parcelContour.contour, 1.0f);
	Polygon3D::reorientFace(inParcel.parcelContour.contour);

	inBlock.findParcelFrontAndBackEdges(inBlock, inParcel, frontEdges, rearEdges, sideEdges);

	//Compute buildable area polygon
	float bldgFootprintArea = inParcel.computeBuildableArea(
		placeTypesIn.myPlaceTypes[inParcel.getMyPlaceTypeIdx()].getFloat("parcel_setback_front"),
		placeTypesIn.myPlaceTypes[inParcel.getMyPlaceTypeIdx()].getFloat("parcel_setback_rear"),
		placeTypesIn.myPlaceTypes[inParcel.getMyPlaceTypeIdx()].getFloat("parcel_setback_sides"),
		frontEdges, rearEdges, sideEdges,
		inParcel.parcelBuildableAreaContour.contour);
	//printf("parcelBuilsable %d\n",inParcel.parcelBuildableAreaContour.contour.size());
	if(inParcel.parcelBuildableAreaContour.isSelfIntersecting()){
		inParcel.parcelBuildableAreaContour.contour.clear();
		return false;
	}

	//compute building footprint polygon
	if(!computeBuildingFootprintPolygon(
		placeTypesIn.myPlaceTypes.at(inParcel.getMyPlaceTypeIdx()).getFloat("building_max_frontage"),
		placeTypesIn.myPlaceTypes.at(inParcel.getMyPlaceTypeIdx()).getFloat("building_max_depth"),
		frontEdges, rearEdges, sideEdges,
		inParcel.parcelBuildableAreaContour.contour,
		inParcel.myBuilding.buildingFootprint.contour))
	{
		printf("!computeBuildingFootprintPolygon\n");
		return false;
	}

	// もしfootprintの一辺の長さが短すぎたら、または、短い辺と長い辺の比が大きすぎたら、ビルの建設を中止する
	QVector3D obbSize;
	QMatrix4x4 obbMat;
	inParcel.myBuilding.buildingFootprint.getMyOBB(obbSize, obbMat);
	if (obbSize.x() < 5 || obbSize.y() < 5) return false;
	if (obbSize.x() > obbSize.y() * 5 || obbSize.y() > obbSize.x() * 5) return false;

	// stoties
	float heightDev = 
		(placeTypesIn.myPlaceTypes.at(inParcel.getMyPlaceTypeIdx()).getFloat("building_stories_deviation")/100.0f)*
		(((float)qrand()/RAND_MAX)*2.0f-1.0f)* //LC::misctools::genRand(-1.0f,1.0f)*
		placeTypesIn.myPlaceTypes.at(inParcel.getMyPlaceTypeIdx()).getFloat("building_stories_mean");

	int bldgNumStories = (int)
		placeTypesIn.myPlaceTypes.at(inParcel.getMyPlaceTypeIdx()).getFloat("building_stories_mean") +
		heightDev;

	// find the lowest elevation
	float minZ = std::numeric_limits<float>::max();
	for (int i = 0; i < inParcel.myBuilding.buildingFootprint.contour.size(); ++i) {
		float z = rendManager.getTerrainHeight(inParcel.myBuilding.buildingFootprint[i].x(), inParcel.myBuilding.buildingFootprint[i].y());
		if (z < minZ) {
			minZ = z;
		}
	}

	// set the elevation
	for (int i = 0; i < inParcel.myBuilding.buildingFootprint.contour.size(); ++i) {
		inParcel.myBuilding.buildingFootprint[i].setZ(minZ);
	}

	//Set building
	//inParcel.myBuilding.buildingFootprint=inParcel.myBuilding.buildingFootprint;
	inParcel.myBuilding.numStories=bldgNumStories;
	inParcel.myBuilding.bldType=BLDG_WITH_BLDG;

	return true;
}