1 /* $Id: overlay.c,v 1.10 2007/08/03 16:48:50 gregcouch Exp $ */
2 
3 /*
4  * Togl - a Tk OpenGL widget
5  * Copyright (C) 1996-1997  Brian Paul and Ben Bederson
6  * Copyright (C) 2006-2007  Greg Couch
7  * See the LICENSE file for copyright details.
8  */
9 
10 
11 /*
12  * An example Togl program using an overlay.
13  */
14 
15 #define USE_TOGL_STUBS
16 
17 #include "togl.h"
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #undef TCL_STORAGE_CLASS
22 #define TCL_STORAGE_CLASS DLLEXPORT
23 
24 
25 /* Overlay color indexes: */
26 static unsigned long Red, Green;
27 
28 
29 /*
30  * Togl widget create callback.  This is called by Tcl/Tk when the widget has
31  * been realized.  Here's where one may do some one-time context setup or
32  * initializations.
33  */
34 static int
create_cb(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * const * objv)35 create_cb(ClientData clientData, Tcl_Interp *interp, int objc,
36         Tcl_Obj *const *objv)
37 {
38     Togl   *togl;
39 
40     if (objc != 2) {
41         Tcl_WrongNumArgs(interp, 1, objv, "pathName");
42         return TCL_ERROR;
43     }
44 
45     if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {
46         return TCL_ERROR;
47     }
48 
49     /* allocate overlay color indexes */
50     Red = Togl_AllocColorOverlay(togl, 1, 0, 0);
51     Green = Togl_AllocColorOverlay(togl, 0, 1, 0);
52 
53     /* in this demo we always show the overlay */
54     if (Togl_ExistsOverlay(togl)) {
55         Togl_ShowOverlay(togl);
56         printf("Red and green lines are in the overlay\n");
57     } else {
58         printf("Sorry, this display doesn't support overlays\n");
59     }
60     return TCL_OK;
61 }
62 
63 
64 /*
65  * Togl widget reshape callback.  This is called by Tcl/Tk when the widget
66  * has been resized.  Typically, we call glViewport and perhaps setup the
67  * projection matrix.
68  */
69 static int
reshape_cb(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * const * objv)70 reshape_cb(ClientData clientData, Tcl_Interp *interp, int objc,
71         Tcl_Obj *const *objv)
72 {
73     int     width;
74     int     height;
75     float   aspect;
76     Togl   *togl;
77 
78     if (objc != 2) {
79         Tcl_WrongNumArgs(interp, 1, objv, "pathName");
80         return TCL_ERROR;
81     }
82 
83     if (Togl_GetToglFromObj(interp, objv[1], &togl) != TCL_OK) {
84         return TCL_ERROR;
85     }
86 
87     width = Togl_Width(togl);
88     height = Togl_Height(togl);
89     aspect = (float) width / (float) height;
90 
91     /* Set up viewing for normal plane's context */
92     glViewport(0, 0, width, height);
93     glMatrixMode(GL_PROJECTION);
94     glLoadIdentity();
95     glOrtho(-aspect, aspect, -1, 1, -1, 1);
96     glMatrixMode(GL_MODELVIEW);
97 
98     /* Set up viewing for overlay plane's context */
99     if (Togl_ExistsOverlay(togl)) {
100         Togl_UseLayer(togl, TOGL_OVERLAY);
101         glViewport(0, 0, width, height);
102         glMatrixMode(GL_PROJECTION);
103         glLoadIdentity();
104         glOrtho(-1, 1, -1, 1, -1, 1);
105         glMatrixMode(GL_MODELVIEW);
106         Togl_UseLayer(togl, TOGL_NORMAL);
107     }
108     return TCL_OK;
109 }
110 
111 
112 /*
113  * Togl widget overlay display callback.  This is called by Tcl/Tk when the
114  * overlay has to be redrawn.
115  */
116 static int
overlay_display_cb(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * const * objv)117 overlay_display_cb(ClientData clientData, Tcl_Interp *interp, int objc,
118         Tcl_Obj *const *objv)
119 {
120     glClear(GL_COLOR_BUFFER_BIT);
121 
122     glIndexi(Red);
123     glBegin(GL_LINES);
124     glVertex2f(-1, -1);
125     glVertex2f(1, 1);
126     glVertex2f(-1, 1);
127     glVertex2f(1, -1);
128     glEnd();
129 
130     glIndexi(Green);
131     glBegin(GL_LINE_LOOP);
132     glVertex2f(-0.5f, -0.5f);
133     glVertex2f(0.5f, -0.5f);
134     glVertex2f(0.5f, 0.5f);
135     glVertex2f(-0.5f, 0.5f);
136     glEnd();
137     glFlush();
138     return TCL_OK;
139 }
140 
141 
142 /*
143  * Togl widget display callback.  This is called by Tcl/Tk when the widget's
144  * contents have to be redrawn.  Typically, we clear the color and depth
145  * buffers, render our objects, then swap the front/back color buffers.
146  */
147 static int
display_cb(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * const * objv)148 display_cb(ClientData clientData, Tcl_Interp *interp, int objc,
149         Tcl_Obj *const *objv)
150 {
151     glClear(GL_COLOR_BUFFER_BIT);
152 
153     glLoadIdentity();
154 
155     glBegin(GL_TRIANGLES);
156 
157     glColor3f(1, 0, 1);
158     glVertex2f(-0.5f, -0.3f);
159     glVertex2f(0.5f, -0.3f);
160     glVertex2f(0, 0.6f);
161 
162     glColor3f(1, 1, 0);
163     glVertex2f(-0.5f + 0.2f, -0.3f - 0.2f);
164     glVertex2f(0.5f + 0.2f, -0.3f - 0.2f);
165     glVertex2f(0 + 0.2f, 0.6f - 0.2f);
166 
167     glColor3f(0, 1, 1);
168     glVertex2f(-0.5f + 0.4f, -0.3f - 0.4f);
169     glVertex2f(0.5f + 0.4f, -0.3f - 0.4f);
170     glVertex2f(0 + 0.4f, 0.6f - 0.4f);
171 
172     glEnd();
173 
174     glFlush();
175     return TCL_OK;
176 }
177 
178 
179 /*
180  * Called by Tcl to let me initialize the modules (Togl) I will need.
181  */
182 EXTERN int
Overlay_Init(Tcl_Interp * interp)183 Overlay_Init(Tcl_Interp *interp)
184 {
185     /*
186      * Initialize Tcl and the Togl widget module.
187      */
188     if (Tcl_InitStubs(interp, "8.1", 0) == NULL
189             || Togl_InitStubs(interp, "2.0", 0) == NULL) {
190         return TCL_ERROR;
191     }
192 
193     /*
194      * Specify the C callback functions for widget creation, display,
195      * and reshape.
196      */
197     Tcl_CreateObjCommand(interp, "create_cb", create_cb, NULL, NULL);
198     Tcl_CreateObjCommand(interp, "display_cb", display_cb, NULL, NULL);
199     Tcl_CreateObjCommand(interp, "reshape_cb", reshape_cb, NULL, NULL);
200 
201     Tcl_CreateObjCommand(interp, "overlay_display_cb", overlay_display_cb, NULL,
202             NULL);
203 
204     /*
205      * Make a new Togl widget command so the Tcl code can set a C variable.
206      */
207     /* NONE */
208 
209     /*
210      * Call Tcl_CreateCommand for application-specific commands, if
211      * they weren't already created by the init procedures called above.
212      */
213     return TCL_OK;
214 }
215