[go: up one dir, main page]

Menu

[r112]: / lpi_gl.cpp  Maximize  Restore  History

Download this file

258 lines (206 with data), 7.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
Copyright (c) 2005-2008 Lode Vandevenne
All rights reserved.
This file is part of Lode's Programming Interface.
Lode's Programming Interface 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 3 of the License, or
(at your option) any later version.
Lode's Programming Interface 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 Lode's Programming Interface. If not, see <http://www.gnu.org/licenses/>.
*/
#include "lpi_gl.h"
#include <vector>
namespace lpi
{
int screenWidth()
{
GLint array[4];
glGetIntegerv(GL_VIEWPORT, array); //array[2] contains the width in pixels of the viewport
return array[2];
}
int screenHeight()
{
GLint array[4];
glGetIntegerv(GL_VIEWPORT, array); //array[3] contains the height in pixels of the viewport
return array[3];
}
namespace
{
//these values are in OpenGL viewport coordinates, that is NOT the same as pixel coordinates, use setScissor to properly set these
std::vector<int> clipLeft;
std::vector<int> clipTop;
std::vector<int> clipRight;
std::vector<int> clipBottom;
int screenMode = -1;
double lastNear, lastFar;
}
void set2DScreen(int w, int h)
{
if(screenMode == 0) return;
screenMode = 0;
//the official code for "Setting Your Raster Position to a Pixel Location" (i.e. set up an oldskool 2D screen)
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, w, h, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
enableTwoSided(); //important, without this, 2D stuff might not be drawn if only one side is enabled
disableZBuffer();
disableSmoothing();
}
/*
The modelview matrix isn't touched by this function, if you want to reset that one too, do
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
before or after calling this function.
*/
void set3DScreen(double near, double far, int w, int h)
{
if(screenMode == 1 && near == lastNear && far == lastFar) return;
screenMode = 1;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
/*
multiplying with matrix glup does the same as "gluPerspective(90, double(w)/double(h), near, far);"
to support other fovy values than 90, replace the value 1.0 in elements 0 and 5 to "1.0 / tan(fovy / 2)", where fovy is in radians
*/
double aspect = double(w) / double(h);
double glup[16] = {1.0 / aspect, 0, 0, 0,
0, 1.0, 0, 0,
0, 0, (far + near) / (near - far), -1,
0, 0, (2 * far * near) / (near - far), 0};
glMultMatrixd(glup);
//flip the z axis because my camera code assumes the z axis flipped compared to opengl
double flipz[16] = {1, 0, 0, 0,
0, 1, 0, 0,
0, 0, -1, 0,
0, 0, 0, 1};
glMultMatrixd(flipz);
lastNear = near;
lastFar = far;
glMatrixMode(GL_MODELVIEW); //make sure nothing else changed the projection matrix, which may be used only for the projection, not the camera.
}
//Initialize OpenGL: set up the camera and settings to emulate 2D graphics
void initGL()
{
set2DScreen();
//glShadeModel(GL_FLAT); //shading, don't do the GL_FLAT thing or gradient rectangles don't work anymore
//glCullFace(GL_BACK); //culling
//glFrontFace(GL_CCW);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glEnable(GL_SCISSOR_TEST); //scissoring is used to, for example, not draw parts of textures that are scrolled away, and is always enabled (but by default the scissor area is as big as the screen)
GLint array[4];
glGetIntegerv(GL_VIEWPORT, array); //get viewport size from OpenGL
//initialize the scissor area (the values at position std::vector.size() - 1 in the std::vectors must ALWAYS be set to the values below and may never be changed!)
clipLeft.clear();
clipLeft.push_back(0);
clipTop.clear();
clipTop.push_back(0);
clipRight.clear();
clipRight.push_back(array[2]);
clipBottom.clear();
clipBottom.push_back(array[3]);
}
void set2DScreen()
{
GLint array[4];
glGetIntegerv(GL_VIEWPORT, array); //get viewport size from OpenGL
set2DScreen(array[2], array[3]);
}
void set3DScreen(double near, double far)
{
GLint array[4];
glGetIntegerv(GL_VIEWPORT, array); //get viewport size from OpenGL
set3DScreen(near, far, array[2], array[3]);
}
void enableOneSided()
{
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
}
void enableTwoSided()
{
glDisable(GL_CULL_FACE);
}
void enableZBuffer()
{
glEnable(GL_DEPTH_TEST);
}
void disableZBuffer()
{
glDisable(GL_DEPTH_TEST);
}
bool smoothing_gl = false;
void enableSmoothing()
{
smoothing_gl = true;
}
void disableSmoothing()
{
smoothing_gl = false;
}
bool enabledSmoothing()
{
return smoothing_gl;
}
bool onScreen(int x, int y)
{
GLint array[4];
glGetIntegerv(GL_VIEWPORT, array); //get viewport size from OpenGL
return (x >= 0 && y >= 0 && x < array[2] && y < array[3]);
}
//set new scissor area (limited drawing area on the screen)
void setScissor(int left, int top, int right, int bottom)
{
if(right < left) right = left;
if(bottom < top) bottom = top;
//the values stored in the std::vectors are transformed to opengl viewport coordinates, AND right and bottom actually contain the size instead of coordinates (because OpenGL works that way)
clipLeft.push_back(left);
clipTop.push_back(top);
clipRight.push_back(right);
clipBottom.push_back(bottom);
setOpenGLScissor();
}
void setSmallestScissor(int left, int top, int right, int bottom)
{
int smallestLeft = left;
int smallestTop = top;
int smallestRight = right;
int smallestBottom = bottom;
if(clipLeft.back() > smallestLeft) smallestLeft = clipLeft.back(); //de meest rechtse van de linkerzijden
if(clipTop.back() > smallestTop) smallestTop = clipTop.back(); //de laagste van de top zijden
if(clipRight.back() < smallestRight) smallestRight = clipRight.back(); //de meest linkse van de rechtse zijden
if(clipBottom.back() < smallestBottom) smallestBottom = clipBottom.back(); //de hoogste van de bodem zijden
//if(smallestLeft < smallestRight) smallestLeft = 0, smallestRight = 1;
//if(smallestTop < smallestBottom) smallestTop = 0, smallestBottom = 1;
setScissor(smallestLeft, smallestTop, smallestRight, smallestBottom);
}
//uses the extern scissor area variables to set the scissoring area of OpenGL
void setOpenGLScissor()
{
GLint array[4];
glGetIntegerv(GL_VIEWPORT, array); //array[3] contains the height in pixels of the viewport
glScissor(clipLeft.back(), array[3] - clipBottom.back(), clipRight.back() - clipLeft.back(), clipBottom.back() - clipTop.back());
}
//reset the scissor area back to the previous coordinates before your last setScissor call (works like a stack)
void resetScissor()
{
if(clipLeft.size() > 1)
{
clipLeft.pop_back();
clipTop.pop_back();
clipRight.pop_back();
clipBottom.pop_back();
}
setOpenGLScissor();
}
} //namespace lpi