diff options
Diffstat (limited to 'intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp')
-rwxr-xr-x | intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp | 656 |
1 files changed, 656 insertions, 0 deletions
diff --git a/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp new file mode 100755 index 00000000000..92e5198f139 --- /dev/null +++ b/intern/bsp/test/BSP_GhostTest/BSP_GhostTest3D.cpp @@ -0,0 +1,656 @@ +/** + * $Id$ + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +/** + +* $Id$ +* Copyright (C) 2001 NaN Technologies B.V. +*/ + +#if defined(WIN32) || defined(__APPLE__) +# ifdef WIN32 +# include <windows.h> +# include <GL/gl.h> +# include <GL/glu.h> +# else // WIN32 +# include <AGL/gl.h> +# endif // WIN32 +#else // defined(WIN32) || defined(__APPLE__) +# include <GL/gl.h> +# include <GL/glu.h> +#endif // defined(WIN32) || defined(__APPLE__) + + +#include "BSP_GhostTest3D.h" +#include "BSP_MeshDrawer.h" + +#include "GHOST_ISystem.h" +#include "GHOST_IWindow.h" + +#include "MT_Quaternion.h" +#include "MT_Transform.h" +#include "CSG_BooleanOps.h" + +#include <iostream> + + +using namespace std; + + +BSP_GhostTestApp3D:: +BSP_GhostTestApp3D( +) : + m_window(NULL), + m_system(NULL), + m_finish_me_off(false), + m_current_object(0) +{ + //nothing to do; +} + + void +BSP_GhostTestApp3D:: +SetMesh( + MEM_SmartPtr<BSP_TMesh> mesh +){ + m_meshes.push_back(mesh); + + BSP_RotationSetting rotation_setting; + BSP_TranslationSetting translation_setting; + + rotation_setting.m_angle_x = MT_Scalar(0); + rotation_setting.m_angle_y = MT_Scalar(0); + rotation_setting.m_moving = false; + rotation_setting.x_old = 0; + rotation_setting.y_old = 0; + + translation_setting.m_t_x = MT_Scalar(0); + translation_setting.m_t_y = MT_Scalar(0); + translation_setting.m_t_z = MT_Scalar(0); + translation_setting.m_moving = false; + translation_setting.x_old = 0; + translation_setting.y_old = 0; + + m_rotation_settings.push_back(rotation_setting); + m_translation_settings.push_back(translation_setting); + m_render_modes.push_back(e_wireframe_shaded); + m_scale_settings.push_back(MT_Scalar(1)); + +} + + void +BSP_GhostTestApp3D:: +Swap( + int i +){ + + if (!m_rotation_settings[i].m_moving && !m_translation_settings[i].m_moving) { + swap(m_meshes[i],m_meshes.back()); + swap(m_rotation_settings[i],m_rotation_settings.back()); + swap(m_translation_settings[i],m_translation_settings.back()); + swap(m_scale_settings[i],m_scale_settings.back()); + swap(m_render_modes[i],m_render_modes.back()); + } +} + + + + + + + MT_Transform +BSP_GhostTestApp3D:: +GetTransform( + int i +){ + + MT_Quaternion q_ax(MT_Vector3(0,1,0),m_rotation_settings[i].m_angle_x); + MT_Quaternion q_ay(MT_Vector3(1,0,0),m_rotation_settings[i].m_angle_y); + + MT_Point3 tr( + m_translation_settings[i].m_t_x, + m_translation_settings[i].m_t_y, + m_translation_settings[i].m_t_z + ); + + + MT_Matrix3x3 rotx(q_ax); + MT_Matrix3x3 roty(q_ay); + + MT_Matrix3x3 rot = rotx * roty; + + MT_Transform trans(tr,rot); + + MT_Transform scalet; + scalet.setIdentity(); + scalet.scale(m_scale_settings[i],m_scale_settings[i],m_scale_settings[i]); + + return trans * scalet; +} + + void +BSP_GhostTestApp3D:: +Operate( + int type +){ + + CSG_VertexIteratorDescriptor * vA = VertexIt_Construct(m_meshes[0],GetTransform(0)); + CSG_FaceIteratorDescriptor * fA = FaceIt_Construct(m_meshes[0]); + + CSG_VertexIteratorDescriptor * vB = VertexIt_Construct(m_meshes[1],GetTransform(1)); + CSG_FaceIteratorDescriptor * fB = FaceIt_Construct(m_meshes[1]); + + // describe properties. + + CSG_MeshPropertyDescriptor props; + props.mesh_property_flags = 0; + props.user_data_size = 0; + + CSG_BooleanOperation * op = CSG_NewBooleanFunction(); + props = CSG_DescibeOperands(op,props,props); + + CSG_PerformBooleanOperation(op,CSG_OperationType(type), + *fA,*vA,*fB,*vB + ); + + CSG_FaceIteratorDescriptor * out_f = CSG_OutputFaceDescriptor(op); + CSG_VertexIteratorDescriptor * out_v = CSG_OutputVertexDescriptor(op); + + MEM_SmartPtr<BSP_TMesh> new_mesh (BuildMesh(props,*out_f,*out_v)); + + // free stuff + + CSG_FreeVertexDescriptor(out_v); + CSG_FreeFaceDescriptor(out_f); + CSG_FreeBooleanOperation(op); + + op = NULL; + SetMesh(new_mesh); +} + + + void +BSP_GhostTestApp3D:: +UpdateFrame( +){ +if (m_window) { + + GHOST_Rect v_rect; + m_window->getClientBounds(v_rect); + + glViewport(0,0,v_rect.getWidth(),v_rect.getHeight()); + +} +} + + +MT_Vector3 +BSP_GhostTestApp3D:: +UnProject( + const MT_Vector3 & vec +) { + + GLint viewport[4]; + GLdouble mvmatrix[16],projmatrix[16]; + + glGetIntegerv(GL_VIEWPORT,viewport); + glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix); + glGetDoublev(GL_PROJECTION_MATRIX,projmatrix); + + GLdouble realy = viewport[3] - vec.y() - 1; + GLdouble outx,outy,outz; + + gluUnProject(vec.x(),realy,vec.z(),mvmatrix,projmatrix,viewport,&outx,&outy,&outz); + + return MT_Vector3(outx,outy,outz); +} + + + bool +BSP_GhostTestApp3D:: +InitApp( +){ + + // create a system and window with opengl + // rendering context. + + GHOST_TSuccess success = GHOST_ISystem::createSystem(); + if (success == GHOST_kFailure) return false; + + m_system = GHOST_ISystem::getSystem(); + if (m_system == NULL) return false; + + m_system->addEventConsumer(this); + + m_window = m_system->createWindow( + "GHOST crud3D!", + 100,100,640,480,GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL + ); + + if ( + m_window == NULL + ) { + m_system = NULL; + GHOST_ISystem::disposeSystem(); + return false; + } + + // make an opengl frustum for this wind + + MT_Vector3 min,max; + + min = m_meshes[0]->m_min; + max = m_meshes[0]->m_max; + InitOpenGl(min,max); + + return true; +} + + void +BSP_GhostTestApp3D:: +Run( +){ + if (m_system == NULL) { + return; + } + + while (!m_finish_me_off) { + m_system->processEvents(true); + m_system->dispatchEvents(); + }; +} + + bool +BSP_GhostTestApp3D:: +processEvent( + GHOST_IEvent* event +){ + + bool handled = false; + + switch(event->getType()) { + case GHOST_kEventWindowSize: + case GHOST_kEventWindowActivate: + UpdateFrame(); + case GHOST_kEventWindowUpdate: + DrawPolies(); + handled = true; + break; + case GHOST_kEventButtonDown: + { + int x,y; + m_system->getCursorPosition(x,y); + + int wx,wy; + m_window->screenToClient(x,y,wx,wy); + + GHOST_TButtonMask button = + static_cast<GHOST_TEventButtonData *>(event->getData())->button; + + if (button == GHOST_kButtonMaskLeft) { + m_rotation_settings[m_current_object].m_moving = true; + m_rotation_settings[m_current_object].x_old = x; + m_rotation_settings[m_current_object].y_old = y; + } else + if (button == GHOST_kButtonMaskRight) { + m_translation_settings[m_current_object].m_moving = true; + m_translation_settings[m_current_object].x_old = x; + m_translation_settings[m_current_object].y_old = y; + } else + + m_window->invalidate(); + handled = true; + break; + + } + + case GHOST_kEventButtonUp: + { + + GHOST_TButtonMask button = + static_cast<GHOST_TEventButtonData *>(event->getData())->button; + + if (button == GHOST_kButtonMaskLeft) { + m_rotation_settings[m_current_object].m_moving = false; + m_rotation_settings[m_current_object].x_old = 0; + m_rotation_settings[m_current_object].y_old = 0; + } else + if (button == GHOST_kButtonMaskRight) { + m_translation_settings[m_current_object].m_moving = false; + m_translation_settings[m_current_object].x_old; + m_translation_settings[m_current_object].y_old; + + } + m_window->invalidate(); + handled = true; + break; + + } + + case GHOST_kEventCursorMove: + { + int x,y; + m_system->getCursorPosition(x,y); + int wx,wy; + m_window->screenToClient(x,y,wx,wy); + + if (m_rotation_settings[m_current_object].m_moving) { + m_rotation_settings[m_current_object].m_angle_x = MT_Scalar(wx)/20; + m_rotation_settings[m_current_object].x_old = wx; + m_rotation_settings[m_current_object].m_angle_y = MT_Scalar(wy)/20; + m_rotation_settings[m_current_object].y_old = wy; + + m_window->invalidate(); + } + if (m_translation_settings[m_current_object].m_moving) { + + // project current objects bounding box centre into screen space. + // unproject mouse point into object space using z-value from + // projected bounding box centre. + + GHOST_Rect bounds; + m_window->getClientBounds(bounds); + + int w_h = bounds.getWidth(); + + y = w_h - wy; + + double mvmatrix[16]; + double projmatrix[16]; + GLint viewport[4]; + + double px, py, pz,sz; + + /* Get the matrices needed for gluUnProject */ + glGetIntegerv(GL_VIEWPORT, viewport); + glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); + glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); + + // work out the position of the end effector in screen space + + GLdouble ex,ey,ez; + + MT_Vector3 bbox_min, bbox_max; + + bbox_min = m_meshes[0]->m_min; + bbox_max = m_meshes[0]->m_max; + + MT_Vector3 bbox_centre = (bbox_min + bbox_max)/2; + + ex = bbox_centre.x(); + ey = bbox_centre.y(); + ez = bbox_centre.z(); + + gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz); + gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz); + + m_translation_settings[m_current_object].m_t_x = px; + m_translation_settings[m_current_object].m_t_y = py; + m_translation_settings[m_current_object].m_t_z = pz; + m_window->invalidate(); + + } + + handled = true; + break; + } + + case GHOST_kEventKeyDown : + { + GHOST_TEventKeyData *kd = + static_cast<GHOST_TEventKeyData *>(event->getData()); + + + switch(kd->key) { + case GHOST_kKeyI: + { + // now intersect meshes. + Operate(e_csg_intersection); + handled = true; + m_window->invalidate(); + break; + } + case GHOST_kKeyU: + { + Operate(e_csg_union); + handled = true; + m_window->invalidate(); + break; + } + case GHOST_kKeyD: + { + Operate(e_csg_difference); + handled = true; + m_window->invalidate(); + break; + } + + case GHOST_kKeyA: + { + + m_scale_settings[m_current_object] *= 1.1; + handled = true; + m_window->invalidate(); + break; + } + case GHOST_kKeyZ: + { + m_scale_settings[m_current_object] *= 0.8; + + handled = true; + m_window->invalidate(); + break; + } + + case GHOST_kKeyR: + + m_render_modes[m_current_object]++; + + if (m_render_modes[m_current_object] > e_last_render_mode) { + m_render_modes[m_current_object] = e_first_render_mode; + } + + handled = true; + m_window->invalidate(); + break; + + + + case GHOST_kKeyB: + handled = true; + m_window->invalidate(); + break; + + case GHOST_kKeyQ: + m_finish_me_off = true; + handled = true; + break; + + case GHOST_kKeyS: + Swap(m_current_object); + m_window->invalidate(); + handled = true; + break; + + case GHOST_kKeySpace: + + // increment the current object only if the object is not being + // manipulated. + if (! (m_rotation_settings[m_current_object].m_moving || m_translation_settings[m_current_object].m_moving)) { + m_current_object ++; + if (m_current_object >= m_meshes.size()) { + m_current_object = 0; + } + } + m_window->invalidate(); + + + handled = true; + break; + default : + break; + } + } + + default : + break; + } + + return handled; + +}; + +BSP_GhostTestApp3D:: +~BSP_GhostTestApp3D( +){ + + if (m_window) { + m_system->disposeWindow(m_window); + m_window = NULL; + GHOST_ISystem::disposeSystem(); + m_system = NULL; + } +}; + + void +BSP_GhostTestApp3D:: +DrawPolies( +){ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + for (int i = 0; i < m_meshes.size(); ++i) { + + MT_Transform trans = GetTransform(i); + + float opengl_mat[16]; + trans.getValue(opengl_mat); + + opengl_mat[14] -= 30; + + glPushMatrix(); + glLoadMatrixf(opengl_mat); + + MT_Vector3 color(1.0,1.0,1.0); + + if (i == m_current_object) { + color = MT_Vector3(1.0,0,0); + } + + BSP_MeshDrawer::DrawMesh(m_meshes[i].Ref(),m_render_modes[i]); + + glPopMatrix(); + } + + m_window->swapBuffers(); +} + + void +BSP_GhostTestApp3D:: +InitOpenGl( + const MT_Vector3 &min, + const MT_Vector3 &max +){ + + GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5}; /* Red diffuse light. */ + GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */ + + GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5}; /* Red diffuse light. */ + GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */ + + /* Enable a single OpenGL light. */ + glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0); + glLightfv(GL_LIGHT0, GL_POSITION, light_position0); + + glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1); + glLightfv(GL_LIGHT1, GL_POSITION, light_position1); + + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_LIGHTING); + + // make sure there is no back face culling. +// glDisable(GL_CULL_FACE); + + + // use two sided lighting model + + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE); + + /* Use depth buffering for hidden surface elimination. */ + glEnable(GL_DEPTH_TEST); + + /* Setup the view of the cube. */ + glMatrixMode(GL_PROJECTION); + + // centre of the box + 3* depth of box + + MT_Vector3 centre = (min + max) * 0.5; + MT_Vector3 diag = max - min; + + float depth = diag.length(); + float distance = 5; + + gluPerspective( + /* field of view in degree */ 40.0, + /* aspect ratio */ 1.0, + /* Z near */ 1.0, + /* Z far */ distance * depth * 2 + ); + glMatrixMode(GL_MODELVIEW); + + gluLookAt( + centre.x(), centre.y(), centre.z() + distance*depth, //eye + centre.x(), centre.y(), centre.z(), //centre + 0.0, 1.0, 0.); /* up is in positive Y direction */ + +} + + + + + + + + + + + + + + + + + + + + + |