|
Blender
V2.59
|
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