StelViewportEffect.cpp   StelViewportEffect.cpp 
skipping to change at line 20 skipping to change at line 20
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*/ */
#include "config.h"
#include "StelViewportEffect.hpp" #include "StelViewportEffect.hpp"
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelPainter.hpp"
#include "SphericMirrorCalculator.hpp" #include "SphericMirrorCalculator.hpp"
#include "StelFileMgr.hpp" #include "StelFileMgr.hpp"
#include "StelMovementMgr.hpp" #include "StelMovementMgr.hpp"
#include "renderer/StelIndexBuffer.hpp"
#include "renderer/StelRenderer.hpp"
#include <QOpenGLFramebufferObject>
#include <QSettings> #include <QSettings>
#include <QFile> #include <QFile>
#include <QDir> #include <QDir>
StelViewportDistorterFisheyeToSphericMirror::StelViewportDistorterFisheyeTo void StelViewportEffect::paintViewportBuffer(const QOpenGLFramebufferObject
SphericMirror * buf) const
(int screenWidth,int screenHeight, StelRenderer* renderer) {
: screenWidth(screenWidth) StelPainter sPainter(StelApp::getInstance().getCore()->getProjection
, screenHeight(screenHeight) 2d());
, originalProjectorParams(StelApp::getInstance().getCore()-> sPainter.setColor(1,1,1);
getCurrentStelProjectorParams()) sPainter.enableTexture2d(true);
, maxTexCoords(1.0f, 1.0f) glBindTexture(GL_TEXTURE_2D, buf->texture());
, texCoordGrid(NULL) sPainter.drawRect2d(0, 0, buf->size().width(), buf->size().height())
, vertexGrid(renderer->createVertexBuffer<Vertex>(PrimitiveType_Tria ;
ngleStrip)) }
struct VertexPoint
{
Vec2f ver_xy;
Vec4f color;
double h;
};
StelViewportDistorterFisheyeToSphericMirror::StelViewportDistorterFisheyeTo
SphericMirror(int screen_w,int screen_h)
: screen_w(screen_w)
, screen_h(screen_h)
, originalProjectorParams(StelApp::getInstance().getCore()->getCurre
ntStelProjectorParams())
, texture_wh(1)
, texture_point_array(NULL)
{ {
QSettings& conf = *StelApp::getInstance().getSettings(); QSettings& conf = *StelApp::getInstance().getSettings();
StelCore* core = StelApp::getInstance().getCore(); StelCore* core = StelApp::getInstance().getCore();
// initialize viewport parameters and texture size: // initialize viewport parameters and texture size:
// maximum FOV value of the not yet distorted image // maximum FOV value of the not yet distorted image
double distorterMaxFOV = conf.value("spheric_mirror/distorter_max_fo double distorter_max_fov = conf.value("spheric_mirror/distorter_max_
v",175.f).toFloat(); fov",175.f).toFloat();
if (distorterMaxFOV > 240.f) if (distorter_max_fov > 240.f)
{ distorter_max_fov = 240.f;
qDebug() << "spheric_mirror/distorter_max_fov too high : set else if (distorter_max_fov < 120.f)
ting to 240.0"; distorter_max_fov = 120.f;
distorterMaxFOV = 240.f; if (distorter_max_fov > core->getMovementMgr()->getMaxFov())
} distorter_max_fov = core->getMovementMgr()->getMaxFov();
else if (distorterMaxFOV < 120.f)
{
qDebug() << "spheric_mirror/distorter_max_fov too low : sett
ing to 120.0";
distorterMaxFOV = 120.f;
}
if (distorterMaxFOV > core->getMovementMgr()->getMaxFov())
distorterMaxFOV = core->getMovementMgr()->getMaxFov();
StelProjectorP proj = core->getProjection(StelCore::FrameJ2000); StelProjectorP prj = core->getProjection(StelCore::FrameJ2000);
core->getMovementMgr()->setMaxFov(distorterMaxFOV); core->getMovementMgr()->setMaxFov(distorter_max_fov);
// width of the not yet distorted image // width of the not yet distorted image
newProjectorParams.viewportXywh[2] = newProjectorParams.viewportXywh[2] = conf.value("spheric_mirror/newP
conf.value("spheric_mirror/newProjectorParams.viewportXywh[2]idt rojectorParams.viewportXywh[2]idth", originalProjectorParams.viewportXywh[2
h", ]).toInt();
originalProjectorParams.viewportXywh[2]).toInt();
if (newProjectorParams.viewportXywh[2] <= 0) if (newProjectorParams.viewportXywh[2] <= 0)
{ {
newProjectorParams.viewportXywh[2] = originalProjectorParams .viewportXywh[2]; newProjectorParams.viewportXywh[2] = originalProjectorParams .viewportXywh[2];
} }
else if (newProjectorParams.viewportXywh[2] > screenWidth) else if (newProjectorParams.viewportXywh[2] > screen_w)
{ {
newProjectorParams.viewportXywh[2] = screenWidth; newProjectorParams.viewportXywh[2] = screen_w;
} }
// height of the not yet distorted image // height of the not yet distorted image
newProjectorParams.viewportXywh[3] = newProjectorParams.viewportXywh[3] = conf.value("spheric_mirror/newP
conf.value("spheric_mirror/newProjectorParams.viewportXywh[3]eig rojectorParams.viewportXywh[3]eight", originalProjectorParams.viewportXywh[
ht", 3]).toInt();
originalProjectorParams.viewportXywh[3]).toInt();
if (newProjectorParams.viewportXywh[3] <= 0) if (newProjectorParams.viewportXywh[3] <= 0)
{ {
newProjectorParams.viewportXywh[3] = originalProjectorParams .viewportXywh[3]; newProjectorParams.viewportXywh[3] = originalProjectorParams .viewportXywh[3];
} }
else if (newProjectorParams.viewportXywh[3] > screenHeight) else if (newProjectorParams.viewportXywh[3] > screen_h)
{ {
newProjectorParams.viewportXywh[3] = screenHeight; newProjectorParams.viewportXywh[3] = screen_h;
} }
// center of the FOV-disk in the not yet distorted image // center of the FOV-disk in the not yet distorted image
newProjectorParams.viewportCenter[0] = newProjectorParams.viewportCenter[0] = conf.value("spheric_mirror/vi
conf.value("spheric_mirror/viewportCenterX", ewportCenterX", 0.5*newProjectorParams.viewportXywh[2]).toFloat();
0.5*newProjectorParams.viewportXywh[2]).toFloat(); newProjectorParams.viewportCenter[1] = conf.value("spheric_mirror/vi
newProjectorParams.viewportCenter[1] = ewportCenterY", 0.5*newProjectorParams.viewportXywh[3]).toFloat();
conf.value("spheric_mirror/viewportCenterY",
0.5*newProjectorParams.viewportXywh[3]).toFloat();
// diameter of the FOV-disk in pixels // diameter of the FOV-disk in pixels
newProjectorParams.viewportFovDiameter = newProjectorParams.viewportFovDiameter = conf.value("spheric_mirror/
conf.value("spheric_mirror/viewport_fov_diameter", viewport_fov_diameter", qMin(newProjectorParams.viewportXywh[2],newProjecto
qMin(newProjectorParams.viewportXywh[2], rParams.viewportXywh[3])).toFloat();
newProjectorParams.viewportXywh[3])).toFloat();
// Vestigial mirror texture dimensions: used to be a single value, // Vestigial mirror texture dimensions: used to be a single value,
// the closest power of 2 higher or equal to the larger screen dimen while (texture_wh < newProjectorParams.viewportXywh[2] || texture_wh
sion. < newProjectorParams.viewportXywh[3])
texture_w = newProjectorParams.viewportXywh[2]; texture_wh <<= 1;
texture_h = newProjectorParams.viewportXywh[3]; viewport_texture_offset[0] = (texture_wh-newProjectorParams.viewport
// while (texture_wh < newProjectorParams.viewportXywh[2] || Xywh[2])>>1;
// texture_wh < newProjectorParams.viewportXywh[3]) viewport_texture_offset[1] = (texture_wh-newProjectorParams.viewport
// { Xywh[3])>>1;
// texture_wh <<= 1;
// }
// TODO: Given the above, is there any point in this? --BM
newProjectorParams.viewportXywh[0] = (screenWidth-newProjectorParams
.viewportXywh[2]) >> 1;
newProjectorParams.viewportXywh[1] = (screenHeight-newProjectorParam
s.viewportXywh[3]) >> 1;
StelApp::getInstance().getCore()->setCurrentStelProjectorParams(newP
rojectorParams);
const QString customDistortionFileName = newProjectorParams.viewportXywh[0] = (screen_w-newProjectorParams.vi
QDir::fromNativeSeparators(conf.value("spheric_mirror/custom_dis ewportXywh[2]) >> 1;
tortion_file","").toString()); newProjectorParams.viewportXywh[1] = (screen_h-newProjectorParams.vi
ewportXywh[3]) >> 1;
if (customDistortionFileName.isEmpty()) StelApp::getInstance().getCore()->setCurrentStelProjectorParams(newP
{ rojectorParams);
generateDistortion(conf, proj, distorterMaxFOV, renderer);
}
else if (!loadDistortionFromFile(customDistortionFileName, renderer)
)
{
qDebug() << "Falling back to generated distortion";
generateDistortion(conf, proj, distorterMaxFOV, renderer);
}
vertexGrid->lock();
}
StelViewportDistorterFisheyeToSphericMirror::~StelViewportDistorterFisheyeT
oSphericMirror(void)
{
if(NULL != texCoordGrid) {delete[] texCoordGrid;}
if(NULL != vertexGrid) {delete vertexGrid;}
foreach(StelIndexBuffer* buffer, stripBuffers)
{
delete buffer;
}
// TODO repair
// prj->setMaxFov(original_max_fov);
// prj->setViewport(original_viewport[0],original_viewport[1],
// original_viewport[2],original_viewport[3],
// original_viewportCenter[0],original_viewportCent
er[1],
// original_viewportFovDiameter);
}
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 vie
wport size of
// 512*512 and viewportFovDiameter=512 you will get
clamping artefacts
// in the 3 otherwise black hills on the bottom of t
he image.
// if (x < 0.f) {x=0.f;height=0;}
// else if (x > newProjectorParams.viewportXywh
[2])
// {x=newProjectorParams.viewportXywh[2];he
ight=0;}
// if (y < 0.f) {y=0.f;height=0;}
// else if (y > newProjectorParams.viewportXywh
[3])
// {y=newProjectorParams.viewportXywh[3];he
ight=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 // init transformation
height) VertexPoint *vertex_point_array = 0;
for (int row = 0; row <= maxGridY; row++) const QString custom_distortion_file = conf.value("spheric_mirror/cu
{ stom_distortion_file","").toString();
for (int col = 0; col <= maxGridX; col++) if (custom_distortion_file.isEmpty())
{
float texture_triangle_base_length = conf.value("spheric_mir
ror/texture_triangle_base_length",16.f).toFloat();
if (texture_triangle_base_length > 256.f)
texture_triangle_base_length = 256.f;
else if (texture_triangle_base_length < 2.f)
texture_triangle_base_length = 2.f;
max_x = (int)trunc(0.5 + screen_w/texture_triangle_base_leng
th);
step_x = screen_w / (double)(max_x-0.5);
max_y = (int)trunc(screen_h/(texture_triangle_base_length*0.
5*sqrt(3.0)));
step_y = screen_h/ (double)max_y;
double gamma = conf.value("spheric_mirror/projector_gamma",0
.45).toDouble();
if (gamma < 0.0)
gamma = 0.0;
const float view_scaling_factor = 0.5 * newProjectorParams.v
iewportFovDiameter / prj->fovToViewScalingFactor(distorter_max_fov*(M_PI/36
0.0));
texture_point_array = new Vec2f[(max_x+1)*(max_y+1)];
vertex_point_array = new VertexPoint[(max_x+1)*(max_y+1)];
double max_h = 0;
SphericMirrorCalculator calc(conf);
for (int j=0;j<=max_y;j++)
{ {
const int cell = row * cols + col; for (int i=0;i<=max_x;i++)
{
VertexPoint &vertex_point(vertex_point_array
[(j*(max_x+1)+i)]);
Vec2f &texture_point(texture_point_array[(j*
(max_x+1)+i)]);
vertex_point.ver_xy[0] = ((i == 0) ? 0.f : (
i == max_x) ? screen_w : (i-0.5f*(j&1))*step_x);
vertex_point.ver_xy[1] = j*step_y;
Vec3f v,vX,vY;
bool rc = calc.retransform(
(vertex_point.ver_
xy[0]-0.5f*screen_w) / screen_h,
(vertex_point.ver_
xy[1]-0.5f*screen_h) / screen_h, v,vX,vY);
rc &= prj->forward(v);
const float x = newProjectorParams.viewportC
enter[0] + v[0] * view_scaling_factor;
const float y = newProjectorParams.viewportC
enter[1] + v[1] * view_scaling_factor;
vertex_point.h = rc ? (vX^vY).length() : 0.0
;
// sharp image up to the border of the fishe
ye 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. Wi
th a viewport size
// of 512*512 and viewportFovDiameter=512 yo
u will get clamping
// artefacts in the 3 otherwise black hills
on the bottom of the image.
// if (x < 0.f) {x=0.f;vertex_point.h=0
;}
// else if (x > newProjectorParams.view
portXywh[2]) {x=newProjectorParams.viewportXywh[2];vertex_point.h=0;}
// if (y < 0.f) {y=0.f;vertex_point.h=0
;}
// else if (y > newProjectorParams.view
portXywh[3]) {y=newProjectorParams.viewportXywh[3];vertex_point.h=0;}
// Getting/setting each vertex is not that efficient texture_point[0] = (viewport_texture_offset[
, but we only do this 0]+x)/texture_wh;
// at startup. texture_point[1] = (viewport_texture_offset[
Vertex vertex = vertexGrid->getVertex(cell); 1]+y)/texture_wh;
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); if (vertex_point.h > max_h) max_h = vertex_p
oint.h;
}
} }
} for (int j=0;j<=max_y;j++)
constructVertexBuffer(renderer);
delete[] heightGrid;
// FIXME: Comment out with /**/ after testing. --BM // FIXME: Comment out with /**/ after testing. --BM
qDebug() << "StelViewportDistorterFisheyeToSphericMirror():" /*qDebug() << "StelViewportDistorterFisheyeToSphericMirror():"
<< "screen_w:" << this->screenWidth << "screen_w:" << this->screenWidth
<< "screen_h:" << this->screenHeight << endl << "screen_h:" << this->screenHeight << endl
<< "originalProjectorParams.viewportXywh:" << "originalProjectorParams.viewportXywh:"
<< originalProjectorParams.viewportXywh[0] << originalProjectorParams.viewportXywh[0]
<< originalProjectorParams.viewportXywh[1] << originalProjectorParams.viewportXywh[1]
<< originalProjectorParams.viewportXywh[2] << originalProjectorParams.viewportXywh[2]
<< originalProjectorParams.viewportXywh[3] << endl << originalProjectorParams.viewportXywh[3] << endl
<< "newProjectorParams.viewportXywh:" << "newProjectorParams.viewportXywh:"
<< newProjectorParams.viewportXywh[0] << newProjectorParams.viewportXywh[0]
<< newProjectorParams.viewportXywh[1] << newProjectorParams.viewportXywh[1]
skipping to change at line 284 skipping to change at line 214
<< originalProjectorParams.zFar << endl << originalProjectorParams.zFar << endl
<< "newProjectorParams.zNear,zFar:" << "newProjectorParams.zNear,zFar:"
<< newProjectorParams.zNear << newProjectorParams.zNear
<< newProjectorParams.zFar << endl << newProjectorParams.zFar << endl
//<< "viewport_texture_offset:" //<< "viewport_texture_offset:"
//<< viewport_texture_offset[0] //<< viewport_texture_offset[0]
//<< viewport_texture_offset[1] << endl //<< viewport_texture_offset[1] << endl
<< "texture_w:" << texture_w << endl << "texture_w:" << texture_w << endl
<< "texture_h:" << texture_h << endl << "texture_h:" << texture_h << endl
<< "max_x:" << maxGridX << endl << "max_x:" << maxGridX << endl
<< "max_y:" << maxGridY; << "max_y:" << maxGridY;*/
} {
for (int i=0;i<=max_x;i++)
void StelViewportDistorterFisheyeToSphericMirror::loadGenerationParameters {
(const QSettings& conf, double& gamma) VertexPoint &vertex_point(vertex_point_array
{ [(j*(max_x+1)+i)]);
// Load generation parameters. vertex_point.color[0] = vertex_point.color[1
float triangleBaseLength = ] = vertex_point.color[2] =
conf.value("spheric_mirror/texture_triangle_base_length",16.f).t
oFloat(); (vertex_point.h<=0.0) ? 0.0 : exp(gamma*log(vertex_point.h/max_
if (triangleBaseLength > 256.f) h));
{ vertex_point.color[3] = 1.0f;
qDebug() << "spheric_mirror/texture_triangle_base_length too }
high : setting to 256.0"; }
triangleBaseLength = 256.f;
}
else if (triangleBaseLength < 2.0f)
{
qDebug() << "spheric_mirror/texture_triangle_base_length too
low : setting to 2.0";
triangleBaseLength = 2.f;
}
#ifdef _MSC_BUILD // MSVC does not have a trunc function
maxGridX = (int)floor(0.5 + screenWidth / triangleBaseLength);
maxGridY = (int)floor(screenHeight / (triangleBaseLength * 0.5 * sqr
t(3.0)));
#else
maxGridX = (int)trunc(0.5 + screenWidth / triangleBaseLength);
maxGridY = (int)trunc(screenHeight / (triangleBaseLength * 0.5 * sqr
t(3.0)));
#endif
stepX = screenWidth / (double)(maxGridX - 0.5);
stepY = screenHeight / (double)maxGridY;
gamma = conf.value("spheric_mirror/projector_gamma",0.45).toDouble()
;
if (gamma < 0.0)
{
qDebug() << "Negative spheric_mirror/projector_gamma : setti
ng to zero.";
gamma = 0.0;
}
}
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) else
{ {
qWarning() << "WARNING: could not open custom_distortion_fil QFile file;
e:" << QDir::toNativeSeparators(fileName) << e.what(); QTextStream in;
return false; QString fName = StelFileMgr::findFile(custom_distortion_file
);
if (fName.isEmpty())
qWarning() << "WARNING: could not open custom_distor
tion_file:" << custom_distortion_file;
else
{
file.setFileName(fName);
if(file.open(QIODevice::ReadOnly))
in.setDevice(&file);
else
qWarning() << "WARNING: could not open custo
m_distortion_file:" << custom_distortion_file;
}
Q_ASSERT(file.error()!=QFile::NoError);
in >> max_x >> max_y;
Q_ASSERT(in.status()==QTextStream::Ok && max_x>0 && max_y>0)
;
step_x = screen_w / (double)(max_x-0.5);
step_y = screen_h/ (double)max_y;
texture_point_array = new Vec2f[(max_x+1)*(max_y+1)];
vertex_point_array = new VertexPoint[(max_x+1)*(max_y+1)];
for (int j=0;j<=max_y;j++)
{
for (int i=0;i<=max_x;i++)
{
VertexPoint &vertex_point(vertex_point_array
[(j*(max_x+1)+i)]);
Vec2f &texture_point(texture_point_array[(j*
(max_x+1)+i)]);
vertex_point.ver_xy[0] = ((i == 0) ? 0.f : (
i == max_x) ? screen_w : (i-0.5f*(j&1))*step_x);
vertex_point.ver_xy[1] = j*step_y;
float x,y;
in >> x >> y >> vertex_point.color[0] >> ver
tex_point.color[1] >> vertex_point.color[2];
vertex_point.color[3] = 1.0f;
Q_ASSERT(in.status()!=QTextStream::Ok);
texture_point[0] = (viewport_texture_offset[
0]+x)/texture_wh;
texture_point[1] = (viewport_texture_offset[
1]+y)/texture_wh;
}
}
} }
Q_ASSERT(file.error() != QFile::NoError);
in >> maxGridX >> maxGridY; // initialize the display list
Q_ASSERT(in.status() == QTextStream::Ok && maxGridX > 0 && maxGridY displayVertexList.clear();
> 0); for (int j=0;j<max_y;j++)
stepX = screenWidth / (double)(maxGridX - 0.5); {
stepY = screenHeight / (double)maxGridY; const Vec2f *t0 = texture_point_array + j*(max_x+1);
const Vec2f *t1 = t0;
const int cols = maxGridX + 1; const VertexPoint *v0 = vertex_point_array + j*(max_x+1);
const int rows = maxGridY + 1; const VertexPoint *v1 = v0;
if (j&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; t1 += (max_x+1);
// Clamp to screen extents. v1 += (max_x+1);
vertex.position[0] = (col == 0) ? 0.f : }
(col == maxGridX) ? screenWidth else
: {
(col - 0.5f t0 += (max_x+1);
* (row & 1)) * stepX; v0 += (max_x+1);
vertex.position[1] = row * stepY; }
float x, y; for (int i=0;i<=max_x;i++,t0++,t1++,v0++,v1++)
in >> x >> y >> vertex.color[0] >> vertex.color[1] > {
> vertex.color[2]; displayColorList << v0->color << v1->color;
vertex.color[3] = 1.0f; displayTexCoordList << *t0 << *t1;
Q_ASSERT(in.status() != QTextStream::Ok); displayVertexList << v0->ver_xy << v1->ver_xy;
vertex.texCoord[0] = x / texture_w;
vertex.texCoord[1] = y / texture_h;
texCoordGrid[row * cols + col] = vertex.texCoord;
vertexGrid->addVertex(vertex);
} }
} }
delete[] vertex_point_array;
constructVertexBuffer(renderer);
return true;
} }
void StelViewportDistorterFisheyeToSphericMirror::constructVertexBuffer StelViewportDistorterFisheyeToSphericMirror::~StelViewportDistorterFisheyeT
(StelRenderer *renderer) oSphericMirror(void)
{ {
const int cols = maxGridX + 1; if (texture_point_array)
delete[] texture_point_array;
// Each row is a triangle strip.
for (int row = 0; row < maxGridY; row++)
{
StelIndexBuffer* buffer = renderer->createIndexBuffer(IndexT
ype_U32);
// Two rows of vertices make up one row of the grid.
uint i0 = row * cols;
uint i1 = i0;
// Alternating between the "first" and the "second" vertex r
ow.
if (row & 1) {i1 += cols;}
else {i0 += cols;}
for (int col = 0; col < cols; col++,i0++,i1++) // TODO repair
{ // prj->setMaxFov(original_max_fov);
buffer->addIndex(i0); // prj->setViewport(original_viewport[0],original_viewport[1],
buffer->addIndex(i1); // original_viewport[2],original_viewport[3],
} // original_viewportCenter[0],original_viewpor
buffer->lock(); tCenter[1],
stripBuffers.append(buffer); // original_viewportFovDiameter);
}
} }
void StelViewportDistorterFisheyeToSphericMirror::distortXY(float& x, float & y) const void StelViewportDistorterFisheyeToSphericMirror::distortXY(float& x, float & y) const
{ {
float textureX, textureY; float texture_x,texture_y;
// find the triangle and interpolate accordingly: // find the triangle and interpolate accordingly:
float dy = y / stepY; float dy = y / step_y;
const int j = (int)floorf(dy); const int j = (int)floorf(dy);
const int cols = maxGridX + 1;
dy -= j; dy -= j;
if (j&1) if (j&1)
{ {
float dx = x / stepX + 0.5f * (1.f - dy); float dx = x / step_x + 0.5f*(1.f-dy);
const int i = (int)floorf(dx); const int i = (int)floorf(dx);
dx -= i; dx -= i;
const Vec2f *const t = texture_point_array + (j*(max_x+1)+i)
const Vec2f* const t = texCoordGrid + (j * cols + i); ;
if (dx + dy <= 1.f) if (dx + dy <= 1.f)
{ {
if (i == 0) if (i == 0)
{ {
dx -= 0.5f*(1.f-dy); dx -= 0.5f*(1.f-dy);
dx *= 2.f; dx *= 2.f;
} }
//This vertex texture_x = t[0][0] + dx * (t[1][0]-t[0][0]) + dy *
const Vec2f t0 = t[0]; (t[max_x+1][0]-t[0][0]);
//Next vertex texture_y = t[0][1] + dx * (t[1][1]-t[0][1]) + dy *
const Vec2f t1 = t[1]; (t[max_x+1][1]-t[0][1]);
//Vertex on next line
const Vec2f t2 = t[cols];
textureX = t0[0] + dx * (t1[0]-t0[0]) + dy * (t2[0]-
t0[0]);
textureY = t0[1] + dx * (t1[1]-t0[1]) + dy * (t2[1]-
t0[1]);
} }
else else
{ {
if (i == maxGridX-1) if (i == max_x-1)
{ {
dx -= 0.5f * (1.f - dy); dx -= 0.5f*(1.f-dy);
dx *= 2.f; dx *= 2.f;
} }
//Next vertex on this line texture_x = t[max_x+2][0] + (1.f-dy) * (t[1][0]-t[ma
const Vec2f t0 = t[1]; x_x+2][0]) + (1.f-dx) * (t[max_x+1][0]-t[max_x+2][0]);
//This vertex on next line texture_y = t[max_x+2][1] + (1.f-dy) * (t[1][1]-t[ma
const Vec2f t1 = t[cols]; x_x+2][1]) + (1.f-dx) * (t[max_x+1][1]-t[max_x+2][1]);
//Next vertex on next line
const Vec2f t2 = t[cols + 1];
textureX = t2[0] + (1.f-dy) * (t0[0]-t2[0]) + (1.f-d
x) * (t1[0]-t2[0]);
textureY = t2[1] + (1.f-dy) * (t0[1]-t2[1]) + (1.f-d
x) * (t1[1]-t2[1]);
} }
} }
else else
{ {
float dx = x / stepX + 0.5f*dy; float dx = x / step_x + 0.5f*dy;
const int i = (int)floorf(dx); const int i = (int)floorf(dx);
dx -= i; dx -= i;
const Vec2f *const t = texCoordGrid + (j * cols + i); const Vec2f *const t = texture_point_array + (j*(max_x+1)+i) ;
if (dx >= dy) if (dx >= dy)
{ {
if (i == maxGridX-1) if (i == max_x-1)
{ {
dx -= 0.5f*dy; dx -= 0.5f*dy;
dx *= 2.f; dx *= 2.f;
} }
//This vertex texture_x = t[1][0] + (1.f-dx) * (t[0][0]-t[1][0]) +
const Vec2f t0 = t[0]; dy * (t[max_x+2][0]-t[1][0]);
//Next vertex texture_y = t[1][1] + (1.f-dx) * (t[0][1]-t[1][1]) +
const Vec2f t1 = t[1]; dy * (t[max_x+2][1]-t[1][1]);
//Next vertex on next line
const Vec2f t2 = t[cols + 1];
textureX = t1[0] + (1.f-dx) * (t0[0]-t1[0]) + dy * (
t2[0]-t1[0]);
textureY = t1[1] + (1.f-dx) * (t0[1]-t1[1]) + dy * (
t2[1]-t1[1]);
} }
else else
{ {
if (i == 0) if (i == 0)
{ {
dx -= 0.5f*dy; dx -= 0.5f*dy;
dx *= 2.f; dx *= 2.f;
} }
//This vertex texture_x = t[max_x+1][0] + (1.f-dy) * (t[0][0]-t[ma
const Vec2f t0 = t[0]; x_x+1][0]) + dx * (t[max_x+2][0]-t[max_x+1][0]);
//This vertex on next line texture_y = t[max_x+1][1] + (1.f-dy) * (t[0][1]-t[ma
const Vec2f t1 = t[cols]; x_x+1][1]) + dx * (t[max_x+2][1]-t[max_x+1][1]);
//Next vertex on next line
const Vec2f t2 = t[cols + 1];
textureX = t1[0] + (1.f-dy) * (t0[0]-t1[0]) + dx * (
t2[0]-t1[0]);
textureY = t1[1] + (1.f-dy) * (t0[1]-t1[1]) + dx * (
t2[1]-t1[1]);
} }
} }
x = texture_w*textureX + newProjectorParams.viewportXywh[0]; x = texture_wh*texture_x - viewport_texture_offset[0] + newProjector
y = texture_h*textureY + newProjectorParams.viewportXywh[1]; Params.viewportXywh[0];
y = texture_wh*texture_y - viewport_texture_offset[1] + newProjector
Params.viewportXywh[1];
} }
void StelViewportDistorterFisheyeToSphericMirror::recalculateTexCoords(cons t QSizeF newMaxTexCoords) void StelViewportDistorterFisheyeToSphericMirror::paintViewportBuffer(const QOpenGLFramebufferObject* buf) const
{ {
const float xMult = newMaxTexCoords.width() / maxTexCoords.width(); StelPainter sPainter(StelApp::getInstance().getCore()->getProjection
const float yMult = newMaxTexCoords.height() / maxTexCoords.height() 2d());
; sPainter.enableTexture2d(true);
glBindTexture(GL_TEXTURE_2D, buf->texture());
vertexGrid->unlock(); glDisable(GL_BLEND);
const int length = vertexGrid->length();
Vertex vertex; sPainter.enableClientStates(true, true, true);
for(int v = 0; v < length; ++v) sPainter.setColorPointer(4, GL_FLOAT, displayColorList.constData());
sPainter.setVertexPointer(2, GL_FLOAT, displayVertexList.constData()
);
sPainter.setTexCoordPointer(2, GL_FLOAT, displayTexCoordList.constDa
ta());
for (int j=0;j<max_y;j++)
{ {
vertex = vertexGrid->getVertex(v); sPainter.drawFromArray(StelPainter::TriangleStrip, (max_x+1)
vertex.texCoord[0] *= xMult; *2, j*(max_x+1)*2, false);
vertex.texCoord[1] *= yMult;
texCoordGrid[v][0] *= xMult;
texCoordGrid[v][1] *= xMult;
vertexGrid->setVertex(v, vertex);
} }
vertexGrid->lock(); sPainter.enableClientStates(false);
maxTexCoords = newMaxTexCoords;
}
void StelViewportDistorterFisheyeToSphericMirror::drawToViewport(StelRender
er* renderer)
{
// Screen texture might be larger than the screen
// if power-of-two textures are required.
// In such cases, we need to adjust texture coordinates
// and do that every time screen size is changed.
StelTextureNew* screenTexture = renderer->getViewportTexture();
const QSize viewportSize = renderer->getViewportSize();
const QSize texSize = screenTexture->getDimensions();
const QSizeF newMaxTexCoords(viewportSize.width() / static_cast<floa
t>(texSize.width()),
viewportSize.height() / static_cast<flo
at>(texSize.height()));
if(maxTexCoords != newMaxTexCoords)
{
recalculateTexCoords(newMaxTexCoords);
}
screenTexture->bind();
foreach(StelIndexBuffer* strip, stripBuffers)
{
renderer->drawVertexBuffer(vertexGrid, strip);
}
delete screenTexture;
} }
 End of changes. 53 change blocks. 
438 lines changed or deleted 297 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/