Minor cleanup.
[lsystem3d.git] / src / renderingsurface.cpp
CommitLineData
3025996b 1// Copyright (C) 2006 Erik Dahlberg
2//
1a372e99 3// This file is part of LSystem3D.
3025996b 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
33FXDEFMAP(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),
1b297ccb 42 FXMAPFUNC(SEL_PAINT, RenderingSurface::ID_CANVAS, RenderingSurface::onRepaint),
43 FXMAPFUNC(SEL_CLOSE, 0, RenderingSurface::onQuit)
3025996b 44};
45
46// macro to set up class implementation
47FXIMPLEMENT(RenderingSurface, FXMainWindow, RenderingSurfaceMap, ARRAYNUMBER(RenderingSurfaceMap))
48
49
50
51/**
52 * Constructor
1b297ccb 53 * @param application the application object
3025996b 54 */
1b297ccb 55RenderingSurface::RenderingSurface(FXApp *application) : FXMainWindow(application, "LSystem3D", NULL, NULL, DECOR_ALL, 100, 100, 800, 800)
3025996b 56{
1b297ccb 57 _lsystem = NULL;
3025996b 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
1b297ccb 78/**
79 * Destructor
80 */
81RenderingSurface::~RenderingSurface()
82{
83 delete _visual;
84}
85
86
87
3025996b 88/**
89 * Create and initialize the window
90 */
91void RenderingSurface::create()
92{
93 // create the window
94 FXMainWindow::create();
95
96 // set up OpenGL
97 _canvas->makeCurrent();
1b297ccb 98
3025996b 99 initOpenGL();
100
101 // make the window appear
102 show();
103}
104
105
106
107/**
108 * Initialize OpenGL
109 */
110void RenderingSurface::initOpenGL()
111{
112 // projection matrix
113 glMatrixMode(GL_PROJECTION);
114 glLoadIdentity();
115 gluPerspective(65, 1, 1, 500);
116
117 // modelview matrix
118 glMatrixMode(GL_MODELVIEW);
119 glLoadIdentity();
120
121
122 // global ambient light
123 GLfloat ambientLight[] = {0.7, 0.7, 0.7, 1.0};
124 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambientLight);
125
126 // diffuse light
127 GLfloat lightPosition[] = {150.0, 150.0, 0.0, 0.0};
128 GLfloat whiteLight[] = {1.0, 1.0, 1.0, 1.0};
129 glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteLight);
130 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
131
132
133 glEnable(GL_COLOR_MATERIAL);
134 glEnable(GL_LIGHTING);
135 glEnable(GL_LIGHT0);
136 glEnable(GL_DEPTH_TEST);
137}
138
139
140
141/**
142 * Force an update of the rendering surface
143 */
144void RenderingSurface::draw()
145{
146 _canvas->update();
147}
148
149
150
151/**
152 * Called by the system when the left mouse button is pressed
153 * @param sender the sender object
154 * @param selector message type and id
155 * @param data event related data
156 * @return
157 */
158long RenderingSurface::onLeftMouseDown(FXObject *sender, FXSelector selector, void *data)
159{
160 _leftMouseDown = true;
161}
162
163
164
165/**
166 * Called by the system when the left mouse button is released
167 * @param sender the sender object
168 * @param selector message type and id
169 * @param data event related data
170 * @return
171 */
172long RenderingSurface::onLeftMouseUp(FXObject *sender, FXSelector selector, void *data)
173{
174 _leftMouseDown = false;
175}
176
177
178
179/**
180 * Called by the system when the middle mouse button is pressed
181 * @param sender the sender object
182 * @param selector message type and id
183 * @param data event related data
184 * @return
185 */
186long RenderingSurface::onMiddleMouseDown(FXObject *sender, FXSelector selector, void *data)
187{
188 _middleMouseDown = true;
189}
190
191
192
193/**
194 * Called by the system when the middle mouse button is released
195 * @param sender the sender object
196 * @param selector message type and id
197 * @param data event related data
198 * @return
199 */
200long RenderingSurface::onMiddleMouseUp(FXObject *sender, FXSelector selector, void *data)
201{
202 _middleMouseDown = false;
203}
204
205
206
207/**
208 * Called by the system when the right mouse button is pressed
209 * @param sender the sender object
210 * @param selector message type and id
211 * @param data event related data
212 * @return
213 */
214long RenderingSurface::onRightMouseDown(FXObject *sender, FXSelector selector, void *data)
215{
216 _rightMouseDown = true;
217}
218
219
220
221/**
222 * Called by the system when the right mouse button is released
223 * @param sender the sender object
224 * @param selector message type and id
225 * @param data event related data
226 * @return
227 */
228long RenderingSurface::onRightMouseUp(FXObject *sender, FXSelector selector, void *data)
229{
230 _rightMouseDown = false;
231}
232
233
234
235/**
236 * Called by the system when the mouse is moved
237 * @param sender the sender object
238 * @param selector message type and id
239 * @param data event related data
240 * @return
241 */
242long RenderingSurface::onMouseMove(FXObject *sender, FXSelector selector, void *data)
243{
244 // check status of the mouse buttons and move model
245
246 // left mouse button
247 if (_leftMouseDown)
248 {
249 // move in z-plane
250
251 FXEvent *event = (FXEvent*)data;
252
253 // TODO: "gluPerspective(65, 1, 1, 500)" -> "translateFactor = 610.0 / (-_modelZ)", ugly...
254 double translateFactor = 610.0 / (-_modelZ);
255
256 _modelX += (event->win_x - event->last_x) / translateFactor;
257 _modelY += -(event->win_y - event->last_y) / translateFactor;
258
259 _canvas->update();
260 }
261
262 // middle mouse button
263 if (_middleMouseDown)
264 {
265 // zoom in/out
266
267 FXEvent *event = (FXEvent*)data;
268
269 _modelZ += -(event->win_y - event->last_y) / 10.0;
270
271 // stop zooming at -1.0
272 if (_modelZ >= -1.0)
273 {
274 _modelZ = -1.0;
275 }
276
277 _canvas->update();
278 }
279
280 // right mouse button
281 if (_rightMouseDown)
282 {
283 // rotate around y-axis
284
285 FXEvent *event = (FXEvent*)data;
286
287 _modelRotationY = ((int)_modelRotationY + event->win_x - event->last_x) % 360;
288
289 _canvas->update();
290 }
291}
292
293
294
295/**
296 * Called by the system when the rendering surface needs a repaint
297 * @param sender the sender object
298 * @param selector message type and id
299 * @param data event related data
300 * @return
301 */
302long RenderingSurface::onRepaint(FXObject *sender, FXSelector selector, void *data)
303{
304 glMatrixMode (GL_MODELVIEW);
305 glLoadIdentity();
306
307
308 // clear scene
309 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
310
311 // position and orientation of model
312 glTranslatef(_modelX, _modelY, _modelZ);
313 glRotatef(_modelRotationY, 0.0, 1.0, 0.0);
314
315 // render model
1b297ccb 316 _lsystem->render();
3025996b 317
318 // make it appear
319 _canvas->swapBuffers();
320}
1b297ccb 321
322
323
324/**
325 * Called by the system when the close button is pressed
326 * @param sender the sender object
327 * @param selector message type and id
328 * @param data event related data
329 * @return
330 */
331long RenderingSurface::onQuit(FXObject *sender, FXSelector selector, void *data)
332{
333 getApp()->exit(0);
334
335 return 1;
336}
337
338
339
340/**
341 * Set current L-system generator
342 * @param lsystem the L-system generator
343 */
344void RenderingSurface::setLSystem(LindenmayerSystem *lsystem)
345{
346 _lsystem = lsystem;
347}