00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 #include <GL/gl.h>
00021 
00022 #include <archon/render/context.H>
00023 
00024 #include <archon/render/conductor.H>
00025 
00026 namespace Archon
00027 {
00028   namespace Render
00029   {
00030     void Channel::render(const Ref<Pipe> &pipe)
00031     {
00032       Display::Bind bind(pipe->context, window);
00033 
00034       if(!pipe->initialized)
00035       {
00036         view->renderer->initOpenGlContext();
00037         pipe->initialized = true;
00038       }
00039 
00040       double l, b, w, h;
00041       Vector3 c, x, y;
00042       double s, t;
00043       Vector3 e;
00044       double n, f;
00045 
00046       
00047       {
00048         Mutex::Lock lock(view->viewMutex);
00049         l = viewport->left;
00050         b = viewport->bottom;
00051         w = viewport->width;
00052         h = viewport->height;
00053         c = screen->center;
00054         x = screen->x;
00055         y = screen->y;
00056         s = screen->halfWidth;
00057         t = screen->halfHeight;
00058         e = eye->position;
00059         n = clip->near;
00060         f = clip->far;
00061       }
00062 
00063       
00064       Vector3 z = x;
00065       z *= y;
00066 
00067       
00068       
00069       c -= e;
00070       c.set(dot(c, x), dot(c, y), dot(c, z));
00071 
00072       
00073       double a = n / -c[2];
00074       glMatrixMode(GL_PROJECTION);
00075       glLoadIdentity();
00076       glFrustum((c[0] - s) * a, (c[0] + s) * a,
00077                 (c[1] - t) * a, (c[1] + t) * a, n, f);
00078 
00079       
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088       
00089       GLdouble m[16] =
00090       {
00091         x[0],       y[0],       z[0],       0,
00092         x[1],       y[1],       z[1],       0,
00093         x[2],       y[2],       z[2],       0,
00094         -dot(x, e), -dot(y, e), -dot(z, e), 1
00095       };
00096       glMatrixMode(GL_MODELVIEW);
00097       glLoadMatrixd(m);
00098 
00099       
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107       
00108       s = window->getWidth();
00109       t = window->getHeight();
00110       unsigned il = static_cast<unsigned>(l * s + 0.5);
00111       unsigned ib = static_cast<unsigned>(b * t + 0.5);
00112       unsigned iw = static_cast<unsigned>((l+w) * s + 0.5) - il;
00113       unsigned ih = static_cast<unsigned>((b+h) * t + 0.5) - ib;
00114       glViewport(il, ib, iw, ih);
00115 
00116       view->renderer->render();
00117     }
00118 
00119 
00120     void Pipe::addChannel(Ref<Conductor> conductor,
00121                           Ref<View> view,
00122                           Ref<Display::Window> window,
00123                           Ref<Viewport> viewport,
00124                           Ref<Screen> screen,
00125                           Ref<Eye> eye,
00126                           Ref<Clip> clip)
00127     {
00128       if(view != viewport->view ||
00129          view !=   screen->view ||
00130          view !=      eye->view ||
00131          view !=     clip->view)
00132         ARCHON_THROW1(ArgumentException,
00133                       "Illegal combination - different View objects found");
00134       conductor->addWindow(window, this);
00135       Mutex::Lock l(channelMutex);
00136       channels.push_back(Channel(view, window, viewport, screen, eye, clip));
00137     }
00138 
00139     void Pipe::render()
00140     {
00141       Ref<Pipe> pipe(this);
00142       Mutex::Lock l(channelMutex);
00143       for(unsigned i=0; i<channels.size(); ++i) channels[i].render(pipe);
00144     }
00145   }
00146 }