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; }
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; }