Blender  V2.59
BSP_GhostTest3D.cpp
Go to the documentation of this file.
00001 
00034 #if defined(WIN32) || defined(__APPLE__)
00035 #       ifdef WIN32
00036 #               include <windows.h>
00037 #               include <GL/gl.h>
00038 #               include <GL/glu.h>
00039 #       else // WIN32
00040 #               include <AGL/gl.h>
00041 #       endif // WIN32
00042 #else // defined(WIN32) || defined(__APPLE__)
00043 #       include <GL/gl.h>
00044 #       include <GL/glu.h>
00045 #endif // defined(WIN32) || defined(__APPLE__)
00046 
00047 
00048 #include "BSP_GhostTest3D.h"
00049 #include "BSP_MeshDrawer.h"
00050 
00051 #include "GHOST_ISystem.h"
00052 #include "GHOST_IWindow.h"
00053 
00054 #include "MT_Quaternion.h"
00055 #include "MT_Transform.h"
00056 #include "CSG_BooleanOps.h"
00057 
00058 #include <iostream>
00059 
00060         int 
00061 EmptyInterpFunc(
00062         void *d1, 
00063         void * d2, 
00064         void *dnew, 
00065         float epsilon
00066 ){
00067         return 0;
00068 }
00069 
00070 
00071 
00072 using namespace std;
00073 
00074 
00075 BSP_GhostTestApp3D::
00076 BSP_GhostTestApp3D(
00077 ) :
00078         m_window(NULL),
00079         m_system(NULL),
00080         m_finish_me_off(false),
00081         m_current_object(0)
00082 {
00083         //nothing to do;
00084 }
00085 
00086         void
00087 BSP_GhostTestApp3D::
00088 SetMesh(
00089         MEM_SmartPtr<BSP_TMesh> mesh
00090 ){
00091         m_meshes.push_back(mesh);
00092 
00093         BSP_RotationSetting rotation_setting;
00094         BSP_TranslationSetting translation_setting;
00095 
00096         rotation_setting.m_angle_x = MT_Scalar(0);
00097         rotation_setting.m_angle_y = MT_Scalar(0);
00098         rotation_setting.m_moving = false;
00099         rotation_setting.x_old = 0;
00100         rotation_setting.y_old = 0;
00101 
00102         translation_setting.m_t_x = MT_Scalar(0);
00103         translation_setting.m_t_y = MT_Scalar(0);
00104         translation_setting.m_t_z = MT_Scalar(0);
00105         translation_setting.m_moving = false;
00106         translation_setting.x_old = 0;
00107         translation_setting.y_old = 0;
00108 
00109         m_rotation_settings.push_back(rotation_setting);
00110         m_translation_settings.push_back(translation_setting);
00111         m_render_modes.push_back(e_wireframe_shaded);
00112         m_scale_settings.push_back(MT_Scalar(1));
00113 
00114 }
00115 
00116         void
00117 BSP_GhostTestApp3D::
00118 Swap(
00119         int i
00120 ){
00121 
00122         if (!m_rotation_settings[i].m_moving && !m_translation_settings[i].m_moving) {
00123                 swap(m_meshes[i],m_meshes.back());
00124                 swap(m_rotation_settings[i],m_rotation_settings.back());
00125                 swap(m_translation_settings[i],m_translation_settings.back());
00126                 swap(m_scale_settings[i],m_scale_settings.back());
00127                 swap(m_render_modes[i],m_render_modes.back());
00128         }
00129 }
00130 
00131 
00132         MT_Transform
00133 BSP_GhostTestApp3D::
00134 GetTransform(
00135         int i
00136 ){
00137 
00138         MT_Quaternion q_ax(MT_Vector3(0,1,0),m_rotation_settings[i].m_angle_x);
00139         MT_Quaternion q_ay(MT_Vector3(1,0,0),m_rotation_settings[i].m_angle_y);
00140 
00141         MT_Point3 tr(
00142                 m_translation_settings[i].m_t_x,
00143                 m_translation_settings[i].m_t_y,
00144                 m_translation_settings[i].m_t_z
00145         );
00146         
00147 
00148         MT_Matrix3x3 rotx(q_ax);
00149         MT_Matrix3x3 roty(q_ay);
00150 
00151         MT_Matrix3x3 rot = rotx * roty;
00152 
00153         MT_Transform trans(tr,rot);
00154 
00155         MT_Transform scalet;
00156         scalet.setIdentity();
00157         scalet.scale(m_scale_settings[i],m_scale_settings[i],m_scale_settings[i]);
00158 
00159         return trans * scalet;
00160 }
00161 
00162         void
00163 BSP_GhostTestApp3D::
00164 Operate(
00165         int type
00166 ){
00167 
00168         CSG_VertexIteratorDescriptor * vA = VertexIt_Construct(m_meshes[0],GetTransform(0));
00169         CSG_FaceIteratorDescriptor * fA = FaceIt_Construct(m_meshes[0]);
00170                                                 
00171         CSG_VertexIteratorDescriptor * vB = VertexIt_Construct(m_meshes[1],GetTransform(1));
00172         CSG_FaceIteratorDescriptor * fB = FaceIt_Construct(m_meshes[1]);
00173 
00174         // describe properties.
00175 
00176         CSG_MeshPropertyDescriptor props;
00177         props.user_face_vertex_data_size = 0;
00178         props.user_data_size = 0;
00179 
00180         CSG_BooleanOperation * op =  CSG_NewBooleanFunction();
00181         props = CSG_DescibeOperands(op,props,props);
00182 
00183         CSG_PerformBooleanOperation(
00184                 op,CSG_OperationType(type),
00185                 *fA,*vA,*fB,*vB,EmptyInterpFunc
00186         );
00187 
00188         CSG_FaceIteratorDescriptor out_f;
00189         CSG_OutputFaceDescriptor(op,&out_f);
00190 
00191         CSG_VertexIteratorDescriptor out_v;
00192         CSG_OutputVertexDescriptor(op,&out_v);
00193 
00194         MEM_SmartPtr<BSP_TMesh> new_mesh (BuildMesh(props,out_f,out_v));
00195 
00196         // free stuff
00197 
00198         CSG_FreeVertexDescriptor(&out_v);
00199         CSG_FreeFaceDescriptor(&out_f);
00200         CSG_FreeBooleanOperation(op);
00201 
00202         op = NULL;
00203         SetMesh(new_mesh);
00204 }
00205 
00206 
00207         void 
00208 BSP_GhostTestApp3D::
00209 UpdateFrame(
00210 ){
00211 if (m_window) {
00212 
00213         GHOST_Rect v_rect;
00214         m_window->getClientBounds(v_rect);
00215         
00216         glViewport(0,0,v_rect.getWidth(),v_rect.getHeight());
00217         
00218 }
00219 }
00220 
00221 
00222 MT_Vector3
00223 BSP_GhostTestApp3D::
00224 UnProject(
00225         const MT_Vector3 & vec
00226 ) {
00227 
00228         GLint viewport[4];
00229         GLdouble mvmatrix[16],projmatrix[16];
00230 
00231         glGetIntegerv(GL_VIEWPORT,viewport);
00232         glGetDoublev(GL_MODELVIEW_MATRIX,mvmatrix);
00233         glGetDoublev(GL_PROJECTION_MATRIX,projmatrix);
00234         
00235         GLdouble realy = viewport[3] - vec.y() - 1;
00236         GLdouble outx,outy,outz;
00237 
00238         gluUnProject(vec.x(),realy,vec.z(),mvmatrix,projmatrix,viewport,&outx,&outy,&outz);
00239 
00240         return MT_Vector3(outx,outy,outz);
00241 }
00242 
00243 
00244         bool
00245 BSP_GhostTestApp3D::
00246 InitApp(
00247 ){
00248 
00249         // create a system and window with opengl
00250         // rendering context.
00251 
00252         GHOST_TSuccess success = GHOST_ISystem::createSystem();
00253         if (success == GHOST_kFailure) return false;
00254 
00255         m_system = GHOST_ISystem::getSystem();
00256         if (m_system == NULL) return false;
00257 
00258         m_system->addEventConsumer(this);
00259         
00260         m_window = m_system->createWindow(
00261                 "GHOST crud3D!",
00262                 100,100,512,512,GHOST_kWindowStateNormal,
00263                 GHOST_kDrawingContextTypeOpenGL,false
00264         );
00265 
00266         if (
00267                 m_window == NULL
00268         ) {
00269                 m_system = NULL;
00270                 GHOST_ISystem::disposeSystem();
00271                 return false;
00272         }
00273 
00274         // make an opengl frustum for this wind
00275 
00276         MT_Vector3 min,max;
00277 
00278         min = m_meshes[0]->m_min;
00279         max = m_meshes[0]->m_max;
00280         InitOpenGl(min,max);
00281 
00282         return true;
00283 }
00284 
00285         void
00286 BSP_GhostTestApp3D::
00287 Run(
00288 ){
00289         if (m_system == NULL) {
00290                 return;
00291         }
00292 
00293         while (!m_finish_me_off) {
00294                 m_system->processEvents(true);
00295                 m_system->dispatchEvents();
00296         };
00297 }
00298 
00299         bool 
00300 BSP_GhostTestApp3D::
00301 processEvent(
00302         GHOST_IEvent* event
00303 ){
00304 
00305         bool handled = false;
00306 
00307         switch(event->getType()) {
00308                 case GHOST_kEventWindowSize:
00309                 case GHOST_kEventWindowActivate:
00310                         UpdateFrame();
00311                 case GHOST_kEventWindowUpdate:
00312                         DrawPolies();
00313                         handled = true;
00314                         break;
00315                 case GHOST_kEventButtonDown:
00316                 {
00317                         int x,y;
00318                         m_system->getCursorPosition(x,y);
00319 
00320 
00321                         int wx,wy;
00322                         m_window->screenToClient(x,y,wx,wy);
00323 
00324                         GHOST_TButtonMask button = 
00325                                 static_cast<GHOST_TEventButtonData *>(event->getData())->button;
00326                         
00327                         if (button == GHOST_kButtonMaskLeft) {
00328                                 m_rotation_settings[m_current_object].m_moving = true;
00329                                 m_rotation_settings[m_current_object].x_old = x;
00330                                 m_rotation_settings[m_current_object].y_old = y;        
00331                         } else 
00332                         if (button == GHOST_kButtonMaskRight) {
00333                                 m_translation_settings[m_current_object].m_moving = true;
00334                                 m_translation_settings[m_current_object].x_old = x;
00335                                 m_translation_settings[m_current_object].y_old = y;     
00336                         } else 
00337                 
00338                         m_window->invalidate();
00339                         handled = true;
00340                         break;
00341 
00342                 }
00343 
00344                 case GHOST_kEventButtonUp:
00345                 {
00346 
00347                         GHOST_TButtonMask button = 
00348                                 static_cast<GHOST_TEventButtonData *>(event->getData())->button;
00349                         
00350                         if (button == GHOST_kButtonMaskLeft) {
00351                                 m_rotation_settings[m_current_object].m_moving = false;
00352                                 m_rotation_settings[m_current_object].x_old = 0;
00353                                 m_rotation_settings[m_current_object].y_old = 0;
00354 
00355                 } else 
00356                         if (button == GHOST_kButtonMaskRight) {
00357                                 m_translation_settings[m_current_object].m_moving = false;
00358                                 m_translation_settings[m_current_object].x_old;
00359                                 m_translation_settings[m_current_object].y_old;
00360 
00361                         }
00362                         m_window->invalidate();
00363                         handled = true;
00364                         break;
00365 
00366                 }
00367 
00368                 case GHOST_kEventCursorMove:
00369                 {               
00370                         int x,y;
00371                         m_system->getCursorPosition(x,y);       
00372                         int wx,wy;
00373                         m_window->screenToClient(x,y,wx,wy);
00374 
00375                         if (m_rotation_settings[m_current_object].m_moving) {
00376                                 m_rotation_settings[m_current_object].m_angle_x = MT_Scalar(wx)/20;
00377                                 m_rotation_settings[m_current_object].x_old = wx;
00378                                 m_rotation_settings[m_current_object].m_angle_y = MT_Scalar(wy)/20;
00379                                 m_rotation_settings[m_current_object].y_old = wy;
00380 
00381                                 m_window->invalidate();
00382                         }
00383                         if (m_translation_settings[m_current_object].m_moving) {
00384 
00385                                 // project current objects bounding box center into screen space.
00386                                 // unproject mouse point into object space using z-value from 
00387                                 // projected bounding box center.
00388 
00389                                 GHOST_Rect bounds;
00390                                 m_window->getClientBounds(bounds);
00391 
00392                                 int w_h = bounds.getHeight();
00393 
00394                                 y = w_h - wy;
00395                                 x = wx;
00396 
00397                                 double mvmatrix[16];
00398                                 double projmatrix[16];
00399                                 GLint viewport[4];
00400 
00401                                 double px, py, pz,sz;
00402 
00403                                 /* Get the matrices needed for gluUnProject */
00404                                 glGetIntegerv(GL_VIEWPORT, viewport);
00405                                 glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
00406                                 glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
00407 
00408                                 // work out the position of the end effector in screen space
00409 
00410                                 GLdouble ex,ey,ez;
00411 
00412                                 ex = m_translation_settings[m_current_object].m_t_x;
00413                                 ey = m_translation_settings[m_current_object].m_t_y;
00414                                 ez = m_translation_settings[m_current_object].m_t_z;
00415 
00416                                 gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz);
00417                                 gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz);
00418 
00419                                 m_translation_settings[m_current_object].m_t_x = px;
00420                                 m_translation_settings[m_current_object].m_t_y = py;
00421                                 m_translation_settings[m_current_object].m_t_z = pz;
00422                                 m_window->invalidate();
00423 
00424                         }               
00425         
00426                         handled = true;
00427                         break;
00428                 }
00429 
00430                 case GHOST_kEventKeyDown :
00431                 {
00432                         GHOST_TEventKeyData *kd = 
00433                                 static_cast<GHOST_TEventKeyData *>(event->getData());
00434 
00435 
00436                         switch(kd->key) {
00437                                 case GHOST_kKeyI:
00438                                 {               
00439                                         // now intersect meshes.
00440                                         Operate(e_csg_intersection);
00441                                         handled = true;
00442                                         m_window->invalidate();
00443                                         break;                                  
00444                                 }
00445                                 case GHOST_kKeyU:       
00446                                 {               
00447                                         Operate(e_csg_union);
00448                                         handled = true;
00449                                         m_window->invalidate();
00450                                         break;                                  
00451                                 }
00452                                 case GHOST_kKeyD:       
00453                                 {               
00454                                         Operate(e_csg_difference);
00455                                         handled = true;
00456                                         m_window->invalidate();
00457                                         break;                                  
00458                                 }
00459 
00460                                 case GHOST_kKeyA:
00461                                 {
00462 
00463                                         m_scale_settings[m_current_object] *= 1.1;
00464                                         handled = true;
00465                                         m_window->invalidate();
00466                                         break;                                  
00467                                 }
00468                                 case GHOST_kKeyZ:
00469                                 {
00470                                         m_scale_settings[m_current_object] *= 0.8;
00471 
00472                                         handled = true;
00473                                         m_window->invalidate();
00474                                         break;                                  
00475                                 }
00476 
00477                                 case GHOST_kKeyR:
00478                                         m_render_modes[m_current_object]++;
00479                                         if (m_render_modes[m_current_object] > e_last_render_mode) {
00480                                                 m_render_modes[m_current_object] = e_first_render_mode;
00481                                         }
00482                                         handled = true;
00483                                         m_window->invalidate();
00484                                         break;                                  
00485 
00486                                 case GHOST_kKeyB:
00487                                         handled = true;
00488                                         m_window->invalidate();
00489                                         break;                                  
00490 
00491                                 case GHOST_kKeyQ:
00492                                         m_finish_me_off = true;
00493                                         handled = true;
00494                                         break;
00495 
00496                                 case GHOST_kKeyS:
00497                                         Swap(m_current_object);
00498                                         m_window->invalidate();
00499                                         handled = true;
00500                                         break;
00501 
00502                                 case GHOST_kKeySpace:
00503 
00504                                         // increment the current object only if the object is not being
00505                                         // manipulated.
00506                                         if (! (m_rotation_settings[m_current_object].m_moving || m_translation_settings[m_current_object].m_moving)) {
00507                                                 m_current_object ++;
00508                                                 if (m_current_object >= m_meshes.size()) {
00509                                                         m_current_object = 0;
00510 
00511                                                 }
00512                                         }
00513                                         m_window->invalidate();
00514                                         handled = true;
00515                                         break;
00516                                 default :
00517                                         break;
00518                         }
00519                 }                       
00520 
00521                 default :
00522                         break;
00523         }
00524         return handled;
00525 };
00526 
00527 BSP_GhostTestApp3D::
00528 ~BSP_GhostTestApp3D(
00529 ){
00530 
00531         if (m_window) {
00532                 m_system->disposeWindow(m_window);
00533                 m_window = NULL;
00534                 GHOST_ISystem::disposeSystem();
00535                 m_system = NULL;
00536         }
00537 };
00538 
00539         
00540 
00541         void
00542 BSP_GhostTestApp3D::
00543 DrawPolies(
00544 ){
00545 
00546         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00547         for (int i = 0; i < m_meshes.size(); ++i) {
00548                 MT_Transform trans = GetTransform(i);
00549 
00550                 float opengl_mat[16];
00551                 trans.getValue(opengl_mat);
00552 
00553                 glPushMatrix();
00554                 glMultMatrixf(opengl_mat);
00555                 MT_Vector3 color(1.0,1.0,1.0);
00556                 if (i == m_current_object) {
00557                         color = MT_Vector3(1.0,0,0);
00558                 }
00559                 BSP_MeshDrawer::DrawMesh(m_meshes[i].Ref(),m_render_modes[i]);
00560 
00561                 glPopMatrix();  
00562         }
00563 
00564         m_window->swapBuffers();
00565 
00566 }
00567 
00568         void
00569 BSP_GhostTestApp3D::
00570 InitOpenGl(
00571         const MT_Vector3 &min,
00572         const MT_Vector3 &max
00573 ){
00574 
00575         GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 0.5};  /* Red diffuse light. */
00576         GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0};  /* Infinite light location. */
00577 
00578         GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 0.5};  /* Red diffuse light. */
00579         GLfloat light_position1[] = {1.0, 0, 0, 0.0};  /* Infinite light location. */
00580 
00581         /* Enable a single OpenGL light. */
00582 
00583         glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
00584         glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
00585 
00586         glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
00587         glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
00588 
00589 
00590         glEnable(GL_LIGHT0);
00591         glEnable(GL_LIGHT1);
00592         glEnable(GL_LIGHTING);
00593 
00594         // make sure there is no back face culling.
00595         //      glDisable(GL_CULL_FACE);
00596 
00597         // use two sided lighting model
00598         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
00599 
00600         /* Use depth buffering for hidden surface elimination. */
00601 
00602         glEnable(GL_DEPTH_TEST);
00603 
00604         /* Setup the view of the cube. */
00605 
00606         glMatrixMode(GL_PROJECTION);
00607 
00608         // center of the box + 3* depth of box
00609 
00610         MT_Vector3 center = (min + max) * 0.5;
00611         MT_Vector3 diag = max - min;
00612 
00613         float depth = diag.length();
00614         float distance = 5;
00615 
00616         gluPerspective( 
00617         /* field of view in degree */ 40.0,
00618         /* aspect ratio */ 1.0,
00619         /* Z near */ 1.0, 
00620         /* Z far */ distance * depth * 2
00621         );
00622         glMatrixMode(GL_MODELVIEW);     
00623 
00624         gluLookAt(
00625                 center.x(), center.y(), center.z() + distance*depth, //eye  
00626                 center.x(), center.y(), center.z(), //center      
00627                 0.0, 1.0, 0.
00628         );      /* up is in positive Y direction */
00629 
00630 }       
00631 
00632                         
00633 
00634 
00635 
00636 
00637         
00638         
00639 
00640         
00641 
00642 
00643 
00644 
00645 
00646 
00647 
00648         
00649 
00650 
00651