source: projectionDesigner/trunk/projdesigner/src/Screen.cpp @ 287

Last change on this file since 287 was 4, checked in by Torben Dannhauer, 15 years ago
File size: 14.4 KB
Line 
1#include "ProjectionModel.h"
2#include "Screen.h"
3#include "screen/ScreenDome.h"
4#include "screen/ScreenPlane.h"
5#include "screen/ScreenBox.h"
6#include "screen/ScreenModel.h"
7#include "Channel.h"
8#include "GUIControler.h"
9#include "RSync.h"
10#include "Exporter.h"
11
12using namespace projection;
13using namespace gmtl;
14
15/**
16 * Constructor. Screen data / rendering class.
17 *
18 * @param Projection model.
19 */
20Screen::Screen(ProjectionModel* pSetup) : QObject()
21{
22    m_pModel = pSetup;
23
24    m_pShapes.push_back(new ScreenDome(this));
25    m_pShapes.push_back(new ScreenPlane(this));
26    m_pShapes.push_back(new ScreenBox(this));
27    m_pShapes.push_back(new ScreenModel(this));
28    m_pCurrentShape = m_pShapes[0]; // Dome
29
30        reset ();
31}
32
33/**
34 * Destructor.
35 */
36Screen::~Screen()
37{
38    while (m_pShapes.count() > 0) {
39        ScreenShape* pShape = m_pShapes.takeAt(0);
40        if (pShape) delete pShape;
41    }
42}
43
44/**
45 * Set transform matrix of the screen.
46 *
47 * @param matrix Transform matrix of the screen.
48 */
49void Screen::setMatrix(const TransformMatrix& matrix)
50{
51    m_transformMatrix = matrix;
52    notifyRedraw();
53}
54
55/**
56 * Retrieve name of the screen shape.
57 *
58 * @param index Index of the screen shape.
59 * @return Name of the screen shape.
60 */
61QString Screen::getShapeName(int index) const
62{
63    if (index < m_pShapes.size())
64        return m_pShapes[index]->getName();
65    return "None";
66}
67
68/**
69 * Retrieve the number of the screen shapes.
70 *
71 * @return Number of the screen shapes.
72 */
73unsigned int Screen::getNumShapes() const
74{
75    return m_pShapes.size();
76}
77
78/**
79 * Retrieve screen shape object.
80 *
81 * @param shapeName Name of the screen shape.
82 * @return Screen shape object.
83 */
84ScreenShape* Screen::getShape(const QString& shapeName) const
85{
86    for (int i=0; i<m_pShapes.size(); ++i)
87        if (m_pShapes[i]->getName() == shapeName)
88            return m_pShapes[i];
89    return NULL;
90}
91
92/**
93 * Select screen shape by name.
94 *
95 * @param shapeName Name of the screen shape to select.
96 */
97void Screen::setCurrentShape(const QString& shapeName)
98{
99    if (m_pCurrentShape && m_pCurrentShape->getName() == shapeName)
100        return;
101
102    for (int i=0; i<m_pShapes.size(); ++i) {
103        if (m_pShapes[i]->getName() == shapeName) {
104            m_pCurrentShape = m_pShapes[i];
105            notifyRedraw();
106        }
107    }
108}
109
110/**
111 * Retrieve the name of the current srceen shape.
112 *
113 * @return Name of the current screen shape.
114 */
115QString Screen::getCurrentShapeName() const
116{
117    return m_pCurrentShape->getName();
118}
119
120/**
121 * Retrieve the current screen shape object.
122 *
123 * @return Current screen shape object.
124 */
125ScreenShape* Screen::getCurrentShape() const
126{
127    return m_pCurrentShape;
128}
129
130/**
131 * Retrive the radius of the current screen.
132 *
133 * @return Radius of the current screen.
134 */
135float Screen::getSize() const
136{
137    Vec3f min, max;
138    m_pCurrentShape->getBoundingBox(min, max);
139    min = m_transformMatrix.getMatrix() * min;
140    max = m_transformMatrix.getMatrix() * max;
141    float minLength = length(min);
142    float maxLength = length(max);
143    return minLength>maxLength?minLength:maxLength;
144}
145
146/**
147 * Show or hide the wire frame mesh of the screen.
148 *
149 * @param bShowFrame True to show the wire frame mesh.
150 */
151void Screen::setShowFrame(bool bShowFrame)
152{
153    m_bShowFrame = bShowFrame;
154    notifyRedraw();
155}
156
157/**
158 * Set line width of the wire frame mesh of the screen.
159 *
160 * @param frameLineWidth Line width of the wire frame mesh of the screen.
161 */
162void Screen::setFrameLineWidth(float frameLineWidth)
163{
164    m_frameLineWidth = frameLineWidth;
165    notifyRedraw();
166}
167
168/**
169 * Set size of the off-screen buffer.
170 *
171 * @param width Width of the off-screen buffer.
172 * @param height Height of the off-screen buffer.
173 */
174void Screen::setBufferSize(int width, int height)
175{
176    if (m_bufferWidth != width || m_bufferHeight != height)
177    {
178        m_bufferWidth = width;
179        m_bufferHeight = height;
180        for (unsigned int i=0; i<m_pModel->getNumChannels(); ++i)
181            m_pModel->getChannel(i)->reconstructBuffer();
182        m_pModel->updateViewAndOffscreens();
183
184        if (m_pModel->getRSync()->isServer())
185        {
186            QDomDocument doc;
187            doc.appendChild(domElement("Screen", doc));
188            m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_SCREEN, doc.toString(0));
189        }
190    }
191}
192
193/**
194 * Draw the screen shape object with.
195 *
196 * @param bDepthMaskControl True to use glDepthMask() for blending.
197 */
198void Screen::draw(bool bDepthMaskControl)
199{
200    glPushMatrix();
201
202    glMultMatrixf(m_transformMatrix.getMatrix().getData());
203
204    glPushAttrib(GL_ALL_ATTRIB_BITS);
205
206    // setup rendering parameters
207    glColor4d(0.5, 0.5, 0.5, 0.5);
208    glEnable(GL_BLEND);
209    if (bDepthMaskControl)
210        glDepthMask(false);
211    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
212    glEnable(GL_LIGHTING);
213
214    // render the screen without textures
215    m_pCurrentShape->draw(false);
216    if (bDepthMaskControl)
217        glDepthMask(true);
218
219    glPopAttrib();
220
221    glPopMatrix();
222}
223
224/**
225 * Draw the wire frame mesh of the screen.
226 */
227void Screen::drawFrame()
228{
229    glPushMatrix();
230
231    glMultMatrixf(m_transformMatrix.getMatrix().getData());
232
233    glPushAttrib(GL_ALL_ATTRIB_BITS);
234
235    // draw overlay meshs
236    if (m_bShowFrame)
237    {
238        // setup rendering parameters
239        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
240        glDisable(GL_LIGHTING);
241        glDisable(GL_TEXTURE_2D);
242        glEnable(GL_POLYGON_OFFSET_LINE);
243        glLineWidth(m_frameLineWidth);
244        glPolygonOffset(-1.0, -1.0);
245
246        glColor4d(1.0, 1.0, 1.0, 1.0);
247        m_pCurrentShape->draw(true);
248
249        glDisable(GL_POLYGON_OFFSET_LINE);
250        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
251    }
252
253    glPopAttrib();
254
255    glPopMatrix();
256}
257
258/**
259 * Draw the screen object with projection texture image of the specified channel.
260 *
261 * @param source Projection image source to draw.
262 * @param pChannel Channel which draws for.
263 */
264void Screen::draw(PROJECT_SOURCE source, Channel* pChannel)
265{
266    glMatrixMode(GL_MODELVIEW);
267    glPushMatrix();
268
269    glPushAttrib(GL_ALL_ATTRIB_BITS);
270
271    glMultMatrixf(m_transformMatrix.getMatrix().getData());
272
273    // setup rendering parameters
274    glEnable(GL_BLEND);
275    glDepthMask(false);
276    glDisable(GL_LIGHTING);
277    if (source != PROJECT_SOURCE_EXPORT_BLENDING)
278    {
279        glBlendFunc(GL_ONE, GL_ONE);
280        glColor4d(0.0, 0.0, 0.0, 1.0);
281    }
282
283    // setup common projection texture parameters
284    glEnable(GL_TEXTURE_2D);
285    glEnable(GL_TEXTURE_GEN_S);
286    glEnable(GL_TEXTURE_GEN_T);
287    glEnable(GL_TEXTURE_GEN_R);
288    glEnable(GL_TEXTURE_GEN_Q);
289
290    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
291    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
292    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
293    glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
294
295    static const GLdouble genfunc[][4] = {
296        { 1.0, 0.0, 0.0, 0.0 },
297        { 0.0, 1.0, 0.0, 0.0 },
298        { 0.0, 0.0, 1.0, 0.0 },
299        { 0.0, 0.0, 0.0, 1.0 },
300    };
301    glTexGendv(GL_S, GL_EYE_PLANE, genfunc[0]);
302    glTexGendv(GL_T, GL_EYE_PLANE, genfunc[1]);
303    glTexGendv(GL_R, GL_EYE_PLANE, genfunc[2]);
304    glTexGendv(GL_Q, GL_EYE_PLANE, genfunc[3]);
305
306    // prepare a projection matrix to use depends on the projection source
307    TransformMatrix xformMat;
308    if (source == PROJECT_SOURCE_PROJECTORAREA ||
309        source == PROJECT_SOURCE_EXPORT_BLENDING)
310    {
311                xformMat = pChannel->getProjectorTransformMatrix();
312    }
313    else
314    {
315                xformMat = pChannel->getView()->getTransformMatrix();
316    }
317
318    // setup clip plane to hide opposite side projection
319#if 1
320    if (m_pCurrentShape->isClippingRequired())
321    {
322        Vec3f pos = makeTrans<Vec3f>(xformMat.getMatrix());
323        Vec3f planeAxis = m_transformMatrix.getMatrix() * (xformMat.getMatrix()) * Vec3f(0.0f, 0.0f, -1.0f);
324        GLdouble plane[4] = { planeAxis[0], planeAxis[1], planeAxis[2], -dot(pos, planeAxis) };
325        glClipPlane(GL_CLIP_PLANE0, plane);
326        glEnable(GL_CLIP_PLANE0);
327    }
328#endif // 1
329
330    // bind a texture for projection
331    switch (source)
332    {
333    case PROJECT_SOURCE_PROJECTORAREA:
334        glBindTexture(GL_TEXTURE_2D, m_pModel->getProjectorAreaTexture()); break;
335    case PROJECT_SOURCE_VIEWAREA:
336        glBindTexture(GL_TEXTURE_2D, m_pModel->getViewAreaTexture()); break;
337    case PROJECT_SOURCE_SCENE:
338        glBindTexture(GL_TEXTURE_2D, pChannel->getViewTexture()); break;
339    case PROJECT_SOURCE_EXPORT_DISTORTION:
340        glBindTexture(GL_TEXTURE_2D, m_pModel->getExporter()->getTexCoordColorTexture()); break;
341    case PROJECT_SOURCE_EXPORT_DISTORTION_R:
342        glBindTexture(GL_TEXTURE_2D, m_pModel->getExporter()->getTexCoordColorRTexture()); break;
343    case PROJECT_SOURCE_EXPORT_BLENDING:
344        glBindTexture(GL_TEXTURE_2D, m_pModel->getExporter()->getBlendingAreaTexture());
345        break;
346    case PROJECT_SOURCE_NONE:
347        break;
348    }
349
350    // setup texture parameters
351    if (source != PROJECT_SOURCE_EXPORT_BLENDING)
352        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
353    else
354        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
355
356    GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
357    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
358
359    if (source != PROJECT_SOURCE_EXPORT_DISTORTION) {
360        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0x812D); // GL_CLAMP_TO_BORDER
361        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0x812D); // GL_CLAMP_TO_BORDER
362    } else {
363        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
364        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
365    }
366
367    switch (source)
368    {
369    case PROJECT_SOURCE_PROJECTORAREA:
370    case PROJECT_SOURCE_EXPORT_DISTORTION:
371    case PROJECT_SOURCE_EXPORT_DISTORTION_R:
372        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
373        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
374        break;
375    default:
376        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
377        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
378        break;
379    }
380
381    // setup texture projection matrix
382    glMatrixMode(GL_TEXTURE);
383    glPushMatrix();
384    glLoadIdentity();
385
386    if (source != PROJECT_SOURCE_EXPORT_DISTORTION)
387    {
388        glTranslated(0.5, 0.5, 1.0);
389        glScaled(0.5, 0.5, 1.0);
390    } else {
391            glScaled(0.5, 0.5, 1.0);
392        glScaled(16.0, 16.0, 1.0);
393    }
394
395        if (source == PROJECT_SOURCE_PROJECTORAREA ||
396        source == PROJECT_SOURCE_EXPORT_BLENDING)
397    {
398                pChannel->getProjector()->beginProjection();
399    }
400    else
401    {
402                ProjectionMatrix projMat = pChannel->getView()->getProjectionMatrix();
403                glMultMatrixf(projMat.getMatrix());
404    }
405
406    Matrix44f invXformMat = xformMat.getMatrix();
407    invert(invXformMat);
408        glMultMatrixf(invXformMat.getData());
409
410    glMultMatrixf(m_transformMatrix.getMatrix().getData());
411
412    glMatrixMode(GL_MODELVIEW);
413
414    // render the screen with the projected texture
415    m_pCurrentShape->draw(false);
416
417#if 1
418        if (source == PROJECT_SOURCE_PROJECTORAREA ||
419        source == PROJECT_SOURCE_EXPORT_BLENDING)
420    {
421                pChannel->getProjector()->endProjection();
422    }
423#endif
424
425    if (m_pCurrentShape->isClippingRequired())
426        glDisable(GL_CLIP_PLANE0);
427
428    glMatrixMode(GL_TEXTURE);
429    glPopMatrix();
430
431    glMatrixMode(GL_MODELVIEW);
432
433    glDisable(GL_TEXTURE_GEN_S);
434    glDisable(GL_TEXTURE_GEN_T);
435    glDisable(GL_TEXTURE_GEN_R);
436    glDisable(GL_TEXTURE_GEN_Q);
437    glDisable(GL_TEXTURE_2D);
438
439    glDepthMask(true);
440
441    glPopAttrib();
442
443    glPopMatrix();
444}
445
446/**
447 * Notify to redraw the screen.
448 */
449void Screen::notifyRedraw()
450{
451    m_pModel->updateViews();
452
453    if (m_pModel->getRSync()->isServer())
454    {
455        QDomDocument doc;
456        doc.appendChild(domElement("Screen", doc));
457        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_SCREEN, doc.toString(0));
458    }
459}
460
461/**
462 * Restore the screen shape from XML data.
463 *
464 * @param element Parent XML element of the screen data.
465 */
466bool Screen::initFromDOMElement(const QDomElement& element)
467{
468    if (!element.isNull())
469    {
470        m_transformMatrix.initFromDOMElement(element.firstChildElement("TransformMatrix"));
471        setCurrentShape(element.attribute("shapeName"));
472        m_bShowFrame = element.attribute("showFrame").toLower()=="true";
473        m_frameLineWidth = element.attribute("frameLineWidth").toFloat();
474        setBufferSize(element.attribute("bufferWidth").toInt(), element.attribute("bufferHeight").toInt());
475
476        QDomElement shapes = element.firstChildElement("Shapes");
477        QDomElement shape = shapes.firstChild().toElement();
478        while (!shape.isNull())
479                {
480            if (shape.tagName() == "Shape") {
481                ScreenShape* pShape = getShape(shape.attribute("name"));
482                                if (pShape)
483                    if( !pShape->initFromDOMElement(shape) )
484                                                return false;
485            }
486            shape = shape.nextSiblingElement();
487        }
488    }
489
490    notifyRedraw();
491
492        return true;    // todo: secure this function and return false on any critical error
493}
494
495/**
496 * Store the current screen shape as XML data.
497 *
498 * @param name XML node name of the data.
499 * @param doc XML document to store the data.
500 * @return Current screen data as XML data.
501 */
502QDomElement Screen::domElement(const QString& name, QDomDocument& doc) const
503{
504    QDomElement de = doc.createElement(name);
505    de.appendChild(m_transformMatrix.domElement("TransformMatrix", doc));
506    de.setAttribute("shapeName", getCurrentShapeName());
507    de.setAttribute("showFrame", (m_bShowFrame?"true":"false"));
508    de.setAttribute("frameLineWidth", m_frameLineWidth);
509    de.setAttribute("bufferWidth", QString::number(m_bufferWidth));
510    de.setAttribute("bufferHeight", QString::number(m_bufferHeight));
511
512    QDomElement shapes = doc.createElement("Shapes");
513    for (int i=0; i<m_pShapes.size(); ++i)
514        shapes.appendChild(m_pShapes[i]->domElement("Shape", doc));
515    de.appendChild(shapes);
516
517    return de;
518}
519
520void Screen::reset()
521{
522    m_pCurrentShape = m_pShapes[0];     // Dome
523    m_bShowFrame = true;
524    m_frameLineWidth = 1.0f;
525    m_bufferWidth = 256;
526    m_bufferHeight = 256;
527}
Note: See TracBrowser for help on using the repository browser.