source: projectionDesigner/trunk/projdesigner/src/Scene.cpp @ 407

Last change on this file since 407 was 4, checked in by Torben Dannhauer, 15 years ago
File size: 11.2 KB
Line 
1#include "ProjectionModel.h"
2#include "Scene.h"
3#include "RSync.h"
4#pragma warning(disable: 4003)
5#include "gmtl/gmtl.h"
6
7#include "GUIControler.h"
8
9using namespace projection;
10using namespace gmtl;
11
12static void dom2vp(const QDomElement& parent, gmtl::Vec3f& center, gmtl::Quatf& rot, float& distance)
13{
14    if (parent.isNull())
15        return;
16
17    center[0] = parent.attribute("centerx", "0").toFloat();
18    center[1] = parent.attribute("centery", "0").toFloat();
19    center[2] = parent.attribute("centerz", "0").toFloat();
20    rot[0] = parent.attribute("rotx", "0").toFloat();
21    rot[1] = parent.attribute("roty", "0").toFloat();
22    rot[2] = parent.attribute("rotz", "0").toFloat();
23    rot[3] = parent.attribute("rotw", "1").toFloat();
24    distance = parent.attribute("distance", "1").toFloat();
25}
26
27static QDomElement vp2dom(QDomDocument& doc, const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
28{
29    QDomElement cm = doc.createElement("Camera");
30    cm.setAttribute("centerx", QString::number(center[0]));
31    cm.setAttribute("centery", QString::number(center[1]));
32    cm.setAttribute("centerz", QString::number(center[2]));
33    cm.setAttribute("rotx", QString::number(rot[0]));
34    cm.setAttribute("roty", QString::number(rot[1]));
35    cm.setAttribute("rotz", QString::number(rot[2]));
36    cm.setAttribute("rotw", QString::number(rot[3]));
37    cm.setAttribute("distance", QString::number(distance));
38    return cm;
39}
40
41static gmtl::Matrix44f vp2matrix(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
42{
43    return makeTrans<Matrix44f>(center) * makeRot<Matrix44f>(rot) * makeTrans<Matrix44f>(Vec3f(0.0f, 0.0f, distance));
44}
45
46/**
47 * Constructor.
48 *
49 * @param pModel Projection model.
50 */
51Scene::Scene(ProjectionModel* pModel) : QObject()
52{
53    m_pModel = pModel;
54        foreach (SceneInterface *scene_interface, ProjectionModel::scene_interfaces)
55        {
56        Q_ASSERT(NULL!=scene_interface);
57            foreach (QString scene_name, scene_interface->scenes())
58                {
59                    SceneContent* scene_content = scene_interface->newSceneContent(scene_name);
60                        m_pContents.push_back(scene_content);
61                }
62        }
63        reset();
64
65    m_bShowGrid = true;
66        m_gridSize = 5;
67
68    m_cameraDistance = 2.0f;
69    m_cameraRot = makeRot<Quatf>(AxisAnglef(Math::deg2Rad(45.0f), Vec3f(0.0f, 1.0f, 0.0f))) *
70                  makeRot<Quatf>(AxisAnglef(Math::deg2Rad(-45.0f), Vec3f(1.0f, 0.0f, 0.0f)));
71}
72
73/**
74 * Destructor.
75 */
76Scene::~Scene()
77{
78    while (m_pContents.count() > 0) {
79        SceneContent* pContent = m_pContents.takeAt(0);
80        if (pContent) delete pContent;
81    }
82}
83
84/**
85 * Retrieve Projection model.
86 *
87 * @return Projection model.
88 */
89ProjectionModel* Scene::getModel() const
90{
91    return  m_pModel;
92}
93
94/**
95 * Retrieve name of the scene content.
96 *
97 * @param index Index of the scene content.
98 * @return Name of the scene content.
99 */
100QString Scene::getContentName(int index) const
101{
102    Q_ASSERT(index < m_pContents.size());
103        SceneContent *sc = m_pContents[index];
104        Q_ASSERT(sc);
105        QString name = sc->getFullName();
106        return name;
107}
108
109/**
110 * Retrieve the number of the scene content.
111 *
112 * @return Number of the scene content.
113 */
114unsigned int Scene::getNumContents() const
115{
116    return m_pContents.size();
117}
118
119/**
120 * Retrieve scene content object.
121 *
122 * @param shapeName Name of the scene content object.
123 * @return Scene content object.
124 */
125SceneContent* Scene::getContent(const QString& contentName) const
126{
127    for (int i=0; i<m_pContents.size(); ++i)
128        if (getContentName(i) == contentName)
129                {
130            return m_pContents[i];
131                }
132    return NULL;
133}
134
135/**
136 * Select scene content by name.
137 *
138 * @param contentName Name of the scene content to select.
139 */
140void Scene::setCurrentContent(const QString& contentName)
141{
142    if (m_pCurrentContent && m_pCurrentContent->scene_name() == contentName)
143        return;
144    for (int i=0; i<m_pContents.size(); ++i) {
145        if (m_pContents[i]->getFullName() == contentName) {
146                    m_pCurrentContent = m_pContents[i];
147                    notifyRedraw();
148                }
149    }
150}
151
152/**
153 * Retrieve the name of the current scene content.
154 *
155 * @return Name of the current scene content.
156 */
157QString Scene::getCurrentContentName() const
158{
159        Q_ASSERT(NULL!=m_pCurrentContent);
160    return m_pCurrentContent->getFullName();
161}
162
163/**
164 * Retrieve current scene content object.
165 *
166 * @return Current scene content object.
167 */
168SceneContent* Scene::getCurrentContent() const
169{
170    return m_pCurrentContent;
171}
172
173/**
174 * Set viewpoint of the scene viewer.
175 *
176 * @param data Viewpoint as XML data.
177 */
178void Scene::setCameraViewpoint(const QString& data)
179{
180    Vec3f center;
181    Quatf rot;
182    float distance;
183    QDomDocument doc;
184    doc.setContent(data);
185    QDomElement camera = doc.firstChildElement("Camera");
186    dom2vp(camera, center, rot, distance);
187    setCameraViewpoint(center, rot, distance);
188}
189
190/**
191 * Set viewpoint data.
192 *
193 * @param center Viewpoint center.
194 * @param rot Viewpoint rotation.
195 * @param distance Viewpoint distance from trackball center.
196 */
197void Scene::setCameraViewpoint(const gmtl::Vec3f& center, const gmtl::Quatf& rot, float distance)
198{
199    m_cameraCenter = center;
200    m_cameraRot = rot;
201    m_cameraDistance = distance;
202
203    if (m_pModel->getRSync()->isServer())
204    {
205        QDomDocument doc;
206        doc.appendChild(vp2dom(doc, m_cameraCenter, m_cameraRot, m_cameraDistance));
207        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_VIEWPOINT, doc.toString(0));
208    }
209
210    m_pModel->updateViewAndOffscreens();
211}
212
213/**
214 * Retrieve viewpoint matrix of the scene viewer.
215 *
216 * @return Viewpoint matrix.
217 */
218gmtl::Matrix44f Scene::getCameraMatrix() const
219{
220    return vp2matrix(m_cameraCenter, m_cameraRot, m_cameraDistance);
221}
222
223/**
224 * Put the camera at the center of the scene.
225 */
226void Scene::centerView()
227{
228    m_pModel->getGUI()->sceneCenterView();
229}
230
231/**
232 * Set camera to view all the scene.
233 */
234void Scene::viewAll()
235{
236    m_pModel->getGUI()->sceneViewAll();
237}
238
239/**
240 * Set transform matrix of the scene.
241 *
242 * @param matrix Transform matrix of the scene.
243 */
244void Scene::setMatrix(const TransformMatrix& matrix)
245{
246    m_transformMatrix = matrix;
247    m_pModel->updateViewAndOffscreens();
248}
249
250/**
251 * Draw the scene content.
252 */
253void Scene::draw()
254{
255    glPushAttrib(GL_ALL_ATTRIB_BITS);
256
257    glPushMatrix();
258    glMultMatrixf(m_transformMatrix.getMatrix().getData());
259    m_pCurrentContent->draw(getModel()->getGUI()->getGLWidget(), getCameraMatrix().getData());
260    glPopMatrix();
261
262    glPopAttrib();
263}
264
265/**
266 * Show or hide the scene content in design view.
267 *
268 * @param bShowInDesignView True to show the scene content in design view.
269 */
270void Scene::setShowInDesignView(bool bShowInDesignView)
271{
272    m_bShowInDesignView = bShowInDesignView;
273    notifyRedraw();
274}
275
276/**
277 * Set size of the scene for SceneViewer.
278 *
279 * @param size Size of the scene.
280 */
281void Scene::setSize(float size)
282{
283    m_size = size;
284    m_pModel->getGUI()->setSceneSize(m_size);
285}
286
287/**
288 * Retrieve size of the scene.
289 *
290 * @return Size of the scene.
291 */
292float Scene::getSize() const
293{
294/*
295    Vec3f min, max;
296    m_pCurrentContent->getBoundingBox(min, max);
297    min = m_transformMatrix.getMatrix() * min;
298    max = m_transformMatrix.getMatrix() * max;
299    float minLength = length(min);
300    float maxLength = length(max);
301    return minLength>maxLength?minLength:maxLength;
302*/
303    return m_size;
304}
305
306/**
307 * Show or hide a grid frame with the scene content.
308 *
309 * @param bShowGrid True to show a grid frame, false to hide.
310 */
311void Scene::setShowGrid(bool bShowGrid)
312{
313    m_bShowGrid = bShowGrid;
314    notifyRedraw();
315}
316
317/**
318 * Set size of the grid frame.
319 *
320 * @param gridSize Size of the grid frame.
321 */
322void Scene::setGridSize(float gridSize)
323{
324    m_gridSize = gridSize;
325    notifyRedraw();
326}
327
328/**
329 * Notify to redraw the screen.
330 */
331void Scene::notifyRedraw()
332{
333    if (m_pModel->getRSync()->isServer())
334    {
335        QDomDocument doc;
336        doc.appendChild(domElement("Scene", doc));
337        m_pModel->getRSync()->sendChanges(RSYNC_COMMAND_SCENE, doc.toString(0));
338    }
339
340    m_pModel->getGUI()->updateSceneViewer();
341    m_pModel->updateViewAndOffscreens();
342}
343
344/**
345 * Restore the scene content from XML data.
346 *
347 * @param element Parent XML element of the scene content data.
348 */
349bool Scene::initFromDOMElement(const QDomElement& element)
350{
351    if (!element.isNull())
352    {
353        if (!element.firstChildElement("TransformMatrix").isNull())
354            m_transformMatrix.initFromDOMElement(element.firstChildElement("TransformMatrix"));
355        setCurrentContent(element.attribute("contentName"));
356        m_bShowInDesignView = element.attribute("showInDesignView").toLower()=="true";
357        m_size = element.attribute("size").toFloat();
358        dom2vp(element.firstChildElement("Camera"), m_cameraCenter, m_cameraRot, m_cameraDistance);
359
360        QDomElement contents = element.firstChildElement("Contents");
361        QDomElement content = contents.firstChild().toElement();
362        while (!content.isNull()) {
363            SceneContent* pContent = getContent(content.attribute("name"));
364            if (pContent)
365                pContent->initFromDOMElement(content);
366            content = content.nextSiblingElement();
367        }
368    }
369        else
370        {
371                        reset();
372        }
373
374        return true;    // todo: secure this function and return false on any critical error
375}
376
377/**
378 * Store the current scene content as XML data.
379 *
380 * @param name XML node name of the data.
381 * @param doc XML document to store the data.
382 * @return Current scene content data as XML data.
383 */
384QDomElement Scene::domElement(const QString& name, QDomDocument& doc) const
385{
386    QDomElement de = doc.createElement(name);
387    de.appendChild(m_transformMatrix.domElement("TransformMatrix", doc));
388    de.setAttribute("contentName", getCurrentContentName());
389    de.setAttribute("showInDesignView", (m_bShowInDesignView?"true":"false"));
390    de.setAttribute("size", m_size);
391    de.appendChild(vp2dom(doc, m_cameraCenter, m_cameraRot, m_cameraDistance));
392
393    QDomElement contents = doc.createElement("Contents");
394    for (int i=0; i<m_pContents.size(); ++i)
395        contents.appendChild(m_pContents[i]->domElement("Content", doc));
396    de.appendChild(contents);
397
398    return de;
399}
400
401/**
402 * Update the scene content.
403 *
404 * @param content Scene content from the widget.
405 */
406void Scene::updateSceneContent(const SceneContent& content)
407{
408        Q_ASSERT(m_pCurrentContent->getFullName()==content.getFullName());
409        if (!content.is_equal_to(*m_pCurrentContent))
410        {
411                m_pCurrentContent->copy_from(content);
412                notifyRedraw();
413        }
414}
415
416/**
417 * Reset the scene
418 */
419void Scene::reset()
420{
421        m_transformMatrix.reset();
422        Q_ASSERT(m_pContents.size()>1);
423        m_pCurrentContent = m_pContents[1]; // Teapot (but how to be sure?!)
424    m_bShowInDesignView = true;
425    m_size = 1000.0f;
426    m_cameraDistance = 2.0f;
427    m_cameraRot = makeRot<Quatf>(AxisAnglef(Math::deg2Rad(45.0f), Vec3f(0.0f, 1.0f, 0.0f))) *
428                  makeRot<Quatf>(AxisAnglef(Math::deg2Rad(-45.0f), Vec3f(1.0f, 0.0f, 0.0f)));
429        for (int i=0; i<m_pContents.size(); ++i)
430        m_pContents[i]->reset();
431}
Note: See TracBrowser for help on using the repository browser.