From 0b027f29f301c139f1357194cac2284016bfaa28 Mon Sep 17 00:00:00 2001 From: Tats Date: Sun, 2 Mar 2014 17:02:52 -0500 Subject: [PATCH] Implemented basic support for texture ellipse (works, default center point, no drawing of control points). --- MainWindow.cpp | 44 ++++++++++++++++++++++++----- MainWindow.h | 7 +++++ Mapper.cpp | 72 ++++++++++++++++++++++++++++++++++++++++++++++++ Mapper.h | 15 ++++++++++ Math.h | 31 +++++++++++++++++++++ Shape.h | 11 ++++++-- libremapping.pro | 1 + 7 files changed, 172 insertions(+), 9 deletions(-) create mode 100644 Math.h diff --git a/MainWindow.cpp b/MainWindow.cpp index 9a05c22..e655537 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -303,12 +303,12 @@ void MainWindow::addEllipse() } else { -// std::tr1::shared_ptr texture = std::tr1::static_pointer_cast(paint); -// Q_CHECK_PTR(texture); -// -// Shape::ptr outputEllipse = Shape::ptr(Util::createEllipseForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height())); -// Shape::ptr inputEllipse = Shape::ptr(Util::createEllipseForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height())); -// mappingPtr = new TextureMapping(paint, inputEllipse, outputEllipse); + std::tr1::shared_ptr texture = std::tr1::static_pointer_cast(paint); + Q_CHECK_PTR(texture); + + Shape::ptr outputEllipse = Shape::ptr(Util::createEllipseForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height())); + Shape::ptr inputEllipse = Shape::ptr(Util::createEllipseForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height())); + mappingPtr = new TextureMapping(paint, inputEllipse, outputEllipse); } // Create mapping. @@ -505,6 +505,36 @@ uid MainWindow::createTriangleTextureMapping(uid mappingId, } } +uid MainWindow::createEllipseTextureMapping(uid mappingId, + uid paintId, + const QVector &src, const QVector &dst) +{ + // Cannot create element with already existing id or element for which no paint exists. + if (Mapping::getUidAllocator().exists(mappingId) || + !Paint::getUidAllocator().exists(paintId) || + paintId == NULL_UID) + return NULL_UID; + + else + { + Paint::ptr paint = mappingManager->getPaintById(paintId); + Q_ASSERT(src.size() == 4 && dst.size() == 4); + + Shape::ptr inputEllipse( new Ellipse(src[0], src[1], src[2], dst[3])); + Shape::ptr outputEllipse(new Ellipse(dst[0], dst[1], dst[2], dst[3])); + + // Add it to the manager. + Mapping::ptr mapping(new TextureMapping(paint, inputEllipse, outputEllipse, mappingId)); + uid id = mappingManager->addMapping(mapping); + + // Add it to the GUI. + addMappingItem(mappingId); + + // Return the id. + return id; + } +} + uid MainWindow::createQuadColorMapping(uid mappingId, uid paintId, const QVector &dst) @@ -1087,7 +1117,7 @@ void MainWindow::addMappingItem(uint mappingId) if (paintType == "color") mapper = Mapper::ptr(new EllipseColorMapper(mapping)); else - mapper = Mapper::ptr(new MeshTextureMapper(textureMapping)); + mapper = Mapper::ptr(new EllipseTextureMapper(textureMapping)); } else { diff --git a/MainWindow.h b/MainWindow.h index 622753a..1b532b3 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -115,6 +115,13 @@ public slots: const QVector &src, const QVector &dst); + /** + * Creates a textured ellipse. + */ + uid createEllipseTextureMapping(uid mappingId, + uid paintId, + const QVector &src, const QVector &dst); + /** * Creates a color quad. */ diff --git a/Mapper.cpp b/Mapper.cpp index a2c09dd..4b3d532 100644 --- a/Mapper.cpp +++ b/Mapper.cpp @@ -419,3 +419,75 @@ void MeshTextureMapper::_doDraw(QPainter* painter) } } +EllipseTextureMapper::EllipseTextureMapper(std::tr1::shared_ptr mapping) +: TextureMapper(mapping) +{ +} + +void EllipseTextureMapper::_doDraw(QPainter* painter) +{ + // Get input and output ellipses. + std::tr1::shared_ptr inputEllipse = std::tr1::static_pointer_cast(inputShape); + std::tr1::shared_ptr outputEllipse = std::tr1::static_pointer_cast(outputShape); + + // Start / end angle. + const float startAngle = 0; + const float endAngle = 2*M_PI; + + // + float angle; + QPointF currentInputPoint; + QPointF prevInputPoint(0, 0); + QPointF currentOutputPoint; + QPointF prevOutputPoint(0, 0); + + // References for performance. + const QPointF& inputCenter = inputEllipse->getCenter(); + float inputHorizRadius = inputEllipse->getHorizontalAxis().length() / 2; + float inputVertRadius = inputEllipse->getVerticalAxis().length() / 2; + float inputRotation = inputEllipse->getRotationRadians(); + + const QPointF& outputCenter = outputEllipse->getCenter(); + float outputHorizRadius = outputEllipse->getHorizontalAxis().length() / 2; + float outputVertRadius = outputEllipse->getVerticalAxis().length() / 2; + float outputRotation = outputEllipse->getRotationRadians(); + + // Variation in angle at each step of the loop. + const int N_TRIANGLES = 100; + const float ANGLE_STEP = 2*M_PI/N_TRIANGLES; + + float circleAngle = 0; + for (int i=0; i<=N_TRIANGLES; i++, circleAngle += ANGLE_STEP) + { + // Set next (current) points. + _setPointOfEllipseAtAngle(currentInputPoint, inputCenter, inputHorizRadius, inputVertRadius, inputRotation, circleAngle); + _setPointOfEllipseAtAngle(currentOutputPoint, outputCenter, outputHorizRadius, outputVertRadius, outputRotation, circleAngle); + + if (i > 0) + { + // Draw triangle. + glBegin(GL_TRIANGLES); + Util::setGlTexPoint(*texture, inputCenter, outputCenter); + Util::setGlTexPoint(*texture, prevInputPoint, prevOutputPoint); + Util::setGlTexPoint(*texture, currentInputPoint, currentOutputPoint); + glEnd(); + } + + prevInputPoint.setX(currentInputPoint.x()); + prevInputPoint.setY(currentInputPoint.y()); + + prevOutputPoint.setX(currentOutputPoint.x()); + prevOutputPoint.setY(currentOutputPoint.y()); + } +} + +void EllipseTextureMapper::_setPointOfEllipseAtAngle(QPointF& point, const QPointF& center, float hRadius, float vRadius, float rotation, float circularAngle) +{ + float xCirc = sin(circularAngle) * hRadius; + float yCirc = cos(circularAngle) * vRadius; + float distance = sqrt( xCirc*xCirc + yCirc*yCirc ); + float angle = atan2( xCirc, yCirc ); + point.setX( sin(angle + 2*M_PI-rotation) * distance + center.x() ); + point.setY( cos(angle + 2*M_PI-rotation) * distance + center.y() ); +} + diff --git a/Mapper.h b/Mapper.h index 378f16a..f3e2b35 100644 --- a/Mapper.h +++ b/Mapper.h @@ -217,4 +217,19 @@ private: QtVariantProperty* _meshItem; }; +class EllipseTextureMapper : public TextureMapper { + Q_OBJECT + +public: + EllipseTextureMapper(std::tr1::shared_ptr mapping); + virtual ~EllipseTextureMapper() {} + +// static void drawRotatedEllipse(float centerX, float centerY, float w, float h, float rotation, float baseRes); + +protected: + virtual void _doDraw(QPainter* painter); + static void _setPointOfEllipseAtAngle(QPointF& point, const QPointF& center, float hRadius, float vRadius, float rotation, float circularAngle); +}; + + #endif /* MAPPER_H_ */ diff --git a/Math.h b/Math.h new file mode 100644 index 0000000..5765845 --- /dev/null +++ b/Math.h @@ -0,0 +1,31 @@ +/* + * Math.h + * + * (c) 2014 Sofian Audry -- info(@)sofianaudry(.)com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef MATH_H_ +#define MATH_H_ + +#include + +inline float degreesToRadians(float degrees) { return degrees / 180.0f * M_PI; } +inline double degreesToRadians(double degrees) { return degrees / 180.0 * M_PI; } +inline float radiansToDegrees(float radians) { return radians * M_PI / 180.0f; } +inline double radiansToDegrees(double radians) { return radians * M_PI / 180.0; } + +#endif /* MATH_H_ */ diff --git a/Shape.h b/Shape.h index 445c9fd..eae9495 100644 --- a/Shape.h +++ b/Shape.h @@ -25,6 +25,7 @@ #include #include + #include #include #include @@ -35,6 +36,8 @@ #include #include +#include "Math.h" + /** * Point (or vertex) on the 2-D canvas. */ @@ -216,9 +219,13 @@ public: virtual QString getType() const { return "ellipse"; } - qreal getRotation() const { + qreal getRotationRadians() const { QVector2D hAxis = getHorizontalAxis(); - return atan2(hAxis.y(), hAxis.x()) * 180.0 / M_PI; + return atan2( hAxis.y(), hAxis.x() ); + } + + qreal getRotation() const { + return radiansToDegrees( getRotationRadians() ); } // QRect getBoundingRect() const { diff --git a/libremapping.pro b/libremapping.pro index e6716f6..fefe88a 100644 --- a/libremapping.pro +++ b/libremapping.pro @@ -9,6 +9,7 @@ HEADERS = \ MapperGLCanvas.h \ Mapping.h \ MappingManager.h \ + Math.h \ # NameAllocator.h \ Paint.h \ ProjectReader.h \