Warning, file /office/calligra/libs/odf/Ko3dScene.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the KDE project
0002  *
0003  * Copyright (C) 2012 Inge Wallin <inge@lysator.liu.se>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 // Own
0022 #include "Ko3dScene.h"
0023 
0024 #include "OdfDebug.h"
0025 
0026 // Calligra
0027 #include <KoXmlReader.h>
0028 #include <KoXmlNS.h>
0029 #include <KoXmlWriter.h>
0030 
0031 
0032 static QVector3D odfToVector3D(const QString &string);
0033 
0034 
0035 
0036 // ----------------------------------------------------------------
0037 //                         Ko3dScene::Private
0038 
0039 
0040 class Q_DECL_HIDDEN Ko3dScene::Private
0041 {
0042 public:
0043     Private() {};
0044     ~Private() {};
0045 
0046     // Camera attributes
0047     QVector3D vrp;          // Camera origin
0048     QVector3D vpn;          // Camera direction
0049     QVector3D vup;          // Up direction
0050     Projection projection;
0051     QString distance;
0052     QString focalLength;
0053     QString shadowSlant;
0054 
0055     // Rendering attributes
0056     Shademode shadeMode;
0057     QColor ambientColor;
0058     bool lightingMode; // True: enable lights, false: disable lights
0059     QString transform;
0060 
0061     // Lightsources (these are children of the element, not attributes)
0062     QVector<Lightsource> lights;
0063 };
0064 
0065 
0066 // ----------------------------------------------------------------
0067 //                         Lightsource
0068 
0069 
0070 Ko3dScene::Lightsource::Lightsource()
0071 {
0072 }
0073 
0074 Ko3dScene::Lightsource::~Lightsource()
0075 {
0076 }
0077 
0078 
0079 // getters
0080 QColor Ko3dScene::Lightsource::diffuseColor() const { return m_diffuseColor; }
0081 QVector3D Ko3dScene::Lightsource::direction() const { return m_direction; }
0082 bool Ko3dScene::Lightsource::enabled() const { return m_enabled; }
0083 bool Ko3dScene::Lightsource::specular() const { return m_specular; }
0084 
0085 // setters
0086 void
0087 Ko3dScene::Lightsource::setDiffuseColor(const QColor &color)
0088 {
0089     m_diffuseColor = color;
0090 }
0091 
0092 void
0093 Ko3dScene::Lightsource::setDirection(const QVector3D &direction)
0094 {
0095     m_direction = direction;
0096 }
0097 
0098 void
0099 Ko3dScene::Lightsource::setEnabled(const bool enabled)
0100 {
0101     m_enabled = enabled;
0102 }
0103 
0104 void
0105 Ko3dScene::Lightsource::setSpecular(const bool specular)
0106 {
0107     m_specular = specular;
0108 }
0109 
0110 
0111 bool Ko3dScene::Lightsource::loadOdf(const KoXmlElement &lightElement)
0112 {
0113     m_diffuseColor = QColor(lightElement.attributeNS(KoXmlNS::dr3d, "diffuse-color", "#ffffff"));
0114     QString direction = lightElement.attributeNS(KoXmlNS::dr3d, "direction");
0115     m_direction = odfToVector3D(direction);
0116     m_enabled = (lightElement.attributeNS(KoXmlNS::dr3d, "enabled") == "true");
0117     m_specular = (lightElement.attributeNS(KoXmlNS::dr3d, "specular") == "true");
0118 
0119     return true;
0120 }
0121 
0122 void Ko3dScene::Lightsource::saveOdf(KoXmlWriter &writer) const
0123 {
0124     writer.startElement("dr3d:light");
0125 
0126     writer.addAttribute("dr3d:diffuse-color", m_diffuseColor.name());
0127     writer.addAttribute("dr3d:direction", (QString("(%1 %2 %3)")
0128                                            .arg(m_direction.x(), 0, 'f', 11)
0129                                            .arg(m_direction.y(), 0, 'f', 11)
0130                                            .arg(m_direction.z(), 0, 'f', 11)));
0131     writer.addAttribute("dr3d:enabled", m_enabled);
0132     writer.addAttribute("dr3d:specular", m_specular);
0133 
0134     writer.endElement(); // dr3d:light
0135 }
0136 
0137 
0138 // ----------------------------------------------------------------
0139 //                         Ko3dScene
0140 
0141 
0142 Ko3dScene::Ko3dScene()
0143     : d(new Private())
0144 {
0145 }
0146 
0147 Ko3dScene::~Ko3dScene()
0148 {
0149     delete d;
0150 }
0151 
0152 
0153 // getters
0154 QVector3D Ko3dScene::vrp() const { return d->vrp; }
0155 QVector3D Ko3dScene::vpn() const { return d->vpn; }
0156 QVector3D Ko3dScene::vup() const { return d->vup; }
0157 Ko3dScene::Projection  Ko3dScene::projection() const { return d->projection; }
0158 QString Ko3dScene::distance() const { return d->distance; }
0159 QString Ko3dScene::focalLength() const { return d->focalLength; }
0160 QString Ko3dScene::shadowSlant() const { return d->shadowSlant; }
0161 Ko3dScene::Shademode   Ko3dScene::shadeMode() const { return d->shadeMode; }
0162 QColor Ko3dScene::ambientColor() const { return d->ambientColor; }
0163 bool Ko3dScene::lightingMode() const { return d->lightingMode; }
0164 QString Ko3dScene::transform() const { return d->transform; }
0165 
0166     // setters
0167 void Ko3dScene::setVrp(const QVector3D &vrp) { d->vrp = vrp; }
0168 void Ko3dScene::setVpn(const QVector3D &vpn) { d->vpn = vpn; }
0169 void Ko3dScene::setVup(const QVector3D &vup) { d->vup = vup; }
0170 void Ko3dScene::setProjection(Projection projection) { d->projection = projection; }
0171 void Ko3dScene::setDistance(const QString &distance) { d->distance = distance; }
0172 void Ko3dScene::setFocalLength(const QString &focalLength) { d->focalLength = focalLength; }
0173 void Ko3dScene::setShadowSlant(const QString &shadowSlant) { d->shadowSlant = shadowSlant; }
0174 void Ko3dScene::setShadeMode(Shademode shadeMode) { d->shadeMode = shadeMode; }
0175 void Ko3dScene::setAmbientColor(const QColor &ambientColor) { d->ambientColor = ambientColor; }
0176 void Ko3dScene::setLightingMode(bool lightingMode) { d->lightingMode = lightingMode; }
0177 void Ko3dScene::setTransform(const QString &transform) { d->transform = transform; }
0178 
0179 
0180 bool Ko3dScene::loadOdf(const KoXmlElement &sceneElement)
0181 {
0182     QString dummy;
0183 
0184     // Check if there is a 3d scene at all in this element. We
0185     // approximate that by checking if there are any camera parameters.
0186     if (!sceneElement.hasAttributeNS(KoXmlNS::dr3d, "vrp")
0187         && !sceneElement.hasAttributeNS(KoXmlNS::dr3d, "vpn")
0188         && !sceneElement.hasAttributeNS(KoXmlNS::dr3d, "vup"))
0189     {
0190         return false;
0191     }
0192 
0193     // 1. Load the scene attributes.
0194 
0195     // Camera attributes
0196     dummy = sceneElement.attributeNS(KoXmlNS::dr3d, "vrp");
0197     d->vrp = odfToVector3D(dummy);
0198     dummy = sceneElement.attributeNS(KoXmlNS::dr3d, "vpn");
0199     d->vpn = odfToVector3D(dummy);
0200     dummy = sceneElement.attributeNS(KoXmlNS::dr3d, "vup", "(0.0 0.0 1.0)");
0201     d->vup = odfToVector3D(dummy);
0202 
0203     dummy = sceneElement.attributeNS(KoXmlNS::dr3d, "projection", "perspective");
0204     if (dummy == "parallel") {
0205         d->projection = Parallel;
0206     }
0207     else {
0208         d->projection = Perspective;
0209     }
0210 
0211     d->distance = sceneElement.attributeNS(KoXmlNS::dr3d, "distance");
0212     d->focalLength = sceneElement.attributeNS(KoXmlNS::dr3d, "focal-length");
0213     d->shadowSlant = sceneElement.attributeNS(KoXmlNS::dr3d, "shadow-slant");
0214     d->ambientColor = QColor(sceneElement.attributeNS(KoXmlNS::dr3d, "ambient-color", "#888888"));
0215 
0216     // Rendering attributes
0217     dummy = sceneElement.attributeNS(KoXmlNS::dr3d, "shade-mode", "gouraud");
0218     if (dummy == "flat") {
0219         d->shadeMode = Flat;
0220     }
0221     else if (dummy == "phong") {
0222         d->shadeMode = Phong;
0223     }
0224     else if (dummy == "draft") {
0225         d->shadeMode = Draft;
0226     }
0227     else {
0228         d->shadeMode = Gouraud;
0229     }
0230 
0231     d->lightingMode = (sceneElement.attributeNS(KoXmlNS::dr3d, "lighting-mode") == "true");
0232     d->transform = sceneElement.attributeNS(KoXmlNS::dr3d, "transform");
0233 
0234     // 2. Load the light sources.
0235 
0236     // From the ODF 1.1 spec section 9.4.1:
0237     KoXmlElement elem;
0238     forEachElement(elem, sceneElement) {
0239         if (elem.localName() == "light" && elem.namespaceURI() == KoXmlNS::dr3d) {
0240             Lightsource  light;
0241             light.loadOdf(elem);
0242             d->lights.append(light);
0243         }
0244     }
0245 
0246     //debugOdf << "Lights:" << d->lights.size();
0247 
0248     return true;
0249 }
0250 
0251 void Ko3dScene::saveOdfAttributes(KoXmlWriter &writer) const
0252 {
0253     // 1. Write scene attributes
0254     // Camera attributes
0255     writer.addAttribute("dr3d:vrp", (QString("(%1 %2 %3)")
0256                                      .arg(d->vrp.x(), 0, 'f', 11)
0257                                      .arg(d->vrp.y(), 0, 'f', 11)
0258                                      .arg(d->vrp.z(), 0, 'f', 11)));
0259     writer.addAttribute("dr3d:vpn", (QString("(%1 %2 %3)")
0260                                      .arg(d->vpn.x(), 0, 'f', 11)
0261                                      .arg(d->vpn.y(), 0, 'f', 11)
0262                                      .arg(d->vpn.z(), 0, 'f', 11)));
0263     writer.addAttribute("dr3d:vup", (QString("(%1 %2 %3)")
0264                                      .arg(d->vup.x(), 0, 'f', 11)
0265                                      .arg(d->vup.y(), 0, 'f', 11)
0266                                      .arg(d->vup.z(), 0, 'f', 11)));
0267 
0268     writer.addAttribute("dr3d:projection", (d->projection == Parallel) ? "parallel" : "perspective");
0269 
0270     writer.addAttribute("dr3d:distance", d->distance);
0271     writer.addAttribute("dr3d:focal-length", d->focalLength);
0272     writer.addAttribute("dr3d:shadow-slant", d->shadowSlant);
0273     writer.addAttribute("dr3d:ambient-color", d->ambientColor.name());
0274 
0275     // Rendering attributes
0276     switch (d->shadeMode) {
0277     case Flat:
0278         writer.addAttribute("dr3d:shade-mode", "flat");
0279         break;
0280     case Phong:
0281         writer.addAttribute("dr3d:shade-mode", "phong");
0282         break;
0283     case Draft:
0284         writer.addAttribute("dr3d:shade-mode", "draft");
0285         break;
0286     case Gouraud:
0287     default:
0288         writer.addAttribute("dr3d:shade-mode", "gouraud");
0289         break;
0290     }
0291 
0292     writer.addAttribute("dr3d:lighting-mode", d->lightingMode);
0293     writer.addAttribute("dr3d:transform", d->transform);
0294 }
0295 
0296 
0297 void Ko3dScene::saveOdfChildren(KoXmlWriter &writer) const
0298 {
0299     // Write light sources.
0300     foreach (const Lightsource &light, d->lights) {
0301         light.saveOdf(writer);
0302     }
0303 }
0304 
0305 
0306 // ----------------------------------------------------------------
0307 //                         Public functions
0308 
0309 
0310 KOODF_EXPORT Ko3dScene *load3dScene(const KoXmlElement &element)
0311 {
0312     Ko3dScene *scene = new Ko3dScene();
0313 
0314     if (scene->loadOdf(element)) {
0315         return scene;
0316     }
0317 
0318     delete scene;
0319     return 0;
0320 }
0321 
0322 
0323 // ----------------------------------------------------------------
0324 //                         Static functions
0325 
0326 
0327 QVector3D odfToVector3D(const QString &string)
0328 {
0329     // The string comes into this function in the form "(0 3.5 0.3)".
0330     QStringList elements = string.mid(1, string.size() - 2).split(' ', QString::SkipEmptyParts);
0331     if (elements.size() == 3) {
0332         return QVector3D(elements[0].toDouble(), elements[1].toDouble(), elements[2].toDouble());
0333     }
0334     else {
0335         return QVector3D(0, 0, 1);
0336     }
0337 }