1 //-----------------------------------------------------------------------------
2 // Render + OpenGL Driver support
3 //-----------------------------------------------------------------------------
4 
5 #ifndef __RENDER_H__
6 #define __RENDER_H__
7 
8 #include "cake.h"
9 #include "camera.h"
10 
11 /**
12  * Interface with OpenGL states.
13  * Records the current state. This class can be seen as an OpenGL states
14  * interface.
15  */
16 class State
17 {
18   public:
19 
20     // there is only a current state, thus all the members are static
21     static void SetInitialState(int multitexture);
22 
23     /**
24      * Set to default state
25      * @todo Terminate this !
26      */
27     static void SetDefaultState(void);
28 
29     /**
30      * Binds the texture of the given layer
31      * @param l layer to bind texture to
32      * @param unit texturing unit on the 3d card (be careful with this
33      *        because currently the only card that supports 4 texturing
34      *        units is the geforce
35      * @test It is incredible how much time does the engine spend here!
36      */
37     static void BindTexture(Layer *l, int unit);
38 
39     /**
40      * Set the appropriate state to render the layer.
41      * @test check all redundant state changes ???
42      */
43     static void setState(Layer *l);
44 
45     /**
46      * Active shader states.
47      */
48     static void SetupShader(void);
49 
50     /**
51      * Evaluates a deform function.
52      * @param p a parameters table
53      * @return the function result
54      */
55     static float Eval(float *p);
56 
57     // input related
58     static Shader *   curr_shader;
59     static Shader *   curr_effect;
60     static int      curr_depthFunc;
61     static int      curr_depthWrite;
62     static int      curr_blendsrc;
63     static int      curr_blenddst;
64     static int      curr_culling;
65     static int      curr_alphaFunc;
66     static int      curr_polygonmode;
67 
68     static int      curr_texture[MAX_TEXTURE_UNITS];
69 
70     static int      skipping;
71 
72     static int      curr_lightmap;
73 
74     static int      last_tcgen[MAX_TEXTURE_UNITS];
75 
76     static int      pass;           // output related
77 
78     // Following functions change manually an opengl state
79     static void setDepthFunc(int val);
80     static void setDepthWrite(int val);
81     static void setBlend(int src, int dst);
82     static void setCulling(int val);
83     static void setAlphaFunc(int func, float funcref = 0);
84     static void setPolygonMode(int val);
85 };
86 
87 /**
88  * Vertex buffer used for arrays generation.
89  */
90 typedef struct
91 {
92   int     st_content;     /**< vertex texture coordinates */
93   float*  st;             /**< 2 texture coordinates */
94   int     c_content;      /**< vertex color */
95   byte*   c;              /**< 4 colors */
96 } Buffer;
97 
98 /**
99  * Structure used to communicate triangles to graphic card.
100  */
101 typedef struct
102 {
103   int     numelems;
104   unsigned int *   elems;        /**< elements buffer */
105 
106   int     numverts;
107   float*  xyz;          /**< 4 coordinates for a vertice */
108   float*  tex_st;       /**< 2 texture coordinates */
109   float*  lm_st;        /**< 2 lightmap coordinates */
110   float*  normal;       /**< 4 coordinates for the normal */
111   byte*   c;            /**< 4 colors */
112 #if MODIF_FOG
113   cplane_t**  fog;      /**< fog plane */
114 #else
115   float*      fog;      /**< 5 fog parameters (normal, dist and type) */
116 #endif
117 } Input;
118 
119 typedef void  (APIENTRY *swapcommand_t) (void);
120 
121 /**
122  * Render class.
123  * The render is a class that interacts with OpenGL driver. All faces are
124  * sent to the OpenGL API through the render.
125  * For now, the render supposes that we use GLUT in the main program for
126  * window management.
127  * This has to consequence that some 3D graphic cards shouldn't work
128  * correctly with the engine, especially the cards which need dynamic drivers
129  * (3Dfx voodoo based cards for example). For these cards, we should rewrite
130  * the driver and use GLS.H instead of GLUT.H and GL.H.
131  * <pre>
132  *   Notes on the Quake 3 axis system :
133  *   ______________________________________
134  *  |                                      |
135  *  |                                      |
136  *  |    Z /|\     _  Y                    |  This represents the orientation
137  *  |       |      /|  _____               |  of axis in the engine for a
138  *  |       |     /   /     /|             |  camera angle of (90 0 0).
139  *  |       |    /   /____ / |  O    O     |
140  *  |       |   /   |     |  | /|\  \|/    |  (by default, the camera has a
141  *  |       |  /    |     | /   |    |     |   pitch = 90, otherwise, the
142  *  |       | /     |_____|/   / \  / \    |   camera looks to the ground)
143  *  |       |/                     \       |
144  *  |     --+----------------------- X     |
145  *  |      /| O                    /       |
146  *  |                                      |
147  *  |______________________________________|
148  *
149  *  The Quake3 axis system is similar to OpenGL system (right hand system).
150  *  On the above figure, the pitch of camera is 90. This explains why Z axis
151  *  is going up.
152  *  In fact, the engine considers Oxy plane as ground and Oz vector as up
153  *  vector.
154  *  In the engine, XYZ axis can be viewed using the grid display. The x, y
155  *  and z axis are respectively displayed in red, green and blue colors.
156  *  They have a length of 1000 and are centered at position (0,0,0).
157  * </pre>
158  * The global principle of render work is to push triangles that have same
159  * shader on a stack, and then to send all the stack to the graphic card
160  * using <code>glDrawElements</code>. A state system is used to store
161  * texture and shader parameters of the triangles.
162  * @see State
163  * @todo Resolve the display problem: the first top line of the screen
164  *       doesn't displays correctly. If r_clear == 1, the first line of
165  *       the screen manifestly appears incorrect.
166  * @bug Check that camera is defined for each part that require the camera pointer.
167  */
168 class Render
169 {
170   private:
171     int       state;
172     Input     input;
173     Buffer    buffer[MAX_TEXTURE_UNITS];
174 
175     /**
176      * Increases the buffer size.
177      * @param newsize the new buffer size.
178      */
179     void IncreaseBuffer(unsigned int newsize);
180 
181     /**
182      * Increases the elems size.
183      * @param newsize the new elems size.
184      */
185     void IncreaseElems(unsigned int newsize);
186 
187   protected:
188     bool ext_swapControl;
189     swapcommand_t swapbuffersfunc;
190 
191   public:
192     Camera* current_camera;         /**< current camera used for rendering */
193 
194     int ready;                      /**< inform if render is ready */
195     int windowIndex;                /**< window index */
196 
197     texinfo fogtexture;            /**< fog texture */
198 
199     int gridpass;                   /**< grid related */
200 
201     unsigned long num_flush;        /**< number of flush calls */
202     unsigned long num_tris;         /**< number of triangles rendered */
203     unsigned long num_verts;        /**< number of vertices */
204     unsigned long num_apicalls;     /**< number of gl api calls */
205 
206     Render(void);
207     ~Render(void);
208 
209     /**
210      * Indicates we are beginning a new frame.
211      */
212     int BeginFrame(void);
213 
214     /**
215      * Indicates the frame is finished and the render can flush all unflushed triangles.
216      */
217     int EndFrame(void);
218 
219     /**
220      * Reset window size and automatically recalculate the console background size.
221      * @param w the new width size
222      * @param h the new height size
223      * @param c the new color bit
224      * @param f the new frequency
225      */
226     void SetWindowSettings(GLsizei w = -1, GLsizei h = -1, GLint c = -1, GLint f = -1);
227 
228 
229     /**
230      * Initialize the render.
231      * @param func a pointer to function used for buffers swap
232      * @return 1 if initialization succeeded, 0 if not
233      */
234     int Init(swapcommand_t func);
235 
236     /**
237      * Shuts down the render.
238      */
239     void Shut(void);
240 
241 
242     /**
243      * Gets the window width.
244      * @return the window width
245      */
246     int GetWidth(void);
247 
248     /**
249      * Gets the window height.
250      * @return the window height
251      */
252     int GetHeight(void);
253 
254     /**
255      * Gets the window left position.
256      * @return the window left position
257      */
258     int GetLeft(void);
259 
260     /**
261      * Gets the window top position.
262      * @return the window top position
263      */
264     int GetTop(void);
265 
266     /**
267      * Gets a report of the current OpenGL states.
268      */
269     void DumpGLState(void);
270 
271     /**
272      * Check for GL error and update gl function counter
273      * The function depends on enableGLChecks constant. If enabled,
274      * the function reports the error in console for release mode and
275      * generates a break in debug mode.
276      * @param ncalls The number of api calls
277      */
278     void CheckGLError(int ncalls = 1);
279 
280     /**
281      * Determines if an extension is supported.
282      * The function must be called after a valid context has been created.
283      */
284     bool CheckExtension(char *extName);
285 
286     // TODO: Comment those functions.
287     int RegisterTexInfo(texinfo *tex, int flags);
288     void UnregisterTexInfo(texinfo *tex);
289     void SetRenderState(Shader *s, int lightmap = ~0, Shader *e = NULL);
290     void InitializeViewPort(void);
291     void PushTriangles(Surface *surf, int *visible = NULL);
292     void Flush(void);
293 
294     /**
295      * Force the flushing.
296      */
297     void ForceFlush(void);
298 
299     // Flushing functions
300     void FlushMtxCVA(void);
301     void FlushMtx(void);
302     void FlushGenericCVA(void);
303     void FlushGeneric(void);
304     void FlushSingleCVA(void);
305     void FlushSingle(void);
306     void FlushVertexLit(void);
307     void FlushGridCVA(void);
308     void FlushGrid(void);
309 
310     void SwapBuffers(void);
311 
312     /**
313      * This function looks for and sends tristrips.
314      * Vertexes are in tristrip order where possible. If we can't lock
315      * the vertex arrays (glLockArraysEXT), then it's better to send
316      * tristrips instead of triangles (less transformations).
317      * <br>
318      * Tristrip order elems look like this:
319      *  0 1 2 2 1 3 2 3 4 4 3 5 4 5 7 7 5 6  <-- elems
320      *    b a a b b a b a a b b a b a a b b  <-- ab pattern
321      *    \ 1 / \ 2 / \ 3 / \ 4 / \ 5 /      <-- baa/bba groups
322      */
323     void Stripmine(int numelems, unsigned int *elems);
324 
325     /**
326      * Modifiy the vertices coord in function of vertex deformations.
327      * @param s the basis surfaces
328      * @param level the tesselation level for surface
329      * @see Shader
330      * @todo Terminate the autosprite + autosprite2 deformations.
331      * @todo Terminate the normal deformation.
332      */
333     void SetVertexCoords(Surface *s, int level = 0);
334 
335     /**
336      * @todo Save last tcgen and last tcmod to know if we dont have
337      *       to recopy the coordinates.
338      */
339     void SetTextureCoordinates(int tmu, Layer *l);
340     void SetVertexColors(int tmu, Layer *l);
341 
342     /**
343      * Generates the perspective matrix.
344      * @param fov the camera fov
345      * @param aspect the aspect ratio
346      * @todo Put that in glutils...
347      * @test Carmack uses vertical fov to deal with 16:9 monitors!
348      */
349     void Perspective(float fov, float aspect);
350 
351     /**
352     * Creates a fog texture.
353     * Current fog version doesn't use any extension. The fog is simulated
354     * with the fog texture. The fog texture is rendered in an additional pass
355     * and texture coordinates are chosen in function of distance between vertex
356     * and camera. See SetTextureCoordinates() function for details on texture
357     * coordinates generation.
358     * @param t The destination texture.
359     */
360     void CreateFogTexture(texinfo *t);
361 };
362 
363 #endif  /* __RENDER_H__ */
364