1 /*
2  *  Copyright (c) 2012-2016, Bruno Levy
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *
8  *  * Redistributions of source code must retain the above copyright notice,
9  *  this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright notice,
11  *  this list of conditions and the following disclaimer in the documentation
12  *  and/or other materials provided with the distribution.
13  *  * Neither the name of the ALICE Project-Team nor the names of its
14  *  contributors may be used to endorse or promote products derived from this
15  *  software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  *  POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  If you modify this software, you should include a notice giving the
30  *  name of the person performing the modification, the date of modification,
31  *  and the reason for such modification.
32  *
33  *  Contact: Bruno Levy
34  *
35  *     Bruno.Levy@inria.fr
36  *     http://www.loria.fr/~levy
37  *
38  *     ALICE Project
39  *     LORIA, INRIA Lorraine,
40  *     Campus Scientifique, BP 239
41  *     54506 VANDOEUVRE LES NANCY CEDEX
42  *     FRANCE
43  *
44  */
45 
46 #ifndef GEOGRAM_GFX_GLUP_GLUP
47 #define GEOGRAM_GFX_GLUP_GLUP
48 
49 #include <geogram_gfx/api/defs.h>
50 #define GLUP_API GEOGRAM_GFX_API
51 
52 #ifdef __cplusplus
53 extern "C" {
54 #endif
55 
56     /**
57      * \file geogram_gfx/GLUP/GLUP.h
58      * \brief GLUP: GL Useful Primitives
59      */
60 
61     /**
62      * \name GLUP base types
63      * @{
64      */
65 
66     typedef float GLUPfloat;
67     typedef double GLUPdouble;
68     typedef int GLUPint;
69     typedef unsigned int GLUPuint;
70     typedef int GLUPsizei;
71     typedef unsigned int GLUPenum;
72     typedef unsigned long int GLUPuint64;
73     typedef void GLUPvoid;
74     typedef int GLUPbitfield;
75 
76     enum {
77         GLUP_FALSE=0, GLUP_TRUE = 1
78     };
79 
80     typedef unsigned char GLUPboolean;
81 
82     /**
83      * @}
84      */
85 
86     /************************************************/
87 
88     /**
89      * \name GLUP context manipulation
90      * @{
91      */
92 
93     /**
94      * \brief Gets the GLSL declaration of GLUP uniform state.
95      * \return a pointer to GLSL source code that declares
96      *  GLUP uniform state.
97      * \details Can be used by client-code shaders that need to
98      *  have access to the GLUP uniform state.
99      */
100     GLUP_API const char* glupUniformStateDeclaration(void);
101 
102     /**
103      * \brief Compiles a GLSL shader.
104      * \param[in] target one of GL_VERTEX_SHADER, GL_FRAGMENT_SHADER,
105      *  GL_COMPUTE_SHADER, GL_TESS_CONTROL_SHADER, GL_TESS_EVALUATION_SHADER,
106      *  GL_GEOMETRY_SHADER.
107      * \return an opaque handle to the compiled shader, or 0 if an error
108      *  occured.
109      */
110     GLUP_API GLUPuint glupCompileShader(GLUPenum target, const char* source);
111 
112     /**
113      * \brief Compiles a GLSL program.
114      * \param[in] source the program source. Shader stages are indicated
115      *  by special comments:
116      *  //stage GL_VERTEX_SHADER
117      *  //stage GL_FRAGMENT_SHADER
118      *  //stage GL_COMPUTE_SHADER
119      *  //stage GL_TESS_CONTROL_SHADER
120      *  //stage GL_TESS_EVALUATION_SHADER
121      *  //stage GL_GEOMETRY_SHADER
122      * \return an opaque handle to the compiled program, or 0 if an error
123      *  occured.
124      */
125     GLUP_API GLUPuint glupCompileProgram(const char* source);
126 
127     /**
128      * \brief Opaque identifier of a GLUP context.
129      */
130     typedef void* GLUPcontext;
131 
132     /**
133      * \brief Creates a new GLUP context.
134      * \details OpenGL needs to be already initialized when this function
135      *  is called (there needs to be a valid active OpenGL context).
136      * \return the newly created GLUPcontext
137      */
138     GLUPcontext GLUP_API glupCreateContext(void);
139 
140     /**
141      * \brief Deletes a GLUP context.
142      * \param[in] context the GLUPcontext to be deleted
143      */
144     void GLUP_API glupDeleteContext(GLUPcontext context);
145 
146     /**
147      * \brief Gets the current GLUP context.
148      * \return the current GLUP context
149      */
150     GLUPcontext GLUP_API glupCurrentContext(void);
151 
152     /**
153      * \brief The name of the profile implemented by the
154      *  current context.
155      * \return a const pointer to the string with the name
156      *  of the current profile.
157      */
158     GLUP_API const char* glupCurrentProfileName(void);
159 
160     /**
161      * \brief Makes a GLUP context the current one.
162      * \param[in] context the GLUP context to be made current
163      */
164     void GLUP_API glupMakeCurrent(GLUPcontext context);
165 
166     /**
167      * \brief Binds the GLUP uniform state to a program.
168      * \param[in] program the handle to the GLSL program.
169      * \details It is necessary to call this function for
170      *  client programs that need to access the GLUP uniform state.
171      */
172     void GLUP_API glupBindUniformState(GLUPuint program);
173 
174     /**
175      * @}
176      */
177 
178     /************************************************/
179 
180     /**
181      * \name GLUP enable / disable
182      * @{
183      */
184 
185     typedef enum {
186         GLUP_LIGHTING           =0,
187         GLUP_VERTEX_COLORS      =1,
188         GLUP_TEXTURING          =2,
189         GLUP_DRAW_MESH          =3,
190         GLUP_CLIPPING           =4,
191         GLUP_INDIRECT_TEXTURING =5,
192 	GLUP_VERTEX_NORMALS     =6,
193         GLUP_PICKING            =7,
194 	GLUP_ALPHA_DISCARD      =8,
195 	GLUP_NORMAL_MAPPING     =9
196     } GLUPtoggle;
197 
198     void GLUP_API glupEnable(GLUPtoggle toggle);
199     void GLUP_API glupDisable(GLUPtoggle toggle);
200     GLUPboolean GLUP_API glupIsEnabled(GLUPtoggle toggle);
201 
202     /**
203      * @}
204      */
205 
206     /************************************************/
207 
208     /**
209      * \name GLUP texturing
210      * @{
211      */
212 
213 
214     /**
215      * \brief The texture units used by GLUP for 1D,2D and 3D
216      *  texturing.
217      * \details Before binding the texture, call
218      *   glActiveTexture(GL_TEXTURE0 + unit) before binding the texture.
219      *   For instance, for 2D texturing, call
220      *   glActiveTexture(GL_TEXTURE0 + GLUP_TEXTURE_2D_UNIT).
221      */
222     enum {
223         GLUP_TEXTURE_1D_UNIT=0,
224         GLUP_TEXTURE_2D_UNIT=1,
225         GLUP_TEXTURE_3D_UNIT=2
226     };
227 
228 
229     /**
230      * \brief The targets to be used as the first
231      *  argument of glBindTexture() for GLUP 1D, 2D
232      *  and 3D textures.
233      * \details we do not use 1D textures, because
234      *  they are not supported by all OpenGL versions.
235      *  Both targets for 1D and 2D textures are GL_TEXTURE_2D.
236      */
237     enum {
238         GLUP_TEXTURE_1D_TARGET=0x0DE1,
239         GLUP_TEXTURE_2D_TARGET=0x0DE1,
240         GLUP_TEXTURE_3D_TARGET=0x806F
241     };
242 
243     typedef enum {
244         GLUP_TEXTURE_1D=1,
245         GLUP_TEXTURE_2D=2,
246         GLUP_TEXTURE_3D=3
247     } GLUPtextureType;
248 
249     void GLUP_API glupTextureType(GLUPtextureType type);
250     GLUPtextureType GLUP_API glupGetTextureType(void);
251 
252     typedef enum {
253         GLUP_TEXTURE_REPLACE=0,
254         GLUP_TEXTURE_MODULATE=1,
255         GLUP_TEXTURE_ADD=2
256     } GLUPtextureMode;
257 
258     void GLUP_API glupTextureMode(GLUPtextureMode mode);
259     GLUPtextureMode GLUP_API glupGetTextureMode(void);
260 
261     /**
262      * @}
263      */
264 
265     /************************************************/
266 
267 
268     /**
269      * \name GLUP drawing state
270      * @{
271      */
272 
273 
274     typedef enum {
275         GLUP_FRONT_COLOR=0,
276         GLUP_BACK_COLOR=1,
277         GLUP_MESH_COLOR=2,
278         GLUP_FRONT_AND_BACK_COLOR=3
279     } GLUPcolor;
280 
281     void GLUP_API glupSetColor4fv(GLUPcolor color, const GLUPfloat* rgba);
282     void GLUP_API glupGetColor4fv(GLUPcolor color, float* rgba);
283 
284     void GLUP_API glupSetColor3fv(GLUPcolor color, const GLUPfloat* rgba);
285     void GLUP_API glupSetColor4f(
286         GLUPcolor color, GLUPfloat r, GLUPfloat g, GLUPfloat b, GLUPfloat a
287     );
288     void GLUP_API glupSetColor3f(
289         GLUPcolor color, GLUPfloat r, GLUPfloat g, GLUPfloat b
290     );
291     void GLUP_API glupSetColor4dv(GLUPcolor color, const GLUPdouble* rgba);
292     void GLUP_API glupSetColor3dv(GLUPcolor color, const GLUPdouble* rgba);
293     void GLUP_API glupSetColor4d(
294         GLUPcolor color, GLUPdouble r, GLUPdouble g, GLUPdouble b, GLUPdouble a
295     );
296     void GLUP_API glupSetColor3d(
297         GLUPcolor color, GLUPdouble r, GLUPdouble g, GLUPdouble b
298     );
299 
300     void GLUP_API glupLightVector3f(GLUPfloat x, GLUPfloat y, GLUPfloat z);
301     void GLUP_API glupLightVector3fv(GLUPfloat* xyz);
302     void GLUP_API glupGetLightVector3fv(GLUPfloat* xyz);
303 
304     void GLUP_API glupSetPointSize(GLUPfloat size);
305     GLUPfloat GLUP_API glupGetPointSize(void);
306 
307     void GLUP_API glupSetMeshWidth(GLUPint width);
308     GLUPint GLUP_API glupGetMeshWidth(void);
309 
310     void GLUP_API glupSetCellsShrink(GLUPfloat x);
311     GLUPfloat GLUP_API glupGetCellsShrink(void);
312 
313     void GLUP_API glupSetAlphaThreshold(GLUPfloat x);
314     GLUPfloat GLUP_API glupGetAlphaThreshold(void);
315 
316     void GLUP_API glupSetSpecular(GLUPfloat x);
317     GLUPfloat GLUP_API glupGetSpecular(void);
318 
319     /**
320      * @}
321      */
322 
323     /************************************************/
324 
325     /**
326      * \name GLUP picking
327      * @{
328      */
329 
330     typedef enum {
331         GLUP_PICK_PRIMITIVE=1,
332         GLUP_PICK_CONSTANT=2
333     } GLUPpickingMode;
334 
335     void GLUP_API glupPickingMode(GLUPpickingMode mode);
336     GLUPpickingMode GLUP_API glupGetPickingMode(void);
337 
338     void GLUP_API glupPickingId(GLUPuint64 id);
339     GLUPuint64 GLUP_API glupGetPickingId(void);
340 
341     void GLUP_API glupBasePickingId(GLUPuint64 id);
342     GLUPuint64 GLUP_API glupGetBasePickingId(void);
343 
344     /**
345      * @}
346      */
347 
348     /************************************************/
349 
350     /**
351      * \name GLUP clipping
352      * @{
353      */
354 
355     typedef enum {
356         GLUP_CLIP_STANDARD=0,
357         GLUP_CLIP_WHOLE_CELLS=1,
358         GLUP_CLIP_STRADDLING_CELLS=2,
359         GLUP_CLIP_SLICE_CELLS=3
360     } GLUPclipMode;
361 
362     /**
363      * \brief Sets the current clipping mode.
364      * \param[in] mode one of GLUP_CLIP_STANDARD,
365      *  GLUP_CLIP_WHOLE_CELLS, GLUP_CLIP_STRADDLING_CELLS,
366      *  GLUP_CLIP_SLICE_CELLS (not implemented yet).
367      */
368     void GLUP_API glupClipMode(GLUPclipMode mode);
369 
370     /**
371      * \brief Gets the clipping mode.
372      * \return the current clipping mode
373      */
374     GLUPclipMode GLUP_API glupGetClipMode(void);
375 
376     /**
377      * \brief Defines the plane used by GLUP clipping.
378      * \details The specified plane equation is pre-multiplied
379      *  by the inverse of the current modelview matrix before
380      *  being stored in the state (like in the old fixed-functionality
381      *  pipeline of OpenGL).
382      * \param[in] eqn a pointer to 4 doubles with the equantion of the
383      *  clipping plane.
384      */
385     void GLUP_API glupClipPlane(const GLUPdouble* eqn);
386 
387     /**
388      * \brief Gets the current clipping plane.
389      * \param[out] eqn a pointer to 4 doubles where to store the
390      *  current clipping plane equation.
391      */
392     void GLUP_API glupGetClipPlane(GLUPdouble* eqn);
393 
394     /**
395      * @}
396      */
397 
398     /************************************************/
399 
400     /**
401      * \name GLUP matrices
402      * @{
403      */
404 
405     typedef enum {
406         GLUP_MODELVIEW_MATRIX = 0,
407         GLUP_PROJECTION_MATRIX = 1,
408         GLUP_TEXTURE_MATRIX = 2
409     } GLUPmatrix;
410 
411     void GLUP_API glupMatrixMode(GLUPmatrix matrix);
412     GLUPmatrix GLUP_API glupGetMatrixMode(void);
413     void GLUP_API glupPushMatrix(void);
414     void GLUP_API glupPopMatrix(void);
415 
416     /**
417      * \brief Queries a GLUP matrix.
418      * \param[in] matrix symbolic name of the matrix, one of
419      *   GLUP_PROJECTION_MATRIX, GLUP_MODELVIEW_MATRIX, GLUP_TEXTURE_MATRIX
420      * \param[out] ptr a pointer to an array of 16 doubles, where to store
421      *   the current matrix on top of the specified stack.
422      */
423     void GLUP_API glupGetMatrixdv(GLUPmatrix matrix, GLUPdouble* ptr);
424 
425     /**
426      * \brief Queries a GLUP matrix.
427      * \param[in] matrix symbolic name of the matrix, one of
428      *   GLUP_PROJECTION_MATRIX, GLUP_MODELVIEW_MATRIX, GLUP_TEXTURE_MATRIX
429      * \param[out] ptr a pointer to an array of 16 doubles, where to store
430      *   the current matrix on top of the specified stack.
431      */
432     void GLUP_API glupGetMatrixfv(GLUPmatrix matrix, GLUPfloat* ptr);
433 
434     void GLUP_API glupLoadIdentity(void);
435     void GLUP_API glupLoadMatrixf(const GLUPfloat* M);
436     void GLUP_API glupLoadMatrixd(const GLUPdouble* M);
437     void GLUP_API glupMultMatrixf(const GLUPfloat* M);
438     void GLUP_API glupMultMatrixd(const GLUPdouble* M);
439     void GLUP_API glupTranslatef(GLUPfloat x, GLUPfloat y, GLUPfloat z);
440     void GLUP_API glupTranslated(GLUPdouble x, GLUPdouble y, GLUPdouble z);
441     void GLUP_API glupScalef(GLUPfloat sx, GLUPfloat sy, GLUPfloat sz);
442     void GLUP_API glupScaled(GLUPdouble sx, GLUPdouble sy, GLUPdouble sz);
443     void GLUP_API glupRotatef(
444         GLUPfloat angle, GLUPfloat x, GLUPfloat y, GLUPfloat z
445     );
446     void GLUP_API glupRotated(
447         GLUPdouble angle, GLUPdouble x, GLUPdouble y, GLUPdouble z
448         );
449     void GLUP_API glupOrtho(
450         GLUPdouble left, GLUPdouble right,
451         GLUPdouble bottom, GLUPdouble top,
452         GLUPdouble nearVal, GLUPdouble farVal
453     );
454     void GLUP_API glupOrtho2D(
455         GLUPdouble left, GLUPdouble right, GLUPdouble bottom, GLUPdouble top
456     );
457     void GLUP_API glupFrustum(
458         GLUPdouble left, GLUPdouble right,
459         GLUPdouble bottom, GLUPdouble top,
460         GLUPdouble nearVal, GLUPdouble farVal
461     );
462     void GLUP_API glupPerspective(
463         GLUPdouble fovy, GLUPdouble aspect,
464         GLUPdouble zNear, GLUPdouble zFar
465     );
466 
467     GLUPint GLUP_API glupProject(
468         GLUPdouble objx, GLUPdouble objy, GLUPdouble objz,
469         const GLUPdouble modelMatrix[16],
470         const GLUPdouble projMatrix[16],
471         const GLUPint viewport[4],
472         GLUPdouble* winx,  GLUPdouble* winy,  GLUPdouble* winz
473     );
474 
475     GLUPboolean GLUP_API glupUnProject(
476         GLUPdouble winx, GLUPdouble winy, GLUPdouble winz,
477         const GLUPdouble modelMatrix[16],
478         const GLUPdouble projMatrix[16],
479         const GLUPint viewport[4],
480         GLUPdouble *objx, GLUPdouble *objy, GLUPdouble *objz
481     );
482 
483     GLUPboolean GLUP_API glupInvertMatrixfv(
484         GLUPfloat Minvert[16],
485         const GLUPfloat M[16]
486     );
487 
488     GLUPboolean GLUP_API glupInvertMatrixdv(
489         GLUPdouble Minvert[16],
490         const GLUPdouble M[16]
491     );
492 
493     /**
494      * @}
495      */
496 
497     /************************************************/
498 
499     /**
500      * \name GLUP drawing functions
501      * @{
502      */
503 
504     /**
505      * \brief Symbolic values corresponding to GLUP
506      *  primitive types.
507      * \see glupBegin(), glupEnd(), glupDrawArrays(), glupDrawElements()
508      */
509     typedef enum {
510         GLUP_POINTS     =0,
511         GLUP_LINES      =1,
512         GLUP_TRIANGLES  =2,
513         GLUP_QUADS      =3,
514         GLUP_TETRAHEDRA =4,
515         GLUP_HEXAHEDRA  =5,
516         GLUP_PRISMS     =6,
517         GLUP_PYRAMIDS   =7,
518         GLUP_CONNECTORS =8,
519 	GLUP_SPHERES    =9,
520         GLUP_NB_PRIMITIVES = 10
521     } GLUPprimitive;
522 
523     /**
524      * \brief Tests whether a given GLUP primitive supports array mode.
525      * \details If array mode is supported, then one can use glupDrawArray()
526      *  and glupDrawElements() with the specified primitive.
527      * \param[in] prim the primitive to be tested.
528      * \retval GLUP_TRUE if array mode is supported with \p prim
529      * \retval GLUP_FALSE otherwise
530      */
531     GLUPboolean GLUP_API glupPrimitiveSupportsArrayMode(GLUPprimitive prim);
532 
533     void GLUP_API glupDrawArrays(
534         GLUPprimitive primitive, GLUPint first, GLUPsizei count
535     );
536 
537     void GLUP_API glupDrawElements(
538         GLUPprimitive primitive, GLUPsizei count,
539         GLUPenum type, const GLUPvoid* indices
540     );
541 
542     void GLUP_API glupBegin(GLUPprimitive primitive);
543     void GLUP_API glupEnd(void);
544 
545     void GLUP_API glupVertex2fv(const GLUPfloat* xy);
546     void GLUP_API glupVertex3fv(const GLUPfloat* xyz);
547     void GLUP_API glupVertex4fv(const GLUPfloat* xyzw);
548 
549     void GLUP_API glupVertex2dv(const GLUPdouble* xy);
550     void GLUP_API glupVertex3dv(const GLUPdouble* xyz);
551     void GLUP_API glupVertex4dv(const GLUPdouble* xyzw);
552 
553     void GLUP_API glupVertex2f(GLUPfloat x, GLUPfloat y);
554     void GLUP_API glupVertex3f(GLUPfloat x, GLUPfloat y, GLUPfloat z);
555     void GLUP_API glupVertex4f(
556         GLUPfloat x, GLUPfloat y, GLUPfloat z, GLUPfloat w
557     );
558 
559     void GLUP_API glupVertex2d(GLUPdouble x, GLUPdouble y);
560     void GLUP_API glupVertex3d(GLUPdouble x, GLUPdouble y, GLUPdouble z);
561     void GLUP_API glupVertex4d(
562         GLUPdouble x, GLUPdouble y, GLUPdouble z, GLUPdouble w
563     );
564 
565     void GLUP_API glupColor3fv(const GLUPfloat* rgb);
566     void GLUP_API glupColor4fv(const GLUPfloat* rgba);
567 
568     void GLUP_API glupColor3dv(const GLUPdouble* rgb);
569     void GLUP_API glupColor4dv(const GLUPdouble* rgba);
570 
571     void GLUP_API glupColor3f(GLUPfloat r, GLUPfloat g, GLUPfloat b);
572     void GLUP_API glupColor4f(
573         GLUPfloat r, GLUPfloat g, GLUPfloat b, GLUPfloat a
574     );
575 
576     void GLUP_API glupColor3d(GLUPdouble r, GLUPdouble g, GLUPdouble b);
577     void GLUP_API glupColor4d(
578         GLUPdouble r, GLUPdouble g, GLUPdouble b, GLUPdouble a
579     );
580 
581     void GLUP_API glupTexCoord2fv(const GLUPfloat* st);
582     void GLUP_API glupTexCoord3fv(const GLUPfloat* stu);
583     void GLUP_API glupTexCoord4fv(const GLUPfloat* stuv);
584 
585     void GLUP_API glupTexCoord2dv(const GLUPdouble* st);
586     void GLUP_API glupTexCoord3dv(const GLUPdouble* stu);
587     void GLUP_API glupTexCoord4dv(const GLUPdouble* stuv);
588 
589     void GLUP_API glupTexCoord1f(GLUPfloat s);
590     void GLUP_API glupTexCoord2f(GLUPfloat s, GLUPfloat t);
591     void GLUP_API glupTexCoord3f(GLUPfloat s, GLUPfloat t, GLUPfloat u);
592     void GLUP_API glupTexCoord4f(
593         GLUPfloat s, GLUPfloat t, GLUPfloat u, GLUPfloat v
594     );
595 
596     void GLUP_API glupTexCoord1d(GLUPdouble s);
597     void GLUP_API glupTexCoord2d(GLUPdouble s, GLUPdouble t);
598     void GLUP_API glupTexCoord3d(GLUPdouble s, GLUPdouble t, GLUPdouble u);
599     void GLUP_API glupTexCoord4d(
600         GLUPdouble s, GLUPdouble t, GLUPdouble u, GLUPdouble v
601     );
602 
603 
604     void GLUP_API glupNormal3fv(GLUPfloat* xyz);
605     void GLUP_API glupNormal3f(GLUPfloat x, GLUPfloat y, GLUPfloat z);
606 
607     void GLUP_API glupNormal3dv(GLUPdouble* xyz);
608     void GLUP_API glupNormal3d(GLUPdouble x, GLUPdouble y, GLUPdouble z);
609 
610 
611     /**
612      * \brief Specifies a GLSL program to be used for drawing the primitives.
613      * \details Can be used with both immediate mode (glupBegin()/glupEnd())
614      *  and array mode (glupDrawArrays(), glupDrawElements()). If the specified
615      *  program is non-zero, then it is used instead of the default GLUP
616      *  program. To access the GLUP uniform state in the program, one may
617      *  append the result of glupUniformStateDeclaration() to the GLSL source
618      *  of the program.
619      * \param[in] program the id of the GLSL program to be used.
620      */
621     void GLUP_API glupUseProgram(GLUPuint program);
622 
623     /**
624      * @}
625      */
626 
627     /************************************************/
628 
629     /**
630      * \name GLUP Vertex Array Object wrapper or emulation.
631      * @{
632      */
633 
634     /**
635      * \brief Generate vertex array object names.
636      * \details This function is a wrapper around glGenVertexArrays()
637      *  if it is supported, else it emulates it.
638      * \param[in] n the number of vertex array object names to generate.
639      * \param[in] arrays an array in which the generated vertex array
640      *   object names are stored.
641      */
642     void GLUP_API glupGenVertexArrays(GLUPsizei n, GLUPuint* arrays);
643 
644     /**
645      * \brief Deletes vertex array objects.
646      * \details This function is a wrapper around glDeleteVertexArrays()
647      *  if it is supported, else it emulates it.
648      * \param[in] n the number of vertex array objects to be deleted.
649      * \param[in] arrays the address of an array containing the \p n
650      *   names of the objects to be deleted.
651      */
652     void GLUP_API glupDeleteVertexArrays(GLUPsizei n, const GLUPuint *arrays);
653 
654 
655     /**
656      * \brief Binds a vertex array object.
657      * \details This function is a wrapper around glBindVertexArray()
658      *  if it is supported, else it emulates it.
659      * \param[in] array the name of the vertex array to bind.
660      */
661     void GLUP_API glupBindVertexArray(GLUPuint array);
662 
663     /**
664      * \brief Gets the name of the bound vertex array object.
665      * \details This function uses glGet(GL_VERTEX_ARRAY_BINDING) if
666      *  vertex array objects are supported, else it emulates it.
667      * \return the name of the bound vertex array object or 0
668      *  if no vertex array object is bound.
669      */
670     GLUPuint GLUP_API glupGetVertexArrayBinding(void);
671 
672     /**
673      * @}
674      */
675 
676 #ifdef __cplusplus
677 }
678 #endif
679 
680 #endif
681