*** empty log message ***
[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),
42 FXMAPFUNC(SEL_PAINT, RenderingSurface::ID_CANVAS, RenderingSurface::onRepaint)
43};
44
45// macro to set up class implementation
46FXIMPLEMENT(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 */
55RenderingSurface::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 */
81void 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 */
99void 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 */
133void 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 */
147long 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 */
161long 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 */
175long 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 */
189long 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 */
203long 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 */
217long 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 */
231long 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 */
291long 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}