Blender V2.61 - r43446
|
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