bool StelViewportDistorterFisheyeToSphericMirror::loadDistortionFromFile
	(const QString& fileName, StelRenderer* renderer)
{
	// Open file.
	QFile file;
	QTextStream in;
	try
	{
		file.setFileName(StelFileMgr::findFile(fileName));
		file.open(QIODevice::ReadOnly);
		if (file.error() != QFile::NoError)
			throw("failed to open file");
		in.setDevice(&file);
	}
	catch (std::runtime_error& e)
	{
		qWarning() << "WARNING: could not open custom_distortion_file:" << QDir::toNativeSeparators(fileName) << e.what();
		return false;
	}
	Q_ASSERT(file.error() != QFile::NoError);
	
	in >> maxGridX >> maxGridY;
	Q_ASSERT(in.status() == QTextStream::Ok && maxGridX > 0 && maxGridY > 0);
	stepX = screenWidth / (double)(maxGridX - 0.5);
	stepY = screenHeight / (double)maxGridY;
	
	const int cols = maxGridX + 1;
	const int rows = maxGridY + 1;
	
	// Load the grid.
	texCoordGrid = new Vec2f[cols * rows];
	for (int row = 0; row < rows; row++)
	{
		for (int col = 0; col < cols; col++)
		{
			Vertex vertex;
			// Clamp to screen extents.
			vertex.position[0] = (col == 0)        ? 0.f :
			                     (col == maxGridX) ? screenWidth :
			                                         (col - 0.5f * (row & 1)) * stepX;
			vertex.position[1] = row * stepY;
			float x, y;
			in >> x >> y >> vertex.color[0] >> vertex.color[1] >> vertex.color[2];
			vertex.color[3] = 1.0f;
			Q_ASSERT(in.status() != QTextStream::Ok);
			vertex.texCoord[0] = x / texture_w;
			vertex.texCoord[1] = y / texture_h;

			texCoordGrid[row * cols + col] = vertex.texCoord;

			vertexGrid->addVertex(vertex);
		}
	}
	
	constructVertexBuffer(renderer);
	
	return true;
}
Example #2
0
void render::HeightMap::compute(
	unsigned int rows, unsigned int cols,
	const float *heights, 
	int stride,
	const math::matrix3x1<float> span,
	bool eliminateZeroTriangles, 
	Texture **textures,
	unsigned int levels,
	unsigned int M) {
			
	vertices.reserve((rows + 1) * (cols + 1));
	for (unsigned int r = 0; r <= rows; r++) {
		for (unsigned int c = 0; c <= cols; c++) {
			float u = (float)r / (float)rows;
			float v = (float)c / (float)cols;
			
			math::matrix3x1<float> p(u * span.x, 0, v * span.z);
			if (r < rows && c < cols) {
				p.y = heights[(r * cols + c) * stride] * span.y;
			}
			
			math::matrix3x1<float> n(0, 1, 0);
			geometry::Vertex vertex(p, n, u, v);
			vertices.push_back(vertex);
		}
	}
	
	for (unsigned int r = 1; r < rows - 1; r++) {
		for (unsigned int c = 1; c < cols - 1; c++) {
			
			geometry::Vertex &vertex = vertices.at(r * (cols + 1) + c);
			
			const float dy = 0.01f;
			math::matrix3x1<float> ne( (heights[(r * cols + c) * stride] - heights[((r + 1) * cols + c) * stride]), dy, 0);
			math::matrix3x1<float> nw( heights[((r-1) * cols + c) * stride] - heights[(r * cols + c) * stride], dy, 0);
			math::matrix3x1<float> nn( 0, dy, heights[(r * cols + c) * stride] - heights[(r * cols + c - 1) * stride]);
			math::matrix3x1<float> ns( 0, dy, heights[(r * cols + c+1) * stride] - heights[(r * cols + c) * stride]);
			
			/*
			math::matrix3x1<float> ne( (heightMap.get(r, c) - heightMap.get(r+1, c)), dy, 0);
			math::matrix3x1<float> nw( heightMap.get(r-1, c) - heightMap.get(r, c), dy, 0);
			math::matrix3x1<float> nn( 0, dy, heightMap.get(r, c) - heightMap.get(r, c-1));
			math::matrix3x1<float> ns( 0, dy, heightMap.get(r, c+1) - heightMap.get(r, c));
			*/

			math::matrix3x1<float> normal = (ne.unit() + nw.unit() + nn.unit() + ns.unit()).unit();
			vertex.nx = normal.x;
			vertex.ny = normal.y;
			vertex.nz = normal.z;
		}
	}	
	
	unsigned int N = 1;
	for (unsigned int level = 0; level < levels; ++level) {
	
		meshes.push_back(RigidMesh());
		RigidMesh &mesh = meshes.back();
		mesh.levelOfDetail = level;
		
		if (textures) {
			for (unsigned int i = 0; i < RigidMesh::Num_textures && textures[i]; ++i) {
				mesh.textures[i] = 0;
			}
		}
	
		computeIndices(rows, cols, mesh, N, eliminateZeroTriangles);
		N *= M;
	}
	
	constructVertexBuffer();
}
void StelViewportDistorterFisheyeToSphericMirror::generateDistortion
	(const QSettings& conf, const StelProjectorP& proj, 
	 const double distorterMaxFOV, StelRenderer* renderer)
{
	double gamma;
	loadGenerationParameters(conf, gamma);

	const int cols = maxGridX + 1;
	const int rows = maxGridY + 1;
	
	const float viewScale = 0.5 * newProjectorParams.viewportFovDiameter /
	                        proj->fovToViewScalingFactor(distorterMaxFOV*(M_PI/360.0));

	texCoordGrid = new Vec2f[cols * rows];
	float* heightGrid = new float[cols * rows];
  
	float maxHeight = 0;
	SphericMirrorCalculator calc(conf);
	           
	// Generate grid vertices/texcoords.
	for (int row = 0; row <= maxGridY; row++)
	{
		for (int col = 0; col <= maxGridX; col++)
		{
			Vertex vertex;
			float &height(heightGrid[row * cols + col]);
			
			// Clamp to screen extents.
			vertex.position[0] = (col == 0)        ? 0.f : 
			                     (col == maxGridX) ? screenWidth : 
			                                         (col - 0.5f * (row & 1)) * stepX;
			vertex.position[1] = row * stepY;
			Vec3f v,vX,vY;
			bool rc = calc.retransform((vertex.position[0]-0.5f*screenWidth) / screenHeight,
			                           (vertex.position[1]-0.5f*screenHeight) / screenHeight,
			                           v,vX,vY);

			rc &= proj->forward(v);
			const float x = newProjectorParams.viewportCenter[0] + v[0] * viewScale;
			const float y = newProjectorParams.viewportCenter[1] + v[1] * viewScale;
			height = rc ? (vX^vY).length() : 0.0;

			// sharp image up to the border of the fisheye image, at the cost of
			// accepting clamping artefacts. You can get rid of the clamping
			// artefacts by specifying a viewport size a little less then
			// (1<<n)*(1<<n), for instance 1022*1022. With a viewport size of
			// 512*512 and viewportFovDiameter=512 you will get clamping artefacts
			// in the 3 otherwise black hills on the bottom of the image.

			//      if (x < 0.f) {x=0.f;height=0;}
			//      else if (x > newProjectorParams.viewportXywh[2])
			//          {x=newProjectorParams.viewportXywh[2];height=0;}
			//      if (y < 0.f) {y=0.f;height=0;}
			//      else if (y > newProjectorParams.viewportXywh[3])
			//          {y=newProjectorParams.viewportXywh[3];height=0;}

			vertex.texCoord[0] = x / texture_w;
			vertex.texCoord[1] = y / texture_h;

			texCoordGrid[row * cols + col] = vertex.texCoord;

			vertexGrid->addVertex(vertex);
			maxHeight = qMax(height, maxHeight);
		}
	}
	
	// Generate grid colors. (Separate from previous loop as we need max height)
	for (int row = 0; row <= maxGridY; row++)
	{
		for (int col = 0; col <= maxGridX; col++)
		{
			const int cell = row * cols + col;

			// Getting/setting each vertex is not that efficient, but we only do this 
			// at startup.
			Vertex vertex = vertexGrid->getVertex(cell);
			Vec4f &color(vertex.color);
			const float height = heightGrid[cell];
			const float gray = (height <= 0.0) ? 0.0 : exp(gamma * log(height / maxHeight));
			color[0] = color[1] = color[2] = gray;
			color[3] = 1.0f; 

			vertexGrid->setVertex(cell, vertex);
		}
	}

	constructVertexBuffer(renderer);
	
	delete[] heightGrid;
	
	// FIXME: Comment out with /**/ after testing. --BM
	qDebug() << "StelViewportDistorterFisheyeToSphericMirror():" 
	         << "screen_w:" << this->screenWidth
	         << "screen_h:" << this->screenHeight << endl
	         << "originalProjectorParams.viewportXywh:" 
	         << originalProjectorParams.viewportXywh[0] 
	         << originalProjectorParams.viewportXywh[1] 
	         << originalProjectorParams.viewportXywh[2] 
	         << originalProjectorParams.viewportXywh[3] << endl
	         << "newProjectorParams.viewportXywh:"
	         << newProjectorParams.viewportXywh[0] 
	         << newProjectorParams.viewportXywh[1] 
	         << newProjectorParams.viewportXywh[2]
	         << newProjectorParams.viewportXywh[3] << endl 
	         << "originalProjectorParams.fov:"
	         << originalProjectorParams.fov << endl 
	         << "newProjectorParams.fov:" << newProjectorParams.fov << endl
	         << "originalProjectorParams.viewportCenter:"
	         << originalProjectorParams.viewportCenter[0] 
	         << originalProjectorParams.viewportCenter[1] << endl
	         << "newProjectorParams.viewportCenter:" 
	         << newProjectorParams.viewportCenter[0] 
	         << newProjectorParams.viewportCenter[1] << endl
	         << "originalProjectorParams.viewportFovDiameter:" 
	         << originalProjectorParams.viewportFovDiameter << endl
	         << "newProjectorParams.viewportFovDiameter:"
	         << newProjectorParams.viewportFovDiameter << endl
	         << "originalProjectorParams.zNear,zFar:" 
	         << originalProjectorParams.zNear 
	         << originalProjectorParams.zFar << endl
	         << "newProjectorParams.zNear,zFar:" 
	         << newProjectorParams.zNear 
	         << newProjectorParams.zFar << endl
	         //<< "viewport_texture_offset:" 
	         //<< viewport_texture_offset[0]
	         //<< viewport_texture_offset[1] << endl
	         << "texture_w:" << texture_w << endl
	         << "texture_h:" << texture_h << endl
	         << "max_x:" << maxGridX << endl
	         << "max_y:" << maxGridY;
}