mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-08 10:40:41 +00:00
182 lines
4.4 KiB
C
182 lines
4.4 KiB
C
|
/*
|
||
|
gl_fisheye.c
|
||
|
|
||
|
GL fisheye rendering
|
||
|
|
||
|
Copyright (C) 2003 Arkadi Shishlov <arkadi@it.lv>
|
||
|
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||
|
|
||
|
This program is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU General Public License
|
||
|
as published by the Free Software Foundation; either version 2
|
||
|
of the License, or (at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
|
||
|
See the GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to:
|
||
|
|
||
|
Free Software Foundation, Inc.
|
||
|
59 Temple Place - Suite 330
|
||
|
Boston, MA 02111-1307, USA
|
||
|
|
||
|
*/
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
# include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#ifdef HAVE_STRING_H
|
||
|
# include <string.h>
|
||
|
#endif
|
||
|
#ifdef HAVE_STRINGS_H
|
||
|
# include <strings.h>
|
||
|
#endif
|
||
|
|
||
|
#include <math.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "QF/cvar.h"
|
||
|
#include "QF/mathlib.h"
|
||
|
#include "QF/render.h"
|
||
|
#include "QF/sys.h"
|
||
|
#include "QF/vid.h"
|
||
|
|
||
|
#include "QF/GL/defines.h"
|
||
|
#include "QF/GL/funcs.h"
|
||
|
#include "QF/GL/qf_draw.h"
|
||
|
#include "QF/GL/qf_fisheye.h"
|
||
|
#include "QF/GL/qf_vid.h"
|
||
|
|
||
|
#include "compat.h"
|
||
|
#include "r_internal.h"
|
||
|
#include "varrays.h"
|
||
|
#include "vid_gl.h"
|
||
|
|
||
|
// Algorithm:
|
||
|
// Draw up to six views, one in each direction.
|
||
|
// Save the picture to cube map texture, use GL_ARB_texture_cube_map.
|
||
|
// Create FPOLYCNTxFPOLYCNT polygons sized flat grid.
|
||
|
// Baseing on field of view, tie cube map texture to grid using
|
||
|
// translation function to map texture coordinates to fixed/regular
|
||
|
// grid vertices coordinates.
|
||
|
// Render view. Fisheye is done.
|
||
|
|
||
|
#define FPOLYCNT 128
|
||
|
|
||
|
struct xyz {
|
||
|
float x, y, z;
|
||
|
};
|
||
|
|
||
|
static struct xyz FisheyeLookupTbl[FPOLYCNT + 1][FPOLYCNT + 1];
|
||
|
//static GLint gl_cube_map_size;
|
||
|
static GLint gl_cube_map_step;
|
||
|
|
||
|
static void
|
||
|
R_BuildFisheyeLookup (int width, int height, float fov)
|
||
|
{
|
||
|
int x, y;
|
||
|
struct xyz *v;
|
||
|
|
||
|
for (y = 0; y <= height; y += gl_cube_map_step) {
|
||
|
for (x = 0; x <= width; x += gl_cube_map_step) {
|
||
|
float dx = x - width / 2;
|
||
|
float dy = y - height / 2;
|
||
|
float yaw = sqrt (dx * dx + dy * dy) * fov / width;
|
||
|
float roll = atan2 (dy, dx);
|
||
|
// X is a first index and Y is a second, because later
|
||
|
// when we draw QUAD_STRIPs we need next Y vertex coordinate.
|
||
|
v = &FisheyeLookupTbl[x / gl_cube_map_step][y / gl_cube_map_step];
|
||
|
v->x = sin (yaw) * cos (roll);
|
||
|
v->y = sin (yaw) * sin (roll);
|
||
|
v->z = cos (yaw);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define CHKGLERR(s) \
|
||
|
do { \
|
||
|
GLint err = qfglGetError(); \
|
||
|
if (err != GL_NO_ERROR) \
|
||
|
printf ("%s: gl error %d\n", s, (int) err); \
|
||
|
} while (0);
|
||
|
|
||
|
|
||
|
static GLuint fisheye_grid;
|
||
|
|
||
|
void
|
||
|
gl_InitFisheye (void)
|
||
|
{
|
||
|
fisheye_grid = qfglGenLists (1);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
build_display_list (int width, int height, float fov)
|
||
|
{
|
||
|
int maxd = max (width, height);
|
||
|
gl_cube_map_step = maxd / FPOLYCNT;
|
||
|
|
||
|
R_BuildFisheyeLookup (width, height, fov * M_PI / 180.0);
|
||
|
|
||
|
qfglNewList (fisheye_grid, GL_COMPILE);
|
||
|
|
||
|
qfglDisable (GL_DEPTH_TEST);
|
||
|
qfglFrontFace (GL_CCW);
|
||
|
qfglClear (GL_COLOR_BUFFER_BIT);
|
||
|
|
||
|
for (int y = 0; y < height; y += gl_cube_map_step) {
|
||
|
qfglBegin (GL_QUAD_STRIP);
|
||
|
// quad_strip, so X is inclusive
|
||
|
for (int x = 0; x <= width; x += gl_cube_map_step) {
|
||
|
int xind = x / gl_cube_map_step;
|
||
|
int yind = y / gl_cube_map_step;
|
||
|
struct xyz *v = &FisheyeLookupTbl[xind][yind + 1];
|
||
|
qfglTexCoord3f (v->x, v->y, v->z);
|
||
|
qfglVertex2i (x, y + gl_cube_map_step);
|
||
|
--v;
|
||
|
qfglTexCoord3f (v->x, v->y, v->z);
|
||
|
qfglVertex2i (x, y);
|
||
|
}
|
||
|
qfglEnd ();
|
||
|
}
|
||
|
qfglEnable (GL_DEPTH_TEST);
|
||
|
qfglEndList ();
|
||
|
CHKGLERR("build list");
|
||
|
}
|
||
|
|
||
|
void
|
||
|
gl_FisheyeScreen (framebuffer_t *fb)
|
||
|
{
|
||
|
static int pwidth = -1;
|
||
|
static int pheight = -1;
|
||
|
static float pfov = -1;
|
||
|
|
||
|
if (pwidth != r_refdef.vrect.width || pheight != r_refdef.vrect.height
|
||
|
|| pfov != scr_ffov->value) {
|
||
|
pwidth = r_refdef.vrect.width;
|
||
|
pheight = r_refdef.vrect.height;
|
||
|
pfov = scr_ffov->value;
|
||
|
|
||
|
build_display_list (pwidth, pheight, pfov);
|
||
|
}
|
||
|
|
||
|
gl_framebuffer_t *buffer = fb->buffer;
|
||
|
|
||
|
qfglMatrixMode (GL_PROJECTION);
|
||
|
qfglLoadIdentity ();
|
||
|
qfglOrtho (0, r_refdef.vrect.width, r_refdef.vrect.height, 0, -9999, 9999);
|
||
|
qfglMatrixMode (GL_MODELVIEW);
|
||
|
qfglLoadIdentity ();
|
||
|
qfglColor3ubv (color_white);
|
||
|
|
||
|
qfglEnable (GL_TEXTURE_CUBE_MAP_ARB);
|
||
|
qfglBindTexture (GL_TEXTURE_CUBE_MAP_ARB, buffer->color);
|
||
|
qfglCallList (fisheye_grid);
|
||
|
qfglDisable (GL_TEXTURE_CUBE_MAP_ARB);
|
||
|
CHKGLERR("fisheye");
|
||
|
}
|