3
* Copyright (C) Fabien Chereau
4
* Author 2006 Johannes Gajdosik
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
#include "viewport_distorter.h"
22
#include "stel_core.h"
23
#include "spheric_mirror_calculator.h"
24
#include "init_parser.h"
26
#include "SDL_opengl.h"
28
class ViewportDistorterDummy : public ViewportDistorter {
30
friend class ViewportDistorter;
31
string getType(void) const {return "none";}
32
void init(const InitParser &conf) {}
33
void distort(void) const {}
34
bool distortXY(int &x,int &y) {return true;}
38
class ViewportDistorterFisheyeToSphericMirror : public ViewportDistorter {
40
friend class ViewportDistorter;
41
ViewportDistorterFisheyeToSphericMirror(int screenW,int screenH,
43
~ViewportDistorterFisheyeToSphericMirror(void);
44
string getType(void) const {return "fisheye_to_spheric_mirror";}
45
void init(const InitParser &conf);
46
void distort(void) const;
47
bool distortXY(int &x,int &y);
50
unsigned int mirror_texture;
58
VertexData *trans_array;
59
int trans_width,trans_height;
60
SphericMirrorCalculator calc;
64
ViewportDistorterFisheyeToSphericMirror
65
::ViewportDistorterFisheyeToSphericMirror(int screenW,int screenH,
67
:screenW(screenW),screenH(screenH),trans_array(0) {
68
if (core->getProjectionType() == "fisheye") {
69
core->setMaxFov(175.0);
71
cerr << "ViewportDistorterFisheyeToSphericMirror: "
72
<< "what are you doing? the projection type should be fisheye."
75
viewport_wh = (screenW < screenH) ? screenW : screenH;
77
while (texture_wh < viewport_wh) texture_wh <<= 1;
78
texture_used = viewport_wh / (float)texture_wh;
80
glGenTextures(1, &mirror_texture);
81
glBindTexture(GL_TEXTURE_2D, mirror_texture);
82
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
83
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
84
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
85
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
86
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
87
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture_wh, texture_wh, 0,
88
GL_RGB, GL_UNSIGNED_BYTE, 0);
90
// calc.setParams(Vec3d(0,-2,15),Vec3d(0,0,20),1,25,0.125);
93
void ViewportDistorterFisheyeToSphericMirror::init(const InitParser &conf) {
95
const double gamma = conf.get_double("spheric_mirror","projector_gamma",0.45);
96
// init transformation
97
trans_width = screenW / 16;
98
trans_height = screenH / 16;
99
trans_array = new VertexData[(trans_width+1)*(trans_height+1)];
101
for (int j=0;j<=trans_height;j++) {
102
for (int i=0;i<=trans_width;i++) {
103
VertexData &data(trans_array[(j*(trans_width+1)+i)]);
105
bool rc = calc.retransform(
106
(i-(trans_width>>1))/(double)trans_height,
107
(j-(trans_height>>1))/(double)trans_height,
109
data.h = rc ? (v_x^v_y).length() : 0.0;
111
const double h = v[1];
114
const double oneoverh = 1./sqrt(v[0]*v[0]+v[1]*v[1]);
115
const double a = 0.5 + atan(v[2]*oneoverh)/M_PI; // range: [0..1]
116
double f = a* 180.0/175.0; // MAX_FOV=175.0 for fisheye
118
double x = (0.5 + v[0] * f);
119
double y = (0.5 + v[1] * f);
120
if (x < 0.0) {x=0.0;data.h=0;} else if (x > 1.0) {x=1.0;data.h=0;}
121
if (y < 0.0) {y=0.0;data.h=0;} else if (y > 1.0) {y=1.0;data.h=0;}
122
data.xy[0] = x*texture_used;
123
data.xy[1] = y*texture_used;
124
if (data.h > max_h) max_h = data.h;
127
for (int j=0;j<=trans_height;j++) {
128
for (int i=0;i<=trans_width;i++) {
129
VertexData &data(trans_array[(j*(trans_width+1)+i)]);
130
data.color[0] = data.color[1] = data.color[2] =
131
(data.h<=0.0) ? 0.0 : exp(gamma*log(data.h/max_h));
132
data.color[3] = 1.0f;
137
ViewportDistorterFisheyeToSphericMirror
138
::~ViewportDistorterFisheyeToSphericMirror(void) {
139
if (trans_array) delete[] trans_array;
140
glDeleteTextures(1,&mirror_texture);
143
bool ViewportDistorterFisheyeToSphericMirror::distortXY(int &x,int &y) {
144
// linear interpolation:
146
const float dx = (x&15)/16.0f;
147
const int i = x >> 4;
148
const float dy = (y&15)/16.0f;
149
const int j = y >> 4;
150
const float f00 = (1.0f-dx)*(1.0f-dy);
151
const float f01 = ( dx)*(1.0f-dy);
152
const float f10 = (1.0f-dx)*( dy);
153
const float f11 = ( dx)*( dy);
154
const VertexData *const v = trans_array + (j*(trans_width+1)+i);
155
x = ((screenW-viewport_wh)>>1)
159
+ v[trans_width+1].xy[0]*f10
160
+ v[trans_width+2].xy[0]*f11)*viewport_wh/texture_used);
161
y = ((screenH-viewport_wh)>>1)
165
+ v[trans_width+1].xy[1]*f10
166
+ v[trans_width+2].xy[1]*f11)*viewport_wh/texture_used));
171
void ViewportDistorterFisheyeToSphericMirror::distort(void) const {
172
glViewport(0, 0, screenW, screenH);
173
glMatrixMode(GL_PROJECTION); // projection matrix mode
174
glPushMatrix(); // store previous matrix
176
gluOrtho2D(0,screenW,0,screenH); // set a 2D orthographic projection
177
glMatrixMode(GL_MODELVIEW); // modelview matrix mode
182
glBindTexture(GL_TEXTURE_2D, mirror_texture);
183
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
184
(screenW-viewport_wh)>>1,(screenH-viewport_wh)>>1,
185
viewport_wh,viewport_wh);
187
glEnable(GL_TEXTURE_2D);
189
float color[4] = {1,1,1,1};
192
glBindTexture(GL_TEXTURE_2D, mirror_texture);
196
glTexCoord2f(0.0, 0.0); glVertex3f(screenW,0, 0.0);
197
glTexCoord2f(texture_used, 0.0); glVertex3f(0,0, 0.0);
198
glTexCoord2f(texture_used, texture_used); glVertex3f(0, screenH, 0.0);
199
glTexCoord2f(0.0, texture_used); glVertex3f(screenW, screenH, 0.0);
204
for (int j=0;j<trans_height;j++) {
205
glBegin(GL_QUAD_STRIP);
206
const VertexData *v0 = trans_array + j*(trans_width+1);
207
const VertexData *v1 = v0 + (trans_width+1);
208
for (int i=0;i<=trans_width;i++) {
209
glColor4fv(v0[i].color);
210
glTexCoord2fv(v0[i].xy);
211
glVertex3f(i*16, j*16, 0.0);
212
glColor4fv(v1[i].color);
213
glTexCoord2fv(v1[i].xy);
214
glVertex3f(i*16, (j+1)*16, 0.0);
220
glMatrixMode(GL_PROJECTION); // Restore previous matrix
222
glMatrixMode(GL_MODELVIEW);
226
ViewportDistorter *ViewportDistorter::create(const string &type,
227
int width,int height,
229
if (type == "fisheye_to_spheric_mirror") {
230
return new ViewportDistorterFisheyeToSphericMirror(width,height,core);
232
return new ViewportDistorterDummy;