StelViewportEffect.cpp   StelViewportEffect.cpp 
skipping to change at line 23 skipping to change at line 23
* 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 "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 <QGLFramebufferObject>
#include <QSettings> #include <QSettings>
#include <QFile> #include <QFile>
void StelViewportEffect::paintViewportBuffer(const QGLFramebufferObject* bu StelViewportDistorterFisheyeToSphericMirror::StelViewportDistorterFisheyeTo
f) const SphericMirror
{ (int screenWidth,int screenHeight, StelRenderer* renderer)
StelPainter sPainter(StelApp::getInstance().getCore()->getProjection : screenWidth(screenWidth)
2d()); , screenHeight(screenHeight)
sPainter.setColor(1,1,1); , originalProjectorParams(StelApp::getInstance().getCore()->
sPainter.enableTexture2d(true); getCurrentStelProjectorParams())
glBindTexture(GL_TEXTURE_2D, buf->texture()); , maxTexCoords(1.0f, 1.0f)
sPainter.drawRect2d(0, 0, buf->size().width(), buf->size().height()) , texCoordGrid(NULL)
; , 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()->ge
tCurrentStelProjectorParams()),
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 distorter_max_fov = conf.value("spheric_mirror/distorter_max_ double distorterMaxFOV = conf.value("spheric_mirror/distorter_max_fo
fov",175.f).toFloat(); v",175.f).toFloat();
if (distorter_max_fov > 240.f) if (distorterMaxFOV > 240.f)
distorter_max_fov = 240.f; {
else if (distorter_max_fov < 120.f) qDebug() << "spheric_mirror/distorter_max_fov too high : set
distorter_max_fov = 120.f; ting to 240.0";
if (distorter_max_fov > core->getMovementMgr()->getMaxFov()) distorterMaxFOV = 240.f;
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 prj = core->getProjection(StelCore::FrameJ2000); StelProjectorP proj = core->getProjection(StelCore::FrameJ2000);
core->getMovementMgr()->setMaxFov(distorter_max_fov); core->getMovementMgr()->setMaxFov(distorterMaxFOV);
// width of the not yet distorted image // width of the not yet distorted image
newProjectorParams.viewportXywh[2] = conf.value("spheric_mirror/newP newProjectorParams.viewportXywh[2] =
rojectorParams.viewportXywh[2]idth", originalProjectorParams.viewportXywh[2 conf.value("spheric_mirror/newProjectorParams.viewportXywh[2]idt
]).toInt(); h",
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] > screen_w) else if (newProjectorParams.viewportXywh[2] > screenWidth)
{ {
newProjectorParams.viewportXywh[2] = screen_w; newProjectorParams.viewportXywh[2] = screenWidth;
} }
// height of the not yet distorted image // height of the not yet distorted image
newProjectorParams.viewportXywh[3] = conf.value("spheric_mirror/newP newProjectorParams.viewportXywh[3] =
rojectorParams.viewportXywh[3]eight", originalProjectorParams.viewportXywh[ conf.value("spheric_mirror/newProjectorParams.viewportXywh[3]eig
3]).toInt(); ht",
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] > screen_h) else if (newProjectorParams.viewportXywh[3] > screenHeight)
{ {
newProjectorParams.viewportXywh[3] = screen_h; newProjectorParams.viewportXywh[3] = screenHeight;
} }
// 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] = conf.value("spheric_mirror/vi newProjectorParams.viewportCenter[0] =
ewportCenterX", 0.5*newProjectorParams.viewportXywh[2]).toFloat(); conf.value("spheric_mirror/viewportCenterX",
newProjectorParams.viewportCenter[1] = conf.value("spheric_mirror/vi 0.5*newProjectorParams.viewportXywh[2]).toFloat();
ewportCenterY", 0.5*newProjectorParams.viewportXywh[3]).toFloat(); newProjectorParams.viewportCenter[1] =
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 = conf.value("spheric_mirror/ newProjectorParams.viewportFovDiameter =
viewport_fov_diameter", qMin(newProjectorParams.viewportXywh[2],newProjecto conf.value("spheric_mirror/viewport_fov_diameter",
rParams.viewportXywh[3])).toFloat(); qMin(newProjectorParams.viewportXywh[2],
newProjectorParams.viewportXywh[3])).toFloat();
texture_wh = 1; texture_wh = 1;
while (texture_wh < newProjectorParams.viewportXywh[2] || texture_wh while (texture_wh < newProjectorParams.viewportXywh[2] ||
< newProjectorParams.viewportXywh[3]) texture_wh < newProjectorParams.viewportXywh[3])
{
texture_wh <<= 1; texture_wh <<= 1;
viewport_texture_offset[0] = (texture_wh-newProjectorParams.viewport }
Xywh[2])>>1;
viewport_texture_offset[1] = (texture_wh-newProjectorParams.viewport
Xywh[3])>>1;
newProjectorParams.viewportXywh[0] = (screen_w-newProjectorParams.vi viewportTextureOffset[0] = (texture_wh-newProjectorParams.viewportXy
ewportXywh[2]) >> 1; wh[2])>>1;
newProjectorParams.viewportXywh[1] = (screen_h-newProjectorParams.vi viewportTextureOffset[1] = (texture_wh-newProjectorParams.viewportXy
ewportXywh[3]) >> 1; wh[3])>>1;
newProjectorParams.viewportXywh[0] = (screenWidth-newProjectorParams
.viewportXywh[2]) >> 1;
newProjectorParams.viewportXywh[1] = (screenHeight-newProjectorParam
s.viewportXywh[3]) >> 1;
StelApp::getInstance().getCore()->setCurrentStelProjectorParams(newP rojectorParams); StelApp::getInstance().getCore()->setCurrentStelProjectorParams(newP rojectorParams);
// init transformation const QString customDistortionFileName =
VertexPoint *vertex_point_array = 0; conf.value("spheric_mirror/custom_distortion_file","").toString(
const QString custom_distortion_file = conf.value("spheric_mirror/cu );
stom_distortion_file","").toString();
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++)
{
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;}
texture_point[0] = (viewport_texture_offset[ if (customDistortionFileName.isEmpty())
0]+x)/texture_wh; {
texture_point[1] = (viewport_texture_offset[ generateDistortion(conf, proj, distorterMaxFOV, renderer);
1]+y)/texture_wh; }
else if (!loadDistortionFromFile(customDistortionFileName, renderer)
)
{
qDebug() << "Falling back to generated distortion";
generateDistortion(conf, proj, distorterMaxFOV, renderer);
}
if (vertex_point.h > max_h) max_h = vertex_p vertexGrid->lock();
oint.h; }
}
} StelViewportDistorterFisheyeToSphericMirror::~StelViewportDistorterFisheyeT
for (int j=0;j<=max_y;j++) oSphericMirror(void)
{ {
for (int i=0;i<=max_x;i++) if(NULL != texCoordGrid) {delete[] texCoordGrid;}
{ if(NULL != vertexGrid) {delete vertexGrid;}
VertexPoint &vertex_point(vertex_point_array
[(j*(max_x+1)+i)]); foreach(StelIndexBuffer* buffer, stripBuffers)
vertex_point.color[0] = vertex_point.color[1 {
] = vertex_point.color[2] = delete buffer;
(vertex_point.h<=0.0) ? 0.0 : exp(gamma*log(vertex_point.h/max_
h));
vertex_point.color[3] = 1.0f;
}
}
} }
else // 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++)
{ {
QFile file; for (int col = 0; col <= maxGridX; col++)
QTextStream in;
try
{
file.setFileName(StelFileMgr::findFile(custom_distor
tion_file));
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_distor Vertex vertex;
tion_file:" << custom_distortion_file << e.what(); float &height(heightGrid[row * cols + col]);
}
Q_ASSERT(file.error()!=QFile::NoError); // Clamp to screen extents.
in >> max_x >> max_y; vertex.position[0] = (col == 0) ? 0.f :
Q_ASSERT(in.status()==QTextStream::Ok && max_x>0 && max_y>0) (col == maxGridX) ? screenWidth
; :
step_x = screen_w / (double)(max_x-0.5); (col - 0.5f
step_y = screen_h/ (double)max_y; * (row & 1)) * stepX;
texture_point_array = new Vec2f[(max_x+1)*(max_y+1)]; vertex.position[1] = row * stepY;
vertex_point_array = new VertexPoint[(max_x+1)*(max_y+1)]; Vec3f v,vX,vY;
for (int j=0;j<=max_y;j++) bool rc = calc.retransform((vertex.position[0]-0.5f*
{ screenWidth) / screenHeight,
for (int i=0;i<=max_x;i++) (vertex.position[1]-0.5f*
{ screenHeight) / screenHeight,
VertexPoint &vertex_point(vertex_point_array v,vX,vY);
[(j*(max_x+1)+i)]);
Vec2f &texture_point(texture_point_array[(j* rc &= proj->forward(v);
(max_x+1)+i)]); const float x = newProjectorParams.viewportCenter[0]
vertex_point.ver_xy[0] = ((i == 0) ? 0.f : ( + v[0] * viewScale;
i == max_x) ? screen_w : (i-0.5f*(j&1))*step_x); const float y = newProjectorParams.viewportCenter[1]
vertex_point.ver_xy[1] = j*step_y; + v[1] * viewScale;
float x,y; height = rc ? (vX^vY).length() : 0.0;
in >> x >> y >> vertex_point.color[0] >> ver
tex_point.color[1] >> vertex_point.color[2]; // sharp image up to the border of the fisheye image
vertex_point.color[3] = 1.0f; , at the cost of
Q_ASSERT(in.status()!=QTextStream::Ok); // accepting clamping artefacts. You can get rid of
texture_point[0] = (viewport_texture_offset[ the clamping
0]+x)/texture_wh; // artefacts by specifying a viewport size a little
texture_point[1] = (viewport_texture_offset[ less then
1]+y)/texture_wh; // (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] = (viewportTextureOffset[0] + x)
/ texture_wh;
vertex.texCoord[1] = (viewportTextureOffset[1] + y)
/ texture_wh;
texCoordGrid[row * cols + col] = vertex.texCoord;
vertexGrid->addVertex(vertex);
maxHeight = qMax(height, maxHeight);
} }
} }
// initialize the display list // Generate grid colors. (Separate from previous loop as we need max
displayVertexList.clear(); height)
for (int j=0;j<max_y;j++) for (int row = 0; row <= maxGridY; row++)
{ {
const Vec2f *t0 = texture_point_array + j*(max_x+1); for (int col = 0; col <= maxGridX; col++)
const Vec2f *t1 = t0;
const VertexPoint *v0 = vertex_point_array + j*(max_x+1);
const VertexPoint *v1 = v0;
if (j&1)
{
t1 += (max_x+1);
v1 += (max_x+1);
}
else
{ {
t0 += (max_x+1); const int cell = row * cols + col;
v0 += (max_x+1);
// 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);
} }
for (int i=0;i<=max_x;i++,t0++,t1++,v0++,v1++) }
constructVertexBuffer(renderer);
delete[] heightGrid;
}
void StelViewportDistorterFisheyeToSphericMirror::loadGenerationParameters
(const QSettings& conf, double& gamma)
{
// Load generation parameters.
float triangleBaseLength =
conf.value("spheric_mirror/texture_triangle_base_length",16.f).t
oFloat();
if (triangleBaseLength > 256.f)
{
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;
}
maxGridX = (int)trunc(0.5 + screenWidth / triangleBaseLength);
stepX = screenWidth / (double)(maxGridX - 0.5);
maxGridY = (int)trunc(screenHeight / (triangleBaseLength * 0.5 * sqr
t(3.0)));
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)
{
qWarning() << "WARNING: could not open custom_distortion_fil
e:" << 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++)
{ {
displayColorList << v0->color << v1->color; Vertex vertex;
displayTexCoordList << *t0 << *t1; // Clamp to screen extents.
displayVertexList << v0->ver_xy << v1->ver_xy; 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] = (viewportTextureOffset[0] + x)
/ texture_wh;
vertex.texCoord[1] = (viewportTextureOffset[1] + y)
/ texture_wh;
texCoordGrid[row * cols + col] = vertex.texCoord;
vertexGrid->addVertex(vertex);
} }
} }
delete[] vertex_point_array;
constructVertexBuffer(renderer);
return true;
} }
StelViewportDistorterFisheyeToSphericMirror::~StelViewportDistorterFisheyeT void StelViewportDistorterFisheyeToSphericMirror::constructVertexBuffer
oSphericMirror(void) (StelRenderer *renderer)
{ {
if (texture_point_array) const int cols = maxGridX + 1;
delete[] texture_point_array;
// TODO repair // Each row is a triangle strip.
// prj->setMaxFov(original_max_fov); for (int row = 0; row < maxGridY; row++)
// prj->setViewport(original_viewport[0],original_viewport[1], {
// original_viewport[2],original_viewport[3], StelIndexBuffer* buffer = renderer->createIndexBuffer(IndexT
// original_viewportCenter[0],original_viewpor ype_U32);
tCenter[1], // Two rows of vertices make up one row of the grid.
// original_viewportFovDiameter); 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++)
{
buffer->addIndex(i0);
buffer->addIndex(i1);
}
buffer->lock();
stripBuffers.append(buffer);
}
} }
void StelViewportDistorterFisheyeToSphericMirror::distortXY(float& x, float & y) const void StelViewportDistorterFisheyeToSphericMirror::distortXY(float& x, float & y) const
{ {
float texture_x,texture_y; float textureX, textureY;
// find the triangle and interpolate accordingly: // find the triangle and interpolate accordingly:
float dy = y / step_y; float dy = y / stepY;
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 / step_x + 0.5f*(1.f-dy); float dx = x / stepX + 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;
} }
texture_x = t[0][0] + dx * (t[1][0]-t[0][0]) + dy * //This vertex
(t[max_x+1][0]-t[0][0]); const Vec2f t0 = t[0];
texture_y = t[0][1] + dx * (t[1][1]-t[0][1]) + dy * //Next vertex
(t[max_x+1][1]-t[0][1]); const Vec2f t1 = t[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 == max_x-1) if (i == maxGridX-1)
{ {
dx -= 0.5f*(1.f-dy); dx -= 0.5f * (1.f - dy);
dx *= 2.f; dx *= 2.f;
} }
texture_x = t[max_x+2][0] + (1.f-dy) * (t[1][0]-t[ma //Next vertex on this line
x_x+2][0]) + (1.f-dx) * (t[max_x+1][0]-t[max_x+2][0]); const Vec2f t0 = t[1];
texture_y = t[max_x+2][1] + (1.f-dy) * (t[1][1]-t[ma //This vertex on next line
x_x+2][1]) + (1.f-dx) * (t[max_x+1][1]-t[max_x+2][1]); const Vec2f t1 = t[cols];
//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 / step_x + 0.5f*dy; float dx = x / stepX + 0.5f*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) if (dx >= dy)
{ {
if (i == max_x-1) if (i == maxGridX-1)
{ {
dx -= 0.5f*dy; dx -= 0.5f*dy;
dx *= 2.f; dx *= 2.f;
} }
texture_x = t[1][0] + (1.f-dx) * (t[0][0]-t[1][0]) + //This vertex
dy * (t[max_x+2][0]-t[1][0]); const Vec2f t0 = t[0];
texture_y = t[1][1] + (1.f-dx) * (t[0][1]-t[1][1]) + //Next vertex
dy * (t[max_x+2][1]-t[1][1]); const Vec2f t1 = t[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;
} }
texture_x = t[max_x+1][0] + (1.f-dy) * (t[0][0]-t[ma //This vertex
x_x+1][0]) + dx * (t[max_x+2][0]-t[max_x+1][0]); const Vec2f t0 = t[0];
texture_y = t[max_x+1][1] + (1.f-dy) * (t[0][1]-t[ma //This vertex on next line
x_x+1][1]) + dx * (t[max_x+2][1]-t[max_x+1][1]); const Vec2f t1 = t[cols];
//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_wh*texture_x - viewport_texture_offset[0] + newProjector x = texture_wh*textureX - viewportTextureOffset[0] + newProjectorPar
Params.viewportXywh[0]; ams.viewportXywh[0];
y = texture_wh*texture_y - viewport_texture_offset[1] + newProjector y = texture_wh*textureY - viewportTextureOffset[1] + newProjectorPar
Params.viewportXywh[1]; ams.viewportXywh[1];
} }
void StelViewportDistorterFisheyeToSphericMirror::paintViewportBuffer(const QGLFramebufferObject* buf) const void StelViewportDistorterFisheyeToSphericMirror::recalculateTexCoords(cons t QSizeF newMaxTexCoords)
{ {
StelPainter sPainter(StelApp::getInstance().getCore()->getProjection const float xMult = newMaxTexCoords.width() / maxTexCoords.width();
2d()); const float yMult = newMaxTexCoords.height() / maxTexCoords.height()
sPainter.enableTexture2d(true); ;
glBindTexture(GL_TEXTURE_2D, buf->texture());
glDisable(GL_BLEND); vertexGrid->unlock();
const int length = vertexGrid->length();
sPainter.enableClientStates(true, true, true); Vertex vertex;
sPainter.setColorPointer(4, GL_FLOAT, displayColorList.constData()); for(int v = 0; v < length; ++v)
sPainter.setVertexPointer(2, GL_FLOAT, displayVertexList.constData()
);
sPainter.setTexCoordPointer(2, GL_FLOAT, displayTexCoordList.constDa
ta());
for (int j=0;j<max_y;j++)
{ {
sPainter.drawFromArray(StelPainter::TriangleStrip, (max_x+1) vertex = vertexGrid->getVertex(v);
*2, j*(max_x+1)*2, false); vertex.texCoord[0] *= xMult;
vertex.texCoord[1] *= yMult;
texCoordGrid[v][0] *= xMult;
texCoordGrid[v][1] *= xMult;
vertexGrid->setVertex(v, vertex);
} }
sPainter.enableClientStates(false); vertexGrid->lock();
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. 50 change blocks. 
287 lines changed or deleted 431 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/