Blender V2.61 - r43446

BSP_GhostTest3D.cpp

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