2
* ***** BEGIN GPL LICENSE BLOCK *****
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License
6
* as published by the Free Software Foundation; either version 2
7
* of the License, or (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19
* All rights reserved.
21
* The Original Code is: all of this file.
23
* Contributor(s): none yet.
25
* ***** END GPL LICENSE BLOCK *****
30
* Copyright (C) 2001 NaN Technologies B.V.
32
#if defined(WIN32) || defined(__APPLE__)
40
#else // defined(WIN32) || defined(__APPLE__)
43
#endif // defined(WIN32) || defined(__APPLE__)
46
#include "BSP_GhostTest3D.h"
47
#include "BSP_MeshDrawer.h"
49
#include "GHOST_ISystem.h"
50
#include "GHOST_IWindow.h"
52
#include "MT_Quaternion.h"
53
#include "MT_Transform.h"
54
#include "CSG_BooleanOps.h"
78
m_finish_me_off(false),
87
MEM_SmartPtr<BSP_TMesh> mesh
89
m_meshes.push_back(mesh);
91
BSP_RotationSetting rotation_setting;
92
BSP_TranslationSetting translation_setting;
94
rotation_setting.m_angle_x = MT_Scalar(0);
95
rotation_setting.m_angle_y = MT_Scalar(0);
96
rotation_setting.m_moving = false;
97
rotation_setting.x_old = 0;
98
rotation_setting.y_old = 0;
100
translation_setting.m_t_x = MT_Scalar(0);
101
translation_setting.m_t_y = MT_Scalar(0);
102
translation_setting.m_t_z = MT_Scalar(0);
103
translation_setting.m_moving = false;
104
translation_setting.x_old = 0;
105
translation_setting.y_old = 0;
107
m_rotation_settings.push_back(rotation_setting);
108
m_translation_settings.push_back(translation_setting);
109
m_render_modes.push_back(e_wireframe_shaded);
110
m_scale_settings.push_back(MT_Scalar(1));
120
if (!m_rotation_settings[i].m_moving && !m_translation_settings[i].m_moving) {
121
swap(m_meshes[i],m_meshes.back());
122
swap(m_rotation_settings[i],m_rotation_settings.back());
123
swap(m_translation_settings[i],m_translation_settings.back());
124
swap(m_scale_settings[i],m_scale_settings.back());
125
swap(m_render_modes[i],m_render_modes.back());
136
MT_Quaternion q_ax(MT_Vector3(0,1,0),m_rotation_settings[i].m_angle_x);
137
MT_Quaternion q_ay(MT_Vector3(1,0,0),m_rotation_settings[i].m_angle_y);
140
m_translation_settings[i].m_t_x,
141
m_translation_settings[i].m_t_y,
142
m_translation_settings[i].m_t_z
146
MT_Matrix3x3 rotx(q_ax);
147
MT_Matrix3x3 roty(q_ay);
149
MT_Matrix3x3 rot = rotx * roty;
151
MT_Transform trans(tr,rot);
154
scalet.setIdentity();
155
scalet.scale(m_scale_settings[i],m_scale_settings[i],m_scale_settings[i]);
157
return trans * scalet;
166
CSG_VertexIteratorDescriptor * vA = VertexIt_Construct(m_meshes[0],GetTransform(0));
167
CSG_FaceIteratorDescriptor * fA = FaceIt_Construct(m_meshes[0]);
169
CSG_VertexIteratorDescriptor * vB = VertexIt_Construct(m_meshes[1],GetTransform(1));
170
CSG_FaceIteratorDescriptor * fB = FaceIt_Construct(m_meshes[1]);
172
// describe properties.
174
CSG_MeshPropertyDescriptor props;
175
props.user_face_vertex_data_size = 0;
176
props.user_data_size = 0;
178
CSG_BooleanOperation * op = CSG_NewBooleanFunction();
179
props = CSG_DescibeOperands(op,props,props);
181
CSG_PerformBooleanOperation(
182
op,CSG_OperationType(type),
183
*fA,*vA,*fB,*vB,EmptyInterpFunc
186
CSG_FaceIteratorDescriptor out_f;
187
CSG_OutputFaceDescriptor(op,&out_f);
189
CSG_VertexIteratorDescriptor out_v;
190
CSG_OutputVertexDescriptor(op,&out_v);
192
MEM_SmartPtr<BSP_TMesh> new_mesh (BuildMesh(props,out_f,out_v));
196
CSG_FreeVertexDescriptor(&out_v);
197
CSG_FreeFaceDescriptor(&out_f);
198
CSG_FreeBooleanOperation(op);
212
m_window->getClientBounds(v_rect);
214
glViewport(0,0,v_rect.getWidth(),v_rect.getHeight());
223
const MT_Vector3 & vec
227
GLdouble mvmatrix[16],projmatrix[16];
229
glGetIntegerv(GL_VIEWPORT,viewport);
230
glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
231
glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
233
GLdouble realy = viewport[3] - vec.y() - 1;
234
GLdouble outx,outy,outz;
236
gluUnProject(vec.x(),realy,vec.z(),mvmatrix,projmatrix,viewport,&outx,&outy,&outz);
238
return MT_Vector3(outx,outy,outz);
247
// create a system and window with opengl
248
// rendering context.
250
GHOST_TSuccess success = GHOST_ISystem::createSystem();
251
if (success == GHOST_kFailure) return false;
253
m_system = GHOST_ISystem::getSystem();
254
if (m_system == NULL) return false;
256
m_system->addEventConsumer(this);
258
m_window = m_system->createWindow(
260
100,100,512,512,GHOST_kWindowStateNormal,
261
GHOST_kDrawingContextTypeOpenGL,false
268
GHOST_ISystem::disposeSystem();
272
// make an opengl frustum for this wind
276
min = m_meshes[0]->m_min;
277
max = m_meshes[0]->m_max;
287
if (m_system == NULL) {
291
while (!m_finish_me_off) {
292
m_system->processEvents(true);
293
m_system->dispatchEvents();
303
bool handled = false;
305
switch(event->getType()) {
306
case GHOST_kEventWindowSize:
307
case GHOST_kEventWindowActivate:
309
case GHOST_kEventWindowUpdate:
313
case GHOST_kEventButtonDown:
316
m_system->getCursorPosition(x,y);
320
m_window->screenToClient(x,y,wx,wy);
322
GHOST_TButtonMask button =
323
static_cast<GHOST_TEventButtonData *>(event->getData())->button;
325
if (button == GHOST_kButtonMaskLeft) {
326
m_rotation_settings[m_current_object].m_moving = true;
327
m_rotation_settings[m_current_object].x_old = x;
328
m_rotation_settings[m_current_object].y_old = y;
330
if (button == GHOST_kButtonMaskRight) {
331
m_translation_settings[m_current_object].m_moving = true;
332
m_translation_settings[m_current_object].x_old = x;
333
m_translation_settings[m_current_object].y_old = y;
336
m_window->invalidate();
342
case GHOST_kEventButtonUp:
345
GHOST_TButtonMask button =
346
static_cast<GHOST_TEventButtonData *>(event->getData())->button;
348
if (button == GHOST_kButtonMaskLeft) {
349
m_rotation_settings[m_current_object].m_moving = false;
350
m_rotation_settings[m_current_object].x_old = 0;
351
m_rotation_settings[m_current_object].y_old = 0;
354
if (button == GHOST_kButtonMaskRight) {
355
m_translation_settings[m_current_object].m_moving = false;
356
m_translation_settings[m_current_object].x_old;
357
m_translation_settings[m_current_object].y_old;
360
m_window->invalidate();
366
case GHOST_kEventCursorMove:
369
m_system->getCursorPosition(x,y);
371
m_window->screenToClient(x,y,wx,wy);
373
if (m_rotation_settings[m_current_object].m_moving) {
374
m_rotation_settings[m_current_object].m_angle_x = MT_Scalar(wx)/20;
375
m_rotation_settings[m_current_object].x_old = wx;
376
m_rotation_settings[m_current_object].m_angle_y = MT_Scalar(wy)/20;
377
m_rotation_settings[m_current_object].y_old = wy;
379
m_window->invalidate();
381
if (m_translation_settings[m_current_object].m_moving) {
383
// project current objects bounding box center into screen space.
384
// unproject mouse point into object space using z-value from
385
// projected bounding box center.
388
m_window->getClientBounds(bounds);
390
int w_h = bounds.getHeight();
396
double projmatrix[16];
399
double px, py, pz,sz;
401
/* Get the matrices needed for gluUnProject */
402
glGetIntegerv(GL_VIEWPORT, viewport);
403
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
404
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
406
// work out the position of the end effector in screen space
410
ex = m_translation_settings[m_current_object].m_t_x;
411
ey = m_translation_settings[m_current_object].m_t_y;
412
ez = m_translation_settings[m_current_object].m_t_z;
414
gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz);
415
gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz);
417
m_translation_settings[m_current_object].m_t_x = px;
418
m_translation_settings[m_current_object].m_t_y = py;
419
m_translation_settings[m_current_object].m_t_z = pz;
420
m_window->invalidate();
428
case GHOST_kEventKeyDown :
430
GHOST_TEventKeyData *kd =
431
static_cast<GHOST_TEventKeyData *>(event->getData());
437
// now intersect meshes.
438
Operate(e_csg_intersection);
440
m_window->invalidate();
445
Operate(e_csg_union);
447
m_window->invalidate();
452
Operate(e_csg_difference);
454
m_window->invalidate();
461
m_scale_settings[m_current_object] *= 1.1;
463
m_window->invalidate();
468
m_scale_settings[m_current_object] *= 0.8;
471
m_window->invalidate();
476
m_render_modes[m_current_object]++;
477
if (m_render_modes[m_current_object] > e_last_render_mode) {
478
m_render_modes[m_current_object] = e_first_render_mode;
481
m_window->invalidate();
486
m_window->invalidate();
490
m_finish_me_off = true;
495
Swap(m_current_object);
496
m_window->invalidate();
500
case GHOST_kKeySpace:
502
// increment the current object only if the object is not being
504
if (! (m_rotation_settings[m_current_object].m_moving || m_translation_settings[m_current_object].m_moving)) {
506
if (m_current_object >= m_meshes.size()) {
507
m_current_object = 0;
511
m_window->invalidate();
530
m_system->disposeWindow(m_window);
532
GHOST_ISystem::disposeSystem();
544
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
545
for (int i = 0; i < m_meshes.size(); ++i) {
546
MT_Transform trans = GetTransform(i);
548
float opengl_mat[16];
549
trans.getValue(opengl_mat);
552
glMultMatrixf(opengl_mat);
553
MT_Vector3 color(1.0,1.0,1.0);
554
if (i == m_current_object) {
555
color = MT_Vector3(1.0,0,0);
557
BSP_MeshDrawer::DrawMesh(m_meshes[i].Ref(),m_render_modes[i]);
562
m_window->swapBuffers();
569
const MT_Vector3 &min,
570
const MT_Vector3 &max
573
GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5}; /* Red diffuse light. */
574
GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
576
GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5}; /* Red diffuse light. */
577
GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */
579
/* Enable a single OpenGL light. */
581
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
582
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
584
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
585
glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
590
glEnable(GL_LIGHTING);
592
// make sure there is no back face culling.
593
// glDisable(GL_CULL_FACE);
595
// use two sided lighting model
596
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
598
/* Use depth buffering for hidden surface elimination. */
600
glEnable(GL_DEPTH_TEST);
602
/* Setup the view of the cube. */
604
glMatrixMode(GL_PROJECTION);
606
// center of the box + 3* depth of box
608
MT_Vector3 center = (min + max) * 0.5;
609
MT_Vector3 diag = max - min;
611
float depth = diag.length();
615
/* field of view in degree */ 40.0,
616
/* aspect ratio */ 1.0,
618
/* Z far */ distance * depth * 2
620
glMatrixMode(GL_MODELVIEW);
623
center.x(), center.y(), center.z() + distance*depth, //eye
624
center.x(), center.y(), center.z(), //center
626
); /* up is in positive Y direction */