1 /* 2 * Copyright 2008 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Alexandre Deckner 7 * 8 */ 9 10 /* 11 * Original Be Sample source modified to use a quaternion for the object's orientation 12 */ 13 14 /* 15 Copyright 1999, Be Incorporated. All Rights Reserved. 16 This file may be used under the terms of the Be Sample Code License. 17 */ 18 19 #include "ObjectView.h" 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 24 #include <InterfaceKit.h> 25 #include <FindDirectory.h> 26 27 #include "FPS.h" 28 #include "GLObject.h" 29 #include "ResScroll.h" 30 31 #define teapotData "teapot.data" 32 char teapotPath[PATH_MAX]; 33 34 float displayScale = 1.0; 35 float depthOfView = 30.0; 36 float zRatio = 10.0; 37 38 float white[3] = {1.0, 1.0, 1.0}; 39 float dimWhite[3] = {0.25, 0.25, 0.25}; 40 float black[3] = {0.0, 0.0, 0.0}; 41 float foggy[3] = {0.4, 0.4, 0.4}; 42 float blue[3] = {0.0, 0.0, 1.0}; 43 float dimBlue[3] = {0.0, 0.0, 0.5}; 44 float yellow[3] = {1.0, 1.0, 0.0}; 45 float dimYellow[3] = {0.5, 0.5, 0.0}; 46 float green[3] = {0.0, 1.0, 0.0}; 47 float dimGreen[3] = {0.0, 0.5, 0.0}; 48 float red[3] = {1.0, 0.0, 0.0}; 49 50 float* bgColor = black; 51 52 53 struct light { 54 float *ambient; 55 float *diffuse; 56 float *specular; 57 }; 58 59 60 light lights[] = { 61 {NULL, NULL, NULL}, 62 {dimWhite, white, white}, 63 {dimWhite, yellow, yellow}, 64 {dimWhite, red, red}, 65 {dimWhite, blue, blue}, 66 {dimWhite, green, green} 67 }; 68 69 70 71 long 72 signalEvent(sem_id event) 73 { 74 long c; 75 get_sem_count(event,&c); 76 if (c < 0) 77 release_sem_etc(event,-c,0); 78 79 return 0; 80 } 81 82 83 long 84 setEvent(sem_id event) 85 { 86 long c; 87 get_sem_count(event,&c); 88 if (c < 0) 89 release_sem_etc(event,-c,0); 90 91 return 0; 92 } 93 94 95 long 96 waitEvent(sem_id event) 97 { 98 acquire_sem(event); 99 100 long c; 101 get_sem_count(event,&c); 102 if (c > 0) 103 acquire_sem_etc(event,c,0,0); 104 105 return 0; 106 } 107 108 109 static int32 110 simonThread(void* cookie) 111 { 112 ObjectView* objectView = reinterpret_cast<ObjectView*>(cookie); 113 114 int noPause = 0; 115 while (acquire_sem_etc(objectView->quittingSem, 1, B_TIMEOUT, 0) == B_NO_ERROR) { 116 if (objectView->SpinIt()) { 117 objectView->DrawFrame(noPause); 118 release_sem(objectView->quittingSem); 119 noPause = 1; 120 } else { 121 release_sem(objectView->quittingSem); 122 noPause = 0; 123 waitEvent(objectView->drawEvent); 124 } 125 } 126 return 0; 127 } 128 129 130 ObjectView::ObjectView(BRect rect, char *name, ulong resizingMode, ulong options) 131 : BGLView(rect, name, resizingMode, 0, options), 132 fHistEntries(0), 133 fOldestEntry(0), 134 fFps(true), 135 fLastGouraud(true), 136 fGouraud(true), 137 fLastZbuf(true), 138 fZbuf(true), 139 fLastCulling(true), 140 fCulling(true), 141 fLastLighting(true), 142 fLighting(true), 143 fLastFilled(true), 144 fFilled(true), 145 fLastPersp(false), 146 fPersp(false), 147 fLastTextured(false), 148 fTextured(false), 149 fLastFog(false), 150 fFog(false), 151 fForceRedraw(false), 152 fLastYXRatio(1), 153 fYxRatio(1) 154 { 155 fTrackingInfo.isTracking = false; 156 fTrackingInfo.pickedObject = NULL; 157 fTrackingInfo.buttons = 0; 158 fTrackingInfo.lastX = 0.0f; 159 fTrackingInfo.lastY = 0.0f; 160 fTrackingInfo.lastDx = 0.0f; 161 fTrackingInfo.lastDy = 0.0f; 162 163 fLastObjectDistance = fObjectDistance = depthOfView / 8; 164 quittingSem = create_sem(1, "quitting sem"); 165 drawEvent = create_sem(0, "draw event"); 166 167 char findDir[PATH_MAX]; 168 find_directory(B_SYSTEM_DATA_DIRECTORY, -1, true, findDir, PATH_MAX); 169 sprintf(teapotPath, "%s/%s", findDir, teapotData); 170 fObjListLock.Lock(); 171 fObjects.AddItem(new TriangleObject(this, teapotPath)); 172 fObjListLock.Unlock(); 173 } 174 175 176 ObjectView::~ObjectView() 177 { 178 delete_sem(quittingSem); 179 delete_sem(drawEvent); 180 } 181 182 183 void 184 ObjectView::AttachedToWindow() 185 { 186 float position[] = {0.0, 3.0, 3.0, 0.0}; 187 float position1[] = {-3.0, -3.0, 3.0, 0.0}; 188 float position2[] = {3.0, 0.0, 0.0, 0.0}; 189 float local_view[] = {0.0, 0.0}; 190 // float ambient[] = {0.1745, 0.03175, 0.03175}; 191 // float diffuse[] = {0.61424, 0.10136, 0.10136}; 192 // float specular[] = {0.727811, 0.626959, 0.626959}; 193 // rgb_color black = {0, 0, 0, 255}; 194 BRect bounds = Bounds(); 195 196 BGLView::AttachedToWindow(); 197 Window()->SetPulseRate(100000); 198 199 LockGL(); 200 201 glEnable(GL_DITHER); 202 glEnable(GL_CULL_FACE); 203 glCullFace(GL_BACK); 204 glDepthFunc(GL_LESS); 205 206 glShadeModel(GL_SMOOTH); 207 208 glLightfv(GL_LIGHT0, GL_POSITION, position); 209 glLightfv(GL_LIGHT0 + 1, GL_POSITION, position1); 210 glLightfv(GL_LIGHT0 + 2, GL_POSITION, position2); 211 glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view); 212 213 glEnable(GL_LIGHT0); 214 glLightfv(GL_LIGHT0, GL_SPECULAR, lights[lightWhite].specular); 215 glLightfv(GL_LIGHT0, GL_DIFFUSE,lights[lightWhite].diffuse); 216 glLightfv(GL_LIGHT0, GL_AMBIENT,lights[lightWhite].ambient); 217 glEnable(GL_LIGHT1); 218 glLightfv(GL_LIGHT1, GL_SPECULAR, lights[lightBlue].specular); 219 glLightfv(GL_LIGHT1, GL_DIFFUSE,lights[lightBlue].diffuse); 220 glLightfv(GL_LIGHT1, GL_AMBIENT,lights[lightBlue].ambient); 221 222 glFrontFace(GL_CW); 223 glEnable(GL_LIGHTING); 224 glEnable(GL_AUTO_NORMAL); 225 glEnable(GL_NORMALIZE); 226 227 glMaterialf(GL_FRONT, GL_SHININESS, 0.6 * 128.0); 228 229 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0); 230 glColor3f(1.0, 1.0, 1.0); 231 232 glViewport(0, 0, (GLint)bounds.IntegerWidth() + 1, 233 (GLint)bounds.IntegerHeight() + 1); 234 glMatrixMode(GL_PROJECTION); 235 glLoadIdentity(); 236 237 float scale = displayScale; 238 glOrtho(-scale, scale, -scale, scale, -scale * depthOfView, 239 scale * depthOfView); 240 glMatrixMode(GL_MODELVIEW); 241 glLoadIdentity(); 242 243 UnlockGL(); 244 245 fDrawThread = spawn_thread(simonThread, "Simon", B_NORMAL_PRIORITY, this); 246 resume_thread(fDrawThread); 247 fForceRedraw = true; 248 setEvent(drawEvent); 249 } 250 251 252 void 253 ObjectView::DetachedFromWindow() 254 { 255 BGLView::DetachedFromWindow(); 256 257 long dummy; 258 long locks = 0; 259 260 while (Window()->IsLocked()) { 261 locks++; 262 Window()->Unlock(); 263 } 264 265 acquire_sem(quittingSem); 266 release_sem(drawEvent); 267 wait_for_thread(fDrawThread, &dummy); 268 release_sem(quittingSem); 269 270 while (locks--) 271 Window()->Lock(); 272 } 273 274 275 void 276 ObjectView::Pulse() 277 { 278 Window()->Lock(); 279 BRect parentBounds = Parent()->Bounds(); 280 BRect bounds = Bounds(); 281 parentBounds.OffsetTo(0, 0); 282 bounds.OffsetTo(0, 0); 283 if (bounds != parentBounds) { 284 ResizeTo(parentBounds.right - parentBounds.left, 285 parentBounds.bottom - parentBounds.top); 286 } 287 Window()->Unlock(); 288 } 289 290 291 void 292 ObjectView::MessageReceived(BMessage* msg) 293 { 294 BMenuItem* item = NULL; 295 bool toggleItem = false; 296 297 switch (msg->what) { 298 case kMsgFPS: 299 fFps = (fFps) ? false : true; 300 msg->FindPointer("source", reinterpret_cast<void**>(&item)); 301 item->SetMarked(fFps); 302 fForceRedraw = true; 303 setEvent(drawEvent); 304 break; 305 case kMsgAddModel: 306 fObjListLock.Lock(); 307 fObjects.AddItem(new TriangleObject(this, teapotPath)); 308 fObjListLock.Unlock(); 309 setEvent(drawEvent); 310 break; 311 case kMsgLights: 312 { 313 msg->FindPointer("source", reinterpret_cast<void**>(&item)); 314 long lightNum = msg->FindInt32("num"); 315 long color = msg->FindInt32("color"); 316 BMenu *menu = item->Menu(); 317 long index = menu->IndexOf(item); 318 menu->ItemAt(index)->SetMarked(true); 319 for (int i = 0; i < menu->CountItems(); i++) { 320 if (i != index) 321 menu->ItemAt(i)->SetMarked(false); 322 } 323 324 LockGL(); 325 if (color != lightNone) { 326 glEnable(GL_LIGHT0 + lightNum - 1); 327 glLightfv(GL_LIGHT0 + lightNum - 1, GL_SPECULAR, 328 lights[color].specular); 329 glLightfv(GL_LIGHT0 + lightNum - 1, GL_DIFFUSE, 330 lights[color].diffuse); 331 glLightfv(GL_LIGHT0 + lightNum - 1, GL_AMBIENT, 332 lights[color].ambient); 333 } else { 334 glDisable(GL_LIGHT0 + lightNum - 1); 335 } 336 UnlockGL(); 337 fForceRedraw = true; 338 setEvent(drawEvent); 339 break; 340 } 341 case kMsgGouraud: 342 fGouraud = !fGouraud; 343 toggleItem = true; 344 break; 345 case kMsgZBuffer: 346 fZbuf = !fZbuf; 347 toggleItem = true; 348 break; 349 case kMsgCulling: 350 fCulling = !fCulling; 351 toggleItem = true; 352 break; 353 case kMsgLighting: 354 fLighting = !fLighting; 355 toggleItem = true; 356 break; 357 case kMsgFilled: 358 fFilled = !fFilled; 359 toggleItem = true; 360 break; 361 case kMsgPerspective: 362 fPersp = !fPersp; 363 toggleItem = true; 364 break; 365 case kMsgFog: 366 fFog = !fFog; 367 toggleItem = true; 368 break; 369 } 370 371 if (toggleItem && msg->FindPointer("source", reinterpret_cast<void**>(&item)) == B_OK){ 372 item->SetMarked(!item->IsMarked()); 373 setEvent(drawEvent); 374 } 375 376 BGLView::MessageReceived(msg); 377 } 378 379 380 int 381 ObjectView::ObjectAtPoint(const BPoint &point) 382 { 383 LockGL(); 384 glShadeModel(GL_FLAT); 385 glDisable(GL_LIGHTING); 386 glDisable(GL_FOG); 387 glClearColor(black[0], black[1], black[2], 1.0); 388 glClear(GL_COLOR_BUFFER_BIT | (fZbuf ? GL_DEPTH_BUFFER_BIT : 0)); 389 390 float idColor[3]; 391 idColor[1] = idColor[2] = 0; 392 for (int i = 0; i < fObjects.CountItems(); i++) { 393 // to take into account 16 bits colorspaces, 394 // only use the 5 highest bits of the red channel 395 idColor[0] = (255 - (i << 3)) / 255.0; 396 reinterpret_cast<GLObject*>(fObjects.ItemAt(i))->Draw(true, idColor); 397 } 398 glReadBuffer(GL_BACK); 399 uchar pixel[256]; 400 glReadPixels((GLint)point.x, (GLint)(Bounds().bottom - point.y), 1, 1, 401 GL_RGB, GL_UNSIGNED_BYTE, pixel); 402 int objNum = pixel[0]; 403 objNum = (255 - objNum) >> 3; 404 405 EnforceState(); 406 UnlockGL(); 407 408 return objNum; 409 } 410 411 412 void 413 ObjectView::MouseDown(BPoint point) 414 { 415 GLObject* object = NULL; 416 417 BMessage *msg = Window()->CurrentMessage(); 418 uint32 buttons = msg->FindInt32("buttons"); 419 object = reinterpret_cast<GLObject*>(fObjects.ItemAt(ObjectAtPoint(point))); 420 421 if (object != NULL){ 422 if (buttons == B_PRIMARY_MOUSE_BUTTON || buttons == B_SECONDARY_MOUSE_BUTTON) { 423 fTrackingInfo.pickedObject = object; 424 fTrackingInfo.buttons = buttons; 425 fTrackingInfo.isTracking = true; 426 fTrackingInfo.lastX = point.x; 427 fTrackingInfo.lastY = point.y; 428 fTrackingInfo.lastDx = 0.0f; 429 fTrackingInfo.lastDy = 0.0f; 430 fTrackingInfo.pickedObject->Spin(0.0f, 0.0f); 431 432 433 SetMouseEventMask(B_POINTER_EVENTS, 434 B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY); 435 } else { 436 ConvertToScreen(&point); 437 object->MenuInvoked(point); 438 } 439 } 440 } 441 442 443 void 444 ObjectView::MouseUp(BPoint point) 445 { 446 if (fTrackingInfo.isTracking) { 447 448 //spin the teapot on release, TODO: use a marching sum and divide by time 449 if (fTrackingInfo.buttons == B_PRIMARY_MOUSE_BUTTON 450 && fTrackingInfo.pickedObject != NULL 451 && (fabs(fTrackingInfo.lastDx) > 1.0f 452 || fabs(fTrackingInfo.lastDy) > 1.0f) ) { 453 454 fTrackingInfo.pickedObject->Spin(0.5f * fTrackingInfo.lastDy, 0.5f * fTrackingInfo.lastDx); 455 456 setEvent(drawEvent); 457 } 458 459 //stop tracking 460 fTrackingInfo.isTracking = false; 461 fTrackingInfo.buttons = 0; 462 fTrackingInfo.pickedObject = NULL; 463 fTrackingInfo.lastX = 0.0f; 464 fTrackingInfo.lastY = 0.0f; 465 fTrackingInfo.lastDx = 0.0f; 466 fTrackingInfo.lastDy = 0.0f; 467 } 468 } 469 470 471 void 472 ObjectView::MouseMoved(BPoint point, uint32 transit, const BMessage *msg) 473 { 474 if (fTrackingInfo.isTracking && fTrackingInfo.pickedObject != NULL) { 475 476 float dx = point.x - fTrackingInfo.lastX; 477 float dy = point.y - fTrackingInfo.lastY; 478 fTrackingInfo.lastX = point.x; 479 fTrackingInfo.lastY = point.y; 480 481 if (fTrackingInfo.buttons == B_PRIMARY_MOUSE_BUTTON) { 482 483 fTrackingInfo.pickedObject->Spin(0.0f, 0.0f); 484 fTrackingInfo.pickedObject->RotateWorldSpace(dx,dy); 485 fTrackingInfo.lastDx = dx; 486 fTrackingInfo.lastDy = dy; 487 488 setEvent(drawEvent); 489 490 } else if (fTrackingInfo.buttons == B_SECONDARY_MOUSE_BUTTON) { 491 492 float xinc = (dx * 2 * displayScale / Bounds().Width()); 493 float yinc = (-dy * 2 * displayScale / Bounds().Height()); 494 float zinc = 0; 495 496 if (fPersp) { 497 zinc = yinc * (fTrackingInfo.pickedObject->z / displayScale); 498 xinc *= -(fTrackingInfo.pickedObject->z * 4 / zRatio); 499 yinc *= -(fTrackingInfo.pickedObject->z * 4 / zRatio); 500 } 501 502 fTrackingInfo.pickedObject->x += xinc; 503 if (modifiers() & B_SHIFT_KEY) 504 fTrackingInfo.pickedObject->z += zinc; 505 else 506 fTrackingInfo.pickedObject->y += yinc; 507 508 fForceRedraw = true; 509 setEvent(drawEvent); 510 } 511 } 512 } 513 514 515 void 516 ObjectView::FrameResized(float width, float height) 517 { 518 LockGL(); 519 520 BGLView::FrameResized(width, height); 521 522 width = Bounds().Width(); 523 height = Bounds().Height(); 524 fYxRatio = height / width; 525 glViewport(0, 0, (GLint)width + 1, (GLint)height + 1); 526 527 // To prevent weird buffer contents 528 glClear(GL_COLOR_BUFFER_BIT); 529 530 glMatrixMode(GL_PROJECTION); 531 glLoadIdentity(); 532 float scale = displayScale; 533 534 if (fPersp) { 535 gluPerspective(60, 1.0 / fYxRatio, 0.15, 120); 536 } else { 537 if (fYxRatio < 1) { 538 glOrtho(-scale / fYxRatio, scale / fYxRatio, -scale, scale, -1.0, 539 depthOfView * 4); 540 } else { 541 glOrtho(-scale, scale, -scale * fYxRatio, scale * fYxRatio, -1.0, 542 depthOfView * 4); 543 } 544 } 545 546 fLastYXRatio = fYxRatio; 547 548 glMatrixMode(GL_MODELVIEW); 549 550 UnlockGL(); 551 552 fForceRedraw = true; 553 setEvent(drawEvent); 554 } 555 556 557 bool 558 ObjectView::RepositionView() 559 { 560 if (!(fPersp != fLastPersp) && 561 !(fLastObjectDistance != fObjectDistance) && 562 !(fLastYXRatio != fYxRatio)) { 563 return false; 564 } 565 566 LockGL(); 567 568 glMatrixMode(GL_PROJECTION); 569 glLoadIdentity(); 570 float scale = displayScale; 571 572 if (fPersp) { 573 gluPerspective(60, 1.0 / fYxRatio, 0.15, 120); 574 } else { 575 if (fYxRatio < 1) { 576 glOrtho(-scale / fYxRatio, scale / fYxRatio, -scale, scale, -1.0, 577 depthOfView * 4); 578 } else { 579 glOrtho(-scale, scale, -scale * fYxRatio, scale * fYxRatio, -1.0, 580 depthOfView * 4); 581 } 582 } 583 584 glMatrixMode(GL_MODELVIEW); 585 586 UnlockGL(); 587 588 fLastObjectDistance = fObjectDistance; 589 fLastPersp = fPersp; 590 fLastYXRatio = fYxRatio; 591 return true; 592 } 593 594 595 void 596 ObjectView::EnforceState() 597 { 598 glShadeModel(fGouraud ? GL_SMOOTH : GL_FLAT); 599 600 if (fZbuf) 601 glEnable(GL_DEPTH_TEST); 602 else 603 glDisable(GL_DEPTH_TEST); 604 605 if (fCulling) 606 glEnable(GL_CULL_FACE); 607 else 608 glDisable(GL_CULL_FACE); 609 610 if (fLighting) 611 glEnable(GL_LIGHTING); 612 else 613 glDisable(GL_LIGHTING); 614 615 if (fFilled) 616 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 617 else 618 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 619 620 if (fFog) { 621 glFogf(GL_FOG_START, 10.0); 622 glFogf(GL_FOG_DENSITY, 0.2); 623 glFogf(GL_FOG_END, depthOfView); 624 glFogfv(GL_FOG_COLOR, foggy); 625 glEnable(GL_FOG); 626 bgColor = foggy; 627 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0); 628 } else { 629 glDisable(GL_FOG); 630 bgColor = black; 631 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0); 632 } 633 } 634 635 636 bool 637 ObjectView::SpinIt() 638 { 639 bool changed = false; 640 641 if (fGouraud != fLastGouraud) { 642 LockGL(); 643 glShadeModel(fGouraud ? GL_SMOOTH : GL_FLAT); 644 UnlockGL(); 645 fLastGouraud = fGouraud; 646 changed = true; 647 } 648 649 if (fZbuf != fLastZbuf) { 650 LockGL(); 651 if (fZbuf) 652 glEnable(GL_DEPTH_TEST); 653 else 654 glDisable(GL_DEPTH_TEST); 655 UnlockGL(); 656 fLastZbuf = fZbuf; 657 changed = true; 658 } 659 660 if (fCulling != fLastCulling) { 661 LockGL(); 662 if (fCulling) 663 glEnable(GL_CULL_FACE); 664 else 665 glDisable(GL_CULL_FACE); 666 UnlockGL(); 667 fLastCulling = fCulling; 668 changed = true; 669 } 670 671 if (fLighting != fLastLighting) { 672 LockGL(); 673 if (fLighting) 674 glEnable(GL_LIGHTING); 675 else 676 glDisable(GL_LIGHTING); 677 UnlockGL(); 678 fLastLighting = fLighting; 679 changed = true; 680 } 681 682 if (fFilled != fLastFilled) { 683 LockGL(); 684 if (fFilled) { 685 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 686 } else { 687 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 688 } 689 UnlockGL(); 690 fLastFilled = fFilled; 691 changed = true; 692 } 693 694 if (fFog != fLastFog) { 695 if (fFog) { 696 glFogf(GL_FOG_START, 1.0); 697 glFogf(GL_FOG_DENSITY, 0.2); 698 glFogf(GL_FOG_END, depthOfView); 699 glFogfv(GL_FOG_COLOR, foggy); 700 glEnable(GL_FOG); 701 bgColor = foggy; 702 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0); 703 } else { 704 glDisable(GL_FOG); 705 bgColor = black; 706 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0); 707 } 708 fLastFog = fFog; 709 changed = true; 710 } 711 712 changed = changed || RepositionView(); 713 changed = changed || fForceRedraw; 714 fForceRedraw = false; 715 716 for (int i = 0; i < fObjects.CountItems(); i++) { 717 bool hack = reinterpret_cast<GLObject*>(fObjects.ItemAt(i))->SpinIt(); 718 changed = changed || hack; 719 } 720 721 return changed; 722 } 723 724 725 void 726 ObjectView::DrawFrame(bool noPause) 727 { 728 LockGL(); 729 glClear(GL_COLOR_BUFFER_BIT | (fZbuf ? GL_DEPTH_BUFFER_BIT : 0)); 730 731 fObjListLock.Lock(); 732 for (int i = 0; i < fObjects.CountItems(); i++) { 733 GLObject *object = reinterpret_cast<GLObject*>(fObjects.ItemAt(i)); 734 if (object->Solidity() == 0) 735 object->Draw(false, NULL); 736 } 737 EnforceState(); 738 for (int i = 0; i < fObjects.CountItems(); i++) { 739 GLObject *object = reinterpret_cast<GLObject*>(fObjects.ItemAt(i)); 740 if (object->Solidity() != 0) 741 object->Draw(false, NULL); 742 } 743 fObjListLock.Unlock(); 744 745 glDisable(GL_BLEND); 746 glDepthMask(GL_TRUE); 747 748 if (noPause) { 749 uint64 now = system_time(); 750 float fps = 1.0 / ((now - fLastFrame) / 1000000.0); 751 fLastFrame = now; 752 int entry; 753 if (fHistEntries < HISTSIZE) { 754 entry = (fOldestEntry + fHistEntries) % HISTSIZE; 755 fHistEntries++; 756 } else { 757 entry = fOldestEntry; 758 fOldestEntry = (fOldestEntry + 1) % HISTSIZE; 759 } 760 761 fFpsHistory[entry] = fps; 762 763 if (fHistEntries > 5) { 764 fps = 0; 765 for (int i = 0; i < fHistEntries; i++) 766 fps += fFpsHistory[(fOldestEntry + i) % HISTSIZE]; 767 768 fps /= fHistEntries; 769 770 if (fFps) { 771 glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT); 772 glPushMatrix(); 773 glLoadIdentity(); 774 glTranslatef(-0.9, -0.9, 0); 775 glScalef(0.10, 0.10, 0.10); 776 glDisable(GL_LIGHTING); 777 glDisable(GL_DEPTH_TEST); 778 glDisable(GL_BLEND); 779 glColor3f(1.0, 1.0, 0); 780 glMatrixMode(GL_PROJECTION); 781 glPushMatrix(); 782 glLoadIdentity(); 783 glMatrixMode(GL_MODELVIEW); 784 785 FPS::drawCounter(fps); 786 787 glMatrixMode(GL_PROJECTION); 788 glPopMatrix(); 789 glMatrixMode(GL_MODELVIEW); 790 glPopMatrix(); 791 glPopAttrib(); 792 } 793 } 794 } else { 795 fHistEntries = 0; 796 fOldestEntry = 0; 797 } 798 SwapBuffers(); 799 UnlockGL(); 800 } 801