diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4fded61b..1df17c0e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -442,6 +442,12 @@ if(USE_GLEW) target_link_libraries(twowindows GLEW::GLEW) endif() +add_executable(twowindows_mutex twowindows_mutex.cpp) +target_link_libraries(twowindows_mutex OpenGL::GL glfw Freetype::Freetype) +if(USE_GLEW) + target_link_libraries(twowindows_mutex GLEW::GLEW) +endif() + add_executable(threewindows threewindows.cpp) target_link_libraries(threewindows OpenGL::GL glfw Freetype::Freetype) if(USE_GLEW) diff --git a/examples/twowindows_mutex.cpp b/examples/twowindows_mutex.cpp new file mode 100644 index 00000000..84b96a82 --- /dev/null +++ b/examples/twowindows_mutex.cpp @@ -0,0 +1,112 @@ +/* + * The twowindows example, but at least compiling and running the mutex locking code in + * morph::Visual. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + int rtn = -1; + + // Demonstrates use of offset (left at 0,0,0), lengths (3,2,1) and the 'thickness' + // scaling factor (0.5) for the coordinate arrows. Defines, and makes current a new + // window and OpenGL context. + morph::Visual v(1024, 768, "Window 1", {0.8,-0.8}, {.1,.05,.05}, 3.0f, 0.01f); + v.showCoordArrows = true; + v.showTitle = true; + v.backgroundWhite(); + v.lightingEffects(); + + // If I define a second Visual here, then the OpenGL context will now be 'pointing' + // at this Visual v2 + morph::Visual v2(768, 768, "Graph on Window 2", {0.8,-0.8}, {.05,.05,.1}, 2.0f, 0.01f); + v2.showCoordArrows = true; + v2.showTitle = true; + v2.backgroundWhite(); + v2.lightingEffects(); + + try { + // Set up data for the first Visual + morph::vec offset = { 0.0, 0.0, 0.0 }; + + std::vector> coords(20*20); + std::vector> quivs(20*20); + morph::vvec qlens(20*20, 0.0f); + + size_t k = 0; + for (int i = -10; i < 10; ++i) { + for (int j = -10; j < 10; ++j) { + float x = 0.1*i; + float y = 0.1*j; + // z is some function of x, y + float z = x * std::exp(-(x*x) - (y*y)); + coords[k] = {x, y, z}; + k++; + } + } + + k = 0; + for (int i = -10; i < 10; ++i) { + for (int j = -10; j < 10; ++j) { + if (i > -10 && i < 10 && j > -10 && j < 10) { + morph::vec r = coords[k] - coords[k-20]; + morph::vec g = coords[k] - coords[k-1]; + // Compute normal and modulate by the distance from the centre + quivs[k] = r.cross(g); + if (coords[k].length() != 0.0f) { quivs[k] *= 1.0f / (1.2f + coords[k].length()); } + qlens[k] = quivs[k].length(); + } else { + quivs[k] = {0.0f, 0.0f, 0.0f}; + } + k++; + } + } + + auto qvp = std::make_unique>(&coords, offset, &quivs, morph::ColourMapType::Jet); + v.bindmodel (qvp); + qvp->quiver_length_gain = 1.0f; // Scale the length of the quivers on screen + qvp->colourScale.compute_scaling(0, qlens.max()); + qvp->quiver_thickness_gain = 0.02f; // Scale thickness of the quivers + qvp->finalize(); + v.addVisualModel (qvp); + + // Set up v2 with a graph, switching to the Visual v2's context first: + auto gv = std::make_unique> (morph::vec({0,0,0})); + v2.bindmodel (gv); + morph::vvec x = {-.5, -.4, -.3, -.2, -.1, 0, .1, .2, .3, .4, .5, .6, .7, .8}; + morph::vvec y = x.pow(3); + gv->setdata (x, y); + gv->finalize(); + v2.addVisualModel (gv); + + bool gotlock = false; + while (v.readyToFinish == false && v2.readyToFinish == false) { + v.waitevents (0.018); + gotlock = v.tryLockContext(); + if (!gotlock) { + v.lockContext(); + } + v.render(); + v.unlockContext(); + + v2.lockContext(); + v2.render(); + v2.unlockContext(); + } + + } catch (const std::exception& e) { + std::cerr << "Caught exception: " << e.what() << std::endl; + rtn = -1; + } + + return rtn; +}