// threaded rendering with vrui // sean whalen, 03-2009 (updated 09-2009) #include <stdlib.h> #include <vector> #include <Geometry/Random.h> #include <GL/GLContextData.h> #include <GL/GLGeometryWrappers.h> #include <Threads/Mutex.h> #include <Threads/Thread.h> #include <Vrui/Vrui.h> #include <Vrui/Application.h> #include <Vrui/Geometry.h> #define RADIUS 10 #define NUM_POINTS 12 using namespace std; class ThreadExample : public Vrui::Application, public GLObject { private: struct DataItem : public GLObject::DataItem { GLuint displayList; int displayListVersion; DataItem() { displayList = glGenLists(1); displayListVersion = 0; } ~DataItem() { glDeleteLists(displayList, 1); } }; int displayListVersion; vector<Vrui::Point> pointsWrite; vector<Vrui::Point> pointsRead; Vrui::Point min; Vrui::Point max; Threads::Thread layoutThread; Threads::Mutex mutex; bool stopped; public: ThreadExample(int, char**, char**); ~ThreadExample(); void display(GLContextData&) const; void frame(); void initContext(GLContextData&) const; void* threadMethod(); }; ThreadExample::ThreadExample(int argc, char** argv, char** appDefaults) : Vrui::Application(argc, argv, appDefaults) { displayListVersion = 0; min = Vrui::Point(-RADIUS, -RADIUS, -RADIUS); max = Vrui::Point(RADIUS, RADIUS, RADIUS); for(int i = 0; i < NUM_POINTS; i++) { Vrui::Point p = Geometry::randPointUniformCO(min, max); pointsWrite.push_back(p); } Vrui::setNavigationTransformation(Vrui::Point(0, 0, 0), 25.0); stopped = false; layoutThread.start(this, &ThreadExample::threadMethod); } ThreadExample::~ThreadExample() { stopped = true; } void ThreadExample::initContext(GLContextData& contextData) const { DataItem* dataItem = new DataItem; contextData.addDataItem(this, dataItem); } void ThreadExample::display(GLContextData& contextData) const { DataItem* dataItem = contextData.retrieveDataItem<DataItem>(this); glPointSize(3); if(dataItem->displayListVersion != displayListVersion) { glNewList(dataItem->displayList, GL_COMPILE); glBegin(GL_POINTS); glColor3f(0, 255, 0); for(int i = 0; i < NUM_POINTS; i++) { glVertex(pointsRead[i]); } glEnd(); glEndList(); dataItem->displayListVersion = displayListVersion; } glCallList(dataItem->displayList); } void ThreadExample::frame() { mutex.lock(); pointsRead = pointsWrite; displayListVersion++; mutex.unlock(); Vrui::requestUpdate(); } void* ThreadExample::threadMethod() { while(!stopped) { mutex.lock(); for(int i = 0; i < NUM_POINTS; i++) { pointsWrite[i] = Geometry::randPointUniformCO(min, max); } mutex.unlock(); } return 0; } int main(int argc, char** argv) { char** appDefaults = 0; ThreadExample app(argc, argv, appDefaults); app.run(); return 0; }