GeometryTerrain::GeometryTerrain(int size, int patch_size, int num_hills, float smoothness, int smooth_passes )
: m_Width(size), 
  m_Length(size),
  m_patchSize(patch_size)
{
	if(patch_size < 2) patch_size = 2;
	if(patch_size > size) patch_size = size;

	m_pHeight	= new float*[m_Width+1];

	m_fOffsetX = 1.0f;
	m_fOffsetY = 1.0f;
	m_fOffsetZ = 1.0f;

	for(int i = 0; i <= m_Length; i++)
	{		
		m_pHeight[i] = new float[m_Width+1];
		memset(m_pHeight[i], 0, sizeof(float)*(m_Length+1));
	}

	m_pVertices = NULL;

	m_nVertexCount = ((unsigned int)GetWidth()+1)*((unsigned int)GetLength()+1);

	//memset(m_pVertices, 0, m_nVertexCount);
	//memset(m_pNormals, 0, m_nVertexCount);


	m_pVertices		= new flx_Vertex[m_nVertexCount];
	m_pTexCoords	= new flx_TexCoord[m_nVertexCount];
	m_pNormals		= new flx_Normal[m_nVertexCount];

	//Add some random Hills and smooth it
	generateTerrain(num_hills);
	for(int i = 0; i < smooth_passes; ++i)
		smoothTerrain(smoothness);

	int deg_x = 0, deg_z = 0;
	for(int z = 0; z <= GetLength(); z++)
	{
		for(int x = 0; x <= GetWidth(); x++)
		{
			//fill Vertex array with data
			m_pVertices[x + z * (GetWidth()+1)].x = (float)x * m_fOffsetX;
			m_pVertices[x + z * (GetWidth()+1)].y = getHeight(x, z);
			m_pVertices[x + z * (GetWidth()+1)].z = (float)z * m_fOffsetZ;

			//fill TexCoord array with data
			m_pTexCoords[x + z * (GetWidth()+1)].u = (float)((float)x/(GetWidth()+1));
			m_pTexCoords[x + z * (GetWidth()+1)].v = (float)((float)z/(GetWidth()+1));
		}
	}

	//Create Indices
	for(int z = 0; z < GetLength()-1; z++)
	{
		//Even rows move left to right
		if(z % 2 == 0)
		{
			int x;
			for(x = 0; x < GetWidth(); x++)
			{
				m_Indices.push_back( x + (z * GetWidth()) );
				m_Indices.push_back( x + (z * GetWidth()) + GetWidth() );
			}

			if(z != GetLength() - 2 ) 
				m_Indices.push_back( --x + (z * GetWidth()) );
		}
		else
		{
			//odd rows move right to left
			int x;
			for(x = GetWidth() -1; x >= 0; x--)
			{
				m_Indices.push_back( x + (z * GetWidth()) );
				m_Indices.push_back( x + (z * GetWidth()) + GetWidth() );
			}

			if(z != GetLength() - 2 ) 
				m_Indices.push_back( ++x + (z * GetWidth()) );
		}
	}

	
	//Fill the buffers with data
	//VertexBuffer.setElementList(m_pVertices, m_nVertexCount);
	//TexCoordBuffer.setElementList(m_pTexCoords, m_nVertexCount);

	//...and calculate the Normals
	computeNormals();

	//Buffers ready to bind!
	//NormalBuffer.build(GL_ARRAY_BUFFER, GL_NORMAL_ARRAY);
	//VertexBuffer.build(GL_ARRAY_BUFFER, GL_VERTEX_ARRAY);
	//TexCoordBuffer.build(GL_ARRAY_BUFFER, GL_TEXTURE_COORD_ARRAY);
	
	buildPatches(0);

	//delete [] m_pVertices; m_pVertices = NULL;
	//delete [] m_pTexCoords; m_pTexCoords = NULL;
	//delete [] m_pNormals; m_pNormals = NULL;
}
ControlWidget::ControlWidget(MainWindow* mainWin) : QDockWidget("Control Widget", (QWidget*)mainWin) {
	this->mainWin = mainWin;

	// set up the UI
	ui.setupUi(this);

	ui.TabWidget->setCurrentIndex(0);
	ui.lineEditNumAvenueIterations->setText("1500");
	ui.lineEditNumStreetIterations->setText("6000");
	ui.lineEditNumExamples->setText("1");
	ui.lineEditRandomSeed->setText("12345");
	ui.checkBoxCleanAvenues->setChecked(true);
	ui.checkBoxCleanStreets->setChecked(false);
	ui.checkBoxLocalStreets->setChecked(true);
	ui.checkBoxCropping->setChecked(false);
	ui.checkBoxUseLayer->setChecked(false);
	ui.lineEditMinBlockSize->setText("10000");
	ui.lineEditHoughScale->setText("500.0");
	ui.lineEditPatchDistance1->setText("80");
	ui.lineEditPatchDistance2->setText("20");
	ui.lineEditInterpolateSigma1->setText("0.2");
	ui.lineEditInterpolateSigma2->setText("0.2");
	ui.lineEditRotationAngle->setText("0.0");
	ui.lineEditRoadAngleTolerance->setText("60");
	ui.lineEditSlopeTolerance->setText("36.4");
	ui.lineEditAcrossRiverTolerance->setText("300");
	ui.lineEditMaxBlockSizeForPark->setText("250000");
	ui.checkBoxSaveRoadImages->setChecked(false);
	ui.checkBoxSavePatchImages->setChecked(false);
	
	ui.terrainPaint_changeEdit->setText("200");
	ui.terrainPaint_changeSlider->setMinimum(0);
	ui.terrainPaint_changeSlider->setMaximum(1000);
	ui.terrainPaint_changeSlider->setValue(200);
	ui.terrainPaint_sizeSlider->setMinimum(1);
	ui.terrainPaint_sizeSlider->setMaximum(1000);
	ui.terrainPaint_sizeSlider->setValue(500);

	ui.render_2DparcelLineSlider->setMinimum(0);
	ui.render_2DparcelLineSlider->setMaximum(50);
	ui.render_2DparcelLineSlider->setSingleStep(1);
	ui.render_2DparcelLineSlider->setValue(5);

	// register the event handlers
	connect(ui.pushButtonGenerateEx, SIGNAL(clicked()), this, SLOT(generateRoadsEx()));
	connect(ui.pushButtonGenerateWarp, SIGNAL(clicked()), this, SLOT(generateRoadsWarp()));
	connect(ui.pushButtonGeneratePM, SIGNAL(clicked()), this, SLOT(generateRoadsPM()));
	connect(ui.pushButtonGenerateAliaga, SIGNAL(clicked()), this, SLOT(generateRoadsAliaga()));
	connect(ui.pushButtonClear, SIGNAL(clicked()), this, SLOT(clear()));
	connect(ui.pushButtonConnect2, SIGNAL(clicked()), this, SLOT(connectRoads2()));

	connect(ui.pushButtonMerge, SIGNAL(clicked()), this, SLOT(mergeRoads()));
	connect(ui.pushButtonTrim, SIGNAL(clicked()), this, SLOT(trimRoads()));
	connect(ui.pushButtonClearBoundaryFlag, SIGNAL(clicked()), this, SLOT(clearBoundaryFlag()));
	connect(ui.pushButtonRemoveDanglingEdges, SIGNAL(clicked()), this, SLOT(removeDanglingEdges()));
	connect(ui.pushButtonRemoveCloseEdges, SIGNAL(clicked()), this, SLOT(removeCloseEdges()));

	// terrain
	connect(ui.terrainPaint_sizeSlider, SIGNAL(valueChanged(int)),this, SLOT(updateTerrainLabels(int)));
	connect(ui.terrainPaint_changeEdit, SIGNAL(textChanged(const QString &)),this, SLOT(updateTerrainEdit(const QString &)));
	connect(ui.terrainPaint_changeSlider, SIGNAL(valueChanged(int)),this, SLOT(updateTerrainLabels(int)));
	connect(ui.terrain_2DShader, SIGNAL(stateChanged(int)),this, SLOT(changeTerrainShader(int)));
	connect(ui.render_2DroadsStrokeSlider, SIGNAL(valueChanged(int)),this, SLOT(updateRender2D(int)));
	connect(ui.render_2DroadsExtraWidthSlider, SIGNAL(valueChanged(int)),this, SLOT(updateRender2D(int)));
	connect(ui.render_2DparksSlider, SIGNAL(valueChanged(int)),this, SLOT(updateRender2D(int)));
	connect(ui.render_2DparcelLineSlider, SIGNAL(valueChanged(int)),this, SLOT(updateRender2D(int)));
	connect(ui.pushButtonSmoothTerrain, SIGNAL(clicked()), this, SLOT(smoothTerrain()));
	connect(ui.content_checkbox, SIGNAL(stateChanged(int)),this, SLOT(contentDesign(int)));

	connect(ui.content_0, SIGNAL(clicked()), this, SLOT(contentDesignLevel()));
	connect(ui.content_1, SIGNAL(clicked()), this, SLOT(contentDesignLevel()));
	connect(ui.content_7, SIGNAL(clicked()), this, SLOT(contentDesignLevel()));
	connect(ui.content_8, SIGNAL(clicked()), this, SLOT(contentDesignLevel()));
	connect(ui.content_9, SIGNAL(clicked()), this, SLOT(contentDesignLevel()));
	connect(ui.content_10, SIGNAL(clicked()), this, SLOT(contentDesignLevel()));
	connect(ui.content_11, SIGNAL(clicked()), this, SLOT(contentDesignLevel()));

	updateRender2D(-1); // update just labels
	updateTerrainLabels(-1);
	contentDesignLevel();

	hide();

	
	
}