*** empty log message ***
[lsystem3d.git] / src / renderingsurface.cpp
1 // Copyright (C) 2006 Erik Dahlberg
2 //
3 // This file is part of LSystem3D.
4 //
5 // LSystem3D is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // LSystem3D is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with LSystem3D; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19
20
21
22 #include <GL/gl.h>
23 #include <GL/glu.h>
24
25 #include "fx.h"
26 #include "fx3d.h"
27
28 #include "renderingsurface.h"
29
30
31
32 // message map
33 FXDEFMAP(RenderingSurface) RenderingSurfaceMap[] =
34 {
35 FXMAPFUNC(SEL_LEFTBUTTONPRESS, RenderingSurface::ID_CANVAS, RenderingSurface::onLeftMouseDown),
36 FXMAPFUNC(SEL_LEFTBUTTONRELEASE, RenderingSurface::ID_CANVAS, RenderingSurface::onLeftMouseUp),
37 FXMAPFUNC(SEL_MIDDLEBUTTONPRESS, RenderingSurface::ID_CANVAS, RenderingSurface::onMiddleMouseDown),
38 FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE, RenderingSurface::ID_CANVAS, RenderingSurface::onMiddleMouseUp),
39 FXMAPFUNC(SEL_RIGHTBUTTONPRESS, RenderingSurface::ID_CANVAS, RenderingSurface::onRightMouseDown),
40 FXMAPFUNC(SEL_RIGHTBUTTONRELEASE, RenderingSurface::ID_CANVAS, RenderingSurface::onRightMouseUp),
41 FXMAPFUNC(SEL_MOTION, RenderingSurface::ID_CANVAS, RenderingSurface::onMouseMove),
42 FXMAPFUNC(SEL_PAINT, RenderingSurface::ID_CANVAS, RenderingSurface::onRepaint)
43 };
44
45 // macro to set up class implementation
46 FXIMPLEMENT(RenderingSurface, FXMainWindow, RenderingSurfaceMap, ARRAYNUMBER(RenderingSurfaceMap))
47
48
49
50 /**
51 * Constructor
52 * @param application the FOX application object
53 * @param lsystem the Lindenmayer-system
54 */
55 RenderingSurface::RenderingSurface(FXApp *application, LindenmayerSystem *lsystem) : FXMainWindow(application, "LSystem3D", NULL, NULL, DECOR_ALL, 100, 100, 800, 800)
56 {
57 _lsystem = lsystem;
58
59 _modelX = 0.0;
60 _modelY = 0.0;
61 _modelZ = -10.0;
62
63 _modelRotationY = 0.0;
64
65 _leftMouseDown = _rightMouseDown = _middleMouseDown = false;
66
67
68 // pixel format info
69 _visual = new FXGLVisual(getApp(), VISUAL_DOUBLEBUFFER);
70
71 // OpenGL drawing area
72 FXVerticalFrame *mainFrame = new FXVerticalFrame(this, LAYOUT_FILL_X | LAYOUT_FILL_Y);
73 _canvas = new FXGLCanvas(mainFrame, _visual, this, ID_CANVAS, LAYOUT_FILL_X | LAYOUT_FILL_Y);
74 }
75
76
77
78 /**
79 * Create and initialize the window
80 */
81 void RenderingSurface::create()
82 {
83 // create the window
84 FXMainWindow::create();
85
86 // set up OpenGL
87 _canvas->makeCurrent();
88 initOpenGL();
89
90 // make the window appear
91 show();
92 }
93
94
95
96 /**
97 * Initialize OpenGL
98 */
99 void RenderingSurface::initOpenGL()
100 {
101 // projection matrix
102 glMatrixMode(GL_PROJECTION);
103 glLoadIdentity();
104 gluPerspective(65, 1, 1, 500);
105
106 // modelview matrix
107 glMatrixMode(GL_MODELVIEW);
108 glLoadIdentity();
109
110
111 // global ambient light
112 GLfloat ambientLight[] = {0.7, 0.7, 0.7, 1.0};
113 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);
114
115 // diffuse light
116 GLfloat lightPosition[] = {150.0, 150.0, 0.0, 0.0};
117 GLfloat whiteLight[] = {1.0, 1.0, 1.0, 1.0};
118 glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteLight);
119 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
120
121
122 glEnable(GL_COLOR_MATERIAL);
123 glEnable(GL_LIGHTING);
124 glEnable(GL_LIGHT0);
125 glEnable(GL_DEPTH_TEST);
126 }
127
128
129
130 /**
131 * Force an update of the rendering surface
132 */
133 void RenderingSurface::draw()
134 {
135 _canvas->update();
136 }
137
138
139
140 /**
141 * Called by the system when the left mouse button is pressed
142 * @param sender the sender object
143 * @param selector message type and id
144 * @param data event related data
145 * @return
146 */
147 long RenderingSurface::onLeftMouseDown(FXObject *sender, FXSelector selector, void *data)
148 {
149 _leftMouseDown = true;
150 }
151
152
153
154 /**
155 * Called by the system when the left mouse button is released
156 * @param sender the sender object
157 * @param selector message type and id
158 * @param data event related data
159 * @return
160 */
161 long RenderingSurface::onLeftMouseUp(FXObject *sender, FXSelector selector, void *data)
162 {
163 _leftMouseDown = false;
164 }
165
166
167
168 /**
169 * Called by the system when the middle mouse button is pressed
170 * @param sender the sender object
171 * @param selector message type and id
172 * @param data event related data
173 * @return
174 */
175 long RenderingSurface::onMiddleMouseDown(FXObject *sender, FXSelector selector, void *data)
176 {
177 _middleMouseDown = true;
178 }
179
180
181
182 /**
183 * Called by the system when the middle mouse button is released
184 * @param sender the sender object
185 * @param selector message type and id
186 * @param data event related data
187 * @return
188 */
189 long RenderingSurface::onMiddleMouseUp(FXObject *sender, FXSelector selector, void *data)
190 {
191 _middleMouseDown = false;
192 }
193
194
195
196 /**
197 * Called by the system when the right mouse button is pressed
198 * @param sender the sender object
199 * @param selector message type and id
200 * @param data event related data
201 * @return
202 */
203 long RenderingSurface::onRightMouseDown(FXObject *sender, FXSelector selector, void *data)
204 {
205 _rightMouseDown = true;
206 }
207
208
209
210 /**
211 * Called by the system when the right mouse button is released
212 * @param sender the sender object
213 * @param selector message type and id
214 * @param data event related data
215 * @return
216 */
217 long RenderingSurface::onRightMouseUp(FXObject *sender, FXSelector selector, void *data)
218 {
219 _rightMouseDown = false;
220 }
221
222
223
224 /**
225 * Called by the system when the mouse is moved
226 * @param sender the sender object
227 * @param selector message type and id
228 * @param data event related data
229 * @return
230 */
231 long RenderingSurface::onMouseMove(FXObject *sender, FXSelector selector, void *data)
232 {
233 // check status of the mouse buttons and move model
234
235 // left mouse button
236 if (_leftMouseDown)
237 {
238 // move in z-plane
239
240 FXEvent *event = (FXEvent*)data;
241
242 // TODO: "gluPerspective(65, 1, 1, 500)" -> "translateFactor = 610.0 / (-_modelZ)", ugly...
243 double translateFactor = 610.0 / (-_modelZ);
244
245 _modelX += (event->win_x - event->last_x) / translateFactor;
246 _modelY += -(event->win_y - event->last_y) / translateFactor;
247
248 _canvas->update();
249 }
250
251 // middle mouse button
252 if (_middleMouseDown)
253 {
254 // zoom in/out
255
256 FXEvent *event = (FXEvent*)data;
257
258 _modelZ += -(event->win_y - event->last_y) / 10.0;
259
260 // stop zooming at -1.0
261 if (_modelZ >= -1.0)
262 {
263 _modelZ = -1.0;
264 }
265
266 _canvas->update();
267 }
268
269 // right mouse button
270 if (_rightMouseDown)
271 {
272 // rotate around y-axis
273
274 FXEvent *event = (FXEvent*)data;
275
276 _modelRotationY = ((int)_modelRotationY + event->win_x - event->last_x) % 360;
277
278 _canvas->update();
279 }
280 }
281
282
283
284 /**
285 * Called by the system when the rendering surface needs a repaint
286 * @param sender the sender object
287 * @param selector message type and id
288 * @param data event related data
289 * @return
290 */
291 long RenderingSurface::onRepaint(FXObject *sender, FXSelector selector, void *data)
292 {
293 glMatrixMode (GL_MODELVIEW);
294 glLoadIdentity();
295
296
297 // clear scene
298 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
299
300 // position and orientation of model
301 glTranslatef(_modelX, _modelY, _modelZ);
302 glRotatef(_modelRotationY, 0.0, 1.0, 0.0);
303
304 // render model
305 _lsystem->getModel()->draw();
306
307
308 // make it appear
309 _canvas->swapBuffers();
310 }