BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / apps / glteapot / ObjectView.cpp
blob6849aa6ea9692ae21e931e48de690d99ebb78c98
1 /*
2 * Copyright 2008 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Alexandre Deckner
8 */
11 * Original Be Sample source modified to use a quaternion for the object's orientation
15 Copyright 1999, Be Incorporated. All Rights Reserved.
16 This file may be used under the terms of the Be Sample Code License.
19 #include "ObjectView.h"
21 #include <Application.h>
22 #include <Catalog.h>
23 #include <Cursor.h>
24 #include <InterfaceKit.h>
25 #include <FindDirectory.h>
27 #include "FPS.h"
28 #include "GLObject.h"
29 #include "ResScroll.h"
31 #undef B_TRANSLATION_CONTEXT
32 #define B_TRANSLATION_CONTEXT "ObjectView"
34 float displayScale = 1.0;
35 float depthOfView = 30.0;
36 float zRatio = 10.0;
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};
50 float* bgColor = black;
52 const char *kNoResourceError = B_TRANSLATE("The Teapot 3D model was "
53 "not found in application resources. "
54 "Please repair the program installation.");
56 struct light {
57 float *ambient;
58 float *diffuse;
59 float *specular;
63 light lights[] = {
64 {NULL, NULL, NULL},
65 {dimWhite, white, white},
66 {dimWhite, yellow, yellow},
67 {dimWhite, red, red},
68 {dimWhite, blue, blue},
69 {dimWhite, green, green}
74 long
75 signalEvent(sem_id event)
77 int32 c;
78 get_sem_count(event,&c);
79 if (c < 0)
80 release_sem_etc(event,-c,0);
82 return 0;
86 long
87 setEvent(sem_id event)
89 int32 c;
90 get_sem_count(event,&c);
91 if (c < 0)
92 release_sem_etc(event,-c,0);
94 return 0;
98 long
99 waitEvent(sem_id event)
101 acquire_sem(event);
103 int32 c;
104 get_sem_count(event,&c);
105 if (c > 0)
106 acquire_sem_etc(event,c,0,0);
108 return 0;
112 static int32
113 simonThread(void* cookie)
115 ObjectView* objectView = reinterpret_cast<ObjectView*>(cookie);
116 BScreen screen(objectView->Window());
118 int noPause = 0;
119 while (acquire_sem_etc(objectView->quittingSem, 1, B_TIMEOUT, 0) == B_NO_ERROR) {
120 if (objectView->SpinIt()) {
121 objectView->DrawFrame(noPause);
122 release_sem(objectView->quittingSem);
123 noPause = 1;
124 } else {
125 release_sem(objectView->quittingSem);
126 noPause = 0;
127 waitEvent(objectView->drawEvent);
129 screen.WaitForRetrace();
131 return 0;
135 ObjectView::ObjectView(BRect rect, const char *name, ulong resizingMode,
136 ulong options)
137 : BGLView(rect, name, resizingMode, 0, options),
138 fHistEntries(0),
139 fOldestEntry(0),
140 fFps(true),
141 fLastGouraud(true),
142 fGouraud(true),
143 fLastZbuf(true),
144 fZbuf(true),
145 fLastCulling(true),
146 fCulling(true),
147 fLastLighting(true),
148 fLighting(true),
149 fLastFilled(true),
150 fFilled(true),
151 fLastPersp(false),
152 fPersp(false),
153 fLastTextured(false),
154 fTextured(false),
155 fLastFog(false),
156 fFog(false),
157 fForceRedraw(false),
158 fLastYXRatio(1),
159 fYxRatio(1)
161 fTrackingInfo.isTracking = false;
162 fTrackingInfo.pickedObject = NULL;
163 fTrackingInfo.buttons = 0;
164 fTrackingInfo.lastX = 0.0f;
165 fTrackingInfo.lastY = 0.0f;
166 fTrackingInfo.lastDx = 0.0f;
167 fTrackingInfo.lastDy = 0.0f;
169 fLastObjectDistance = fObjectDistance = depthOfView / 8;
170 quittingSem = create_sem(1, "quitting sem");
171 drawEvent = create_sem(0, "draw event");
173 TriangleObject *Tri = new TriangleObject(this);
174 if (Tri->InitCheck() == B_OK) {
175 fObjListLock.Lock();
176 fObjects.AddItem(Tri);
177 fObjListLock.Unlock();
178 } else {
179 BAlert *NoResourceAlert = new BAlert(B_TRANSLATE("Error"),
180 kNoResourceError, B_TRANSLATE("OK"), NULL, NULL,
181 B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_STOP_ALERT);
182 NoResourceAlert->SetFlags(NoResourceAlert->Flags() | B_CLOSE_ON_ESCAPE);
183 NoResourceAlert->Go();
184 delete Tri;
189 ObjectView::~ObjectView()
191 delete_sem(quittingSem);
192 delete_sem(drawEvent);
196 void
197 ObjectView::AttachedToWindow()
199 float position[] = {0.0, 3.0, 3.0, 0.0};
200 float position1[] = {-3.0, -3.0, 3.0, 0.0};
201 float position2[] = {3.0, 0.0, 0.0, 0.0};
202 float local_view[] = {0.0, 0.0};
203 // float ambient[] = {0.1745, 0.03175, 0.03175};
204 // float diffuse[] = {0.61424, 0.10136, 0.10136};
205 // float specular[] = {0.727811, 0.626959, 0.626959};
206 // rgb_color black = {0, 0, 0, 255};
207 BRect bounds = Bounds();
209 BGLView::AttachedToWindow();
210 Window()->SetPulseRate(100000);
212 LockGL();
214 glEnable(GL_DITHER);
215 glEnable(GL_CULL_FACE);
216 glCullFace(GL_BACK);
217 glDepthFunc(GL_LESS);
219 glShadeModel(GL_SMOOTH);
221 glLightfv(GL_LIGHT0, GL_POSITION, position);
222 glLightfv(GL_LIGHT0 + 1, GL_POSITION, position1);
223 glLightfv(GL_LIGHT0 + 2, GL_POSITION, position2);
224 glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);
226 glEnable(GL_LIGHT0);
227 glLightfv(GL_LIGHT0, GL_SPECULAR, lights[lightWhite].specular);
228 glLightfv(GL_LIGHT0, GL_DIFFUSE,lights[lightWhite].diffuse);
229 glLightfv(GL_LIGHT0, GL_AMBIENT,lights[lightWhite].ambient);
230 glEnable(GL_LIGHT1);
231 glLightfv(GL_LIGHT1, GL_SPECULAR, lights[lightBlue].specular);
232 glLightfv(GL_LIGHT1, GL_DIFFUSE,lights[lightBlue].diffuse);
233 glLightfv(GL_LIGHT1, GL_AMBIENT,lights[lightBlue].ambient);
235 glFrontFace(GL_CW);
236 glEnable(GL_LIGHTING);
237 glEnable(GL_AUTO_NORMAL);
238 glEnable(GL_NORMALIZE);
240 glMaterialf(GL_FRONT, GL_SHININESS, 0.6 * 128.0);
242 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0);
243 glColor3f(1.0, 1.0, 1.0);
245 glViewport(0, 0, (GLint)bounds.IntegerWidth() + 1,
246 (GLint)bounds.IntegerHeight() + 1);
247 glMatrixMode(GL_PROJECTION);
248 glLoadIdentity();
250 float scale = displayScale;
251 glOrtho(-scale, scale, -scale, scale, -scale * depthOfView,
252 scale * depthOfView);
253 glMatrixMode(GL_MODELVIEW);
254 glLoadIdentity();
256 UnlockGL();
258 fDrawThread = spawn_thread(simonThread, "Simon", B_NORMAL_PRIORITY, this);
259 resume_thread(fDrawThread);
260 fForceRedraw = true;
261 setEvent(drawEvent);
265 void
266 ObjectView::DetachedFromWindow()
268 BGLView::DetachedFromWindow();
270 status_t dummy;
271 long locks = 0;
273 while (Window()->IsLocked()) {
274 locks++;
275 Window()->Unlock();
278 acquire_sem(quittingSem);
279 release_sem(drawEvent);
280 wait_for_thread(fDrawThread, &dummy);
281 release_sem(quittingSem);
283 while (locks--)
284 Window()->Lock();
288 void
289 ObjectView::Pulse()
291 Window()->Lock();
292 BRect parentBounds = Parent()->Bounds();
293 BRect bounds = Bounds();
294 parentBounds.OffsetTo(0, 0);
295 bounds.OffsetTo(0, 0);
296 if (bounds != parentBounds) {
297 ResizeTo(parentBounds.right - parentBounds.left,
298 parentBounds.bottom - parentBounds.top);
300 Window()->Unlock();
304 void
305 ObjectView::MessageReceived(BMessage* msg)
307 BMenuItem* item = NULL;
308 bool toggleItem = false;
310 switch (msg->what) {
311 case kMsgFPS:
312 fFps = (fFps) ? false : true;
313 msg->FindPointer("source", reinterpret_cast<void**>(&item));
314 item->SetMarked(fFps);
315 fForceRedraw = true;
316 setEvent(drawEvent);
317 break;
318 case kMsgAddModel:
320 TriangleObject *Tri = new TriangleObject(this);
321 if (Tri->InitCheck() == B_OK) {
322 fObjListLock.Lock();
323 fObjects.AddItem(Tri);
324 fObjListLock.Unlock();
325 } else {
326 BAlert *NoResourceAlert = new BAlert(B_TRANSLATE("Error"),
327 kNoResourceError, B_TRANSLATE("OK"), NULL, NULL,
328 B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_STOP_ALERT);
329 NoResourceAlert->SetFlags(NoResourceAlert->Flags() | B_CLOSE_ON_ESCAPE);
330 NoResourceAlert->Go();
331 delete Tri;
333 setEvent(drawEvent);
334 break;
336 case kMsgLights:
338 msg->FindPointer("source", reinterpret_cast<void**>(&item));
339 long lightNum = msg->FindInt32("num");
340 long color = msg->FindInt32("color");
341 BMenu *menu = item->Menu();
342 long index = menu->IndexOf(item);
343 menu->ItemAt(index)->SetMarked(true);
344 for (int i = 0; i < menu->CountItems(); i++) {
345 if (i != index)
346 menu->ItemAt(i)->SetMarked(false);
349 LockGL();
350 if (color != lightNone) {
351 glEnable(GL_LIGHT0 + lightNum - 1);
352 glLightfv(GL_LIGHT0 + lightNum - 1, GL_SPECULAR,
353 lights[color].specular);
354 glLightfv(GL_LIGHT0 + lightNum - 1, GL_DIFFUSE,
355 lights[color].diffuse);
356 glLightfv(GL_LIGHT0 + lightNum - 1, GL_AMBIENT,
357 lights[color].ambient);
358 } else {
359 glDisable(GL_LIGHT0 + lightNum - 1);
361 UnlockGL();
362 fForceRedraw = true;
363 setEvent(drawEvent);
364 break;
366 case kMsgGouraud:
367 fGouraud = !fGouraud;
368 toggleItem = true;
369 break;
370 case kMsgZBuffer:
371 fZbuf = !fZbuf;
372 toggleItem = true;
373 break;
374 case kMsgCulling:
375 fCulling = !fCulling;
376 toggleItem = true;
377 break;
378 case kMsgLighting:
379 fLighting = !fLighting;
380 toggleItem = true;
381 break;
382 case kMsgFilled:
383 fFilled = !fFilled;
384 toggleItem = true;
385 break;
386 case kMsgPerspective:
387 fPersp = !fPersp;
388 toggleItem = true;
389 break;
390 case kMsgFog:
391 fFog = !fFog;
392 toggleItem = true;
393 break;
396 if (toggleItem && msg->FindPointer("source", reinterpret_cast<void**>(&item)) == B_OK){
397 item->SetMarked(!item->IsMarked());
398 setEvent(drawEvent);
401 BGLView::MessageReceived(msg);
406 ObjectView::ObjectAtPoint(const BPoint &point)
408 LockGL();
409 glShadeModel(GL_FLAT);
410 glDisable(GL_LIGHTING);
411 glDisable(GL_FOG);
412 glClearColor(black[0], black[1], black[2], 1.0);
413 glClear(GL_COLOR_BUFFER_BIT | (fZbuf ? GL_DEPTH_BUFFER_BIT : 0));
415 float idColor[3];
416 idColor[1] = idColor[2] = 0;
417 for (int i = 0; i < fObjects.CountItems(); i++) {
418 // to take into account 16 bits colorspaces,
419 // only use the 5 highest bits of the red channel
420 idColor[0] = (255 - (i << 3)) / 255.0;
421 reinterpret_cast<GLObject*>(fObjects.ItemAt(i))->Draw(true, idColor);
423 glReadBuffer(GL_BACK);
424 uchar pixel[256];
425 glReadPixels((GLint)point.x, (GLint)(Bounds().bottom - point.y), 1, 1,
426 GL_RGB, GL_UNSIGNED_BYTE, pixel);
427 int objNum = pixel[0];
428 objNum = (255 - objNum) >> 3;
430 EnforceState();
431 UnlockGL();
433 return objNum;
437 void
438 ObjectView::MouseDown(BPoint point)
440 GLObject* object = NULL;
442 BMessage *msg = Window()->CurrentMessage();
443 uint32 buttons = msg->FindInt32("buttons");
444 object = reinterpret_cast<GLObject*>(fObjects.ItemAt(ObjectAtPoint(point)));
446 if (object != NULL){
447 if (buttons == B_PRIMARY_MOUSE_BUTTON || buttons == B_SECONDARY_MOUSE_BUTTON) {
448 fTrackingInfo.pickedObject = object;
449 fTrackingInfo.buttons = buttons;
450 fTrackingInfo.isTracking = true;
451 fTrackingInfo.lastX = point.x;
452 fTrackingInfo.lastY = point.y;
453 fTrackingInfo.lastDx = 0.0f;
454 fTrackingInfo.lastDy = 0.0f;
455 fTrackingInfo.pickedObject->Spin(0.0f, 0.0f);
458 SetMouseEventMask(B_POINTER_EVENTS,
459 B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
461 BCursor grabbingCursor(B_CURSOR_ID_GRABBING);
462 SetViewCursor(&grabbingCursor);
463 } else {
464 ConvertToScreen(&point);
465 object->MenuInvoked(point);
471 void
472 ObjectView::MouseUp(BPoint point)
474 if (fTrackingInfo.isTracking) {
476 //spin the teapot on release, TODO: use a marching sum and divide by time
477 if (fTrackingInfo.buttons == B_PRIMARY_MOUSE_BUTTON
478 && fTrackingInfo.pickedObject != NULL
479 && (fabs(fTrackingInfo.lastDx) > 1.0f
480 || fabs(fTrackingInfo.lastDy) > 1.0f) ) {
482 fTrackingInfo.pickedObject->Spin(0.5f * fTrackingInfo.lastDy, 0.5f * fTrackingInfo.lastDx);
484 setEvent(drawEvent);
487 //stop tracking
488 fTrackingInfo.isTracking = false;
489 fTrackingInfo.buttons = 0;
490 fTrackingInfo.pickedObject = NULL;
491 fTrackingInfo.lastX = 0.0f;
492 fTrackingInfo.lastY = 0.0f;
493 fTrackingInfo.lastDx = 0.0f;
494 fTrackingInfo.lastDy = 0.0f;
496 BCursor grabCursor(B_CURSOR_ID_GRAB);
497 SetViewCursor(&grabCursor);
502 void
503 ObjectView::MouseMoved(BPoint point, uint32 transit, const BMessage *msg)
505 if (fTrackingInfo.isTracking && fTrackingInfo.pickedObject != NULL) {
507 float dx = point.x - fTrackingInfo.lastX;
508 float dy = point.y - fTrackingInfo.lastY;
509 fTrackingInfo.lastX = point.x;
510 fTrackingInfo.lastY = point.y;
512 if (fTrackingInfo.buttons == B_PRIMARY_MOUSE_BUTTON) {
514 fTrackingInfo.pickedObject->Spin(0.0f, 0.0f);
515 fTrackingInfo.pickedObject->RotateWorldSpace(dx,dy);
516 fTrackingInfo.lastDx = dx;
517 fTrackingInfo.lastDy = dy;
519 setEvent(drawEvent);
521 } else if (fTrackingInfo.buttons == B_SECONDARY_MOUSE_BUTTON) {
523 float xinc = (dx * 2 * displayScale / Bounds().Width());
524 float yinc = (-dy * 2 * displayScale / Bounds().Height());
525 float zinc = 0;
527 if (fPersp) {
528 zinc = yinc * (fTrackingInfo.pickedObject->z / displayScale);
529 xinc *= -(fTrackingInfo.pickedObject->z * 4 / zRatio);
530 yinc *= -(fTrackingInfo.pickedObject->z * 4 / zRatio);
533 fTrackingInfo.pickedObject->x += xinc;
534 if (modifiers() & B_SHIFT_KEY)
535 fTrackingInfo.pickedObject->z += zinc;
536 else
537 fTrackingInfo.pickedObject->y += yinc;
539 fForceRedraw = true;
540 setEvent(drawEvent);
542 } else {
543 void* object = fObjects.ItemAt(ObjectAtPoint(point));
544 BCursor cursor(object != NULL
545 ? B_CURSOR_ID_GRAB : B_CURSOR_ID_SYSTEM_DEFAULT);
546 SetViewCursor(&cursor);
551 void
552 ObjectView::FrameResized(float width, float height)
554 BGLView::FrameResized(width, height);
556 LockGL();
558 width = Bounds().Width();
559 height = Bounds().Height();
560 fYxRatio = height / width;
561 glViewport(0, 0, (GLint)width + 1, (GLint)height + 1);
563 // To prevent weird buffer contents
564 glClear(GL_COLOR_BUFFER_BIT);
566 glMatrixMode(GL_PROJECTION);
567 glLoadIdentity();
568 float scale = displayScale;
570 if (fPersp) {
571 gluPerspective(60, 1.0 / fYxRatio, 0.15, 120);
572 } else {
573 if (fYxRatio < 1) {
574 glOrtho(-scale / fYxRatio, scale / fYxRatio, -scale, scale, -1.0,
575 depthOfView * 4);
576 } else {
577 glOrtho(-scale, scale, -scale * fYxRatio, scale * fYxRatio, -1.0,
578 depthOfView * 4);
582 fLastYXRatio = fYxRatio;
584 glMatrixMode(GL_MODELVIEW);
586 UnlockGL();
588 fForceRedraw = true;
589 setEvent(drawEvent);
593 bool
594 ObjectView::RepositionView()
596 if (!(fPersp != fLastPersp) &&
597 !(fLastObjectDistance != fObjectDistance) &&
598 !(fLastYXRatio != fYxRatio)) {
599 return false;
602 LockGL();
604 glMatrixMode(GL_PROJECTION);
605 glLoadIdentity();
606 float scale = displayScale;
608 if (fPersp) {
609 gluPerspective(60, 1.0 / fYxRatio, 0.15, 120);
610 } else {
611 if (fYxRatio < 1) {
612 glOrtho(-scale / fYxRatio, scale / fYxRatio, -scale, scale, -1.0,
613 depthOfView * 4);
614 } else {
615 glOrtho(-scale, scale, -scale * fYxRatio, scale * fYxRatio, -1.0,
616 depthOfView * 4);
620 glMatrixMode(GL_MODELVIEW);
622 UnlockGL();
624 fLastObjectDistance = fObjectDistance;
625 fLastPersp = fPersp;
626 fLastYXRatio = fYxRatio;
627 return true;
631 void
632 ObjectView::EnforceState()
634 glShadeModel(fGouraud ? GL_SMOOTH : GL_FLAT);
636 if (fZbuf)
637 glEnable(GL_DEPTH_TEST);
638 else
639 glDisable(GL_DEPTH_TEST);
641 if (fCulling)
642 glEnable(GL_CULL_FACE);
643 else
644 glDisable(GL_CULL_FACE);
646 if (fLighting)
647 glEnable(GL_LIGHTING);
648 else
649 glDisable(GL_LIGHTING);
651 if (fFilled)
652 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
653 else
654 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
656 if (fFog) {
657 glFogf(GL_FOG_START, 10.0);
658 glFogf(GL_FOG_DENSITY, 0.2);
659 glFogf(GL_FOG_END, depthOfView);
660 glFogfv(GL_FOG_COLOR, foggy);
661 glEnable(GL_FOG);
662 bgColor = foggy;
663 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0);
664 } else {
665 glDisable(GL_FOG);
666 bgColor = black;
667 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0);
672 bool
673 ObjectView::SpinIt()
675 bool changed = false;
677 if (fGouraud != fLastGouraud) {
678 LockGL();
679 glShadeModel(fGouraud ? GL_SMOOTH : GL_FLAT);
680 UnlockGL();
681 fLastGouraud = fGouraud;
682 changed = true;
685 if (fZbuf != fLastZbuf) {
686 LockGL();
687 if (fZbuf)
688 glEnable(GL_DEPTH_TEST);
689 else
690 glDisable(GL_DEPTH_TEST);
691 UnlockGL();
692 fLastZbuf = fZbuf;
693 changed = true;
696 if (fCulling != fLastCulling) {
697 LockGL();
698 if (fCulling)
699 glEnable(GL_CULL_FACE);
700 else
701 glDisable(GL_CULL_FACE);
702 UnlockGL();
703 fLastCulling = fCulling;
704 changed = true;
707 if (fLighting != fLastLighting) {
708 LockGL();
709 if (fLighting)
710 glEnable(GL_LIGHTING);
711 else
712 glDisable(GL_LIGHTING);
713 UnlockGL();
714 fLastLighting = fLighting;
715 changed = true;
718 if (fFilled != fLastFilled) {
719 LockGL();
720 if (fFilled) {
721 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
722 } else {
723 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
725 UnlockGL();
726 fLastFilled = fFilled;
727 changed = true;
730 if (fFog != fLastFog) {
731 if (fFog) {
732 glFogf(GL_FOG_START, 1.0);
733 glFogf(GL_FOG_DENSITY, 0.2);
734 glFogf(GL_FOG_END, depthOfView);
735 glFogfv(GL_FOG_COLOR, foggy);
736 glEnable(GL_FOG);
737 bgColor = foggy;
738 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0);
739 } else {
740 glDisable(GL_FOG);
741 bgColor = black;
742 glClearColor(bgColor[0], bgColor[1], bgColor[2], 1.0);
744 fLastFog = fFog;
745 changed = true;
748 changed = changed || RepositionView();
749 changed = changed || fForceRedraw;
750 fForceRedraw = false;
752 for (int i = 0; i < fObjects.CountItems(); i++) {
753 bool hack = reinterpret_cast<GLObject*>(fObjects.ItemAt(i))->SpinIt();
754 changed = changed || hack;
757 return changed;
761 void
762 ObjectView::DrawFrame(bool noPause)
764 LockGL();
765 glClear(GL_COLOR_BUFFER_BIT | (fZbuf ? GL_DEPTH_BUFFER_BIT : 0));
767 fObjListLock.Lock();
768 for (int i = 0; i < fObjects.CountItems(); i++) {
769 GLObject *object = reinterpret_cast<GLObject*>(fObjects.ItemAt(i));
770 if (object->Solidity() == 0)
771 object->Draw(false, NULL);
773 EnforceState();
774 for (int i = 0; i < fObjects.CountItems(); i++) {
775 GLObject *object = reinterpret_cast<GLObject*>(fObjects.ItemAt(i));
776 if (object->Solidity() != 0)
777 object->Draw(false, NULL);
779 fObjListLock.Unlock();
781 glDisable(GL_BLEND);
782 glDepthMask(GL_TRUE);
784 if (noPause) {
785 uint64 now = system_time();
786 float fps = 1.0 / ((now - fLastFrame) / 1000000.0);
787 fLastFrame = now;
788 int entry;
789 if (fHistEntries < HISTSIZE) {
790 entry = (fOldestEntry + fHistEntries) % HISTSIZE;
791 fHistEntries++;
792 } else {
793 entry = fOldestEntry;
794 fOldestEntry = (fOldestEntry + 1) % HISTSIZE;
797 fFpsHistory[entry] = fps;
799 if (fHistEntries > 5) {
800 fps = 0;
801 for (int i = 0; i < fHistEntries; i++)
802 fps += fFpsHistory[(fOldestEntry + i) % HISTSIZE];
804 fps /= fHistEntries;
806 if (fFps) {
807 glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT);
808 glPushMatrix();
809 glLoadIdentity();
810 glTranslatef(-0.9, -0.9, 0);
811 glScalef(0.10, 0.10, 0.10);
812 glDisable(GL_LIGHTING);
813 glDisable(GL_DEPTH_TEST);
814 glDisable(GL_BLEND);
815 glColor3f(1.0, 1.0, 0);
816 glMatrixMode(GL_PROJECTION);
817 glPushMatrix();
818 glLoadIdentity();
819 glMatrixMode(GL_MODELVIEW);
821 FPS::drawCounter(fps);
823 glMatrixMode(GL_PROJECTION);
824 glPopMatrix();
825 glMatrixMode(GL_MODELVIEW);
826 glPopMatrix();
827 glPopAttrib();
830 } else {
831 fHistEntries = 0;
832 fOldestEntry = 0;
834 SwapBuffers();
835 UnlockGL();