/* * Mapper.cpp * * (c) 2013 Sofian Audry -- info(@)sofianaudry(.)com * (c) 2013 Alexandre Quessy -- alexandre(@)quessy(.)net * * 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 . */ #include "Mapper.h" Mapper::Mapper(Mapping::ptr mapping) : _mapping(mapping) { outputShape = mapping->getShape(); Q_CHECK_PTR(outputShape); // Create editor. _propertyBrowser = new QtTreePropertyBrowser; _variantManager = new QtVariantPropertyManager; _variantFactory = new QtVariantEditorFactory; _topItem = _variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), QObject::tr("Texture mapping")); _propertyBrowser->setFactoryForManager(_variantManager, _variantFactory); // Output shape. _outputItem = _variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), QObject::tr("Output shape")); _buildShapeProperty(_outputItem, mapping->getShape().get()); _topItem->addSubProperty(_outputItem); connect(_variantManager, SIGNAL(valueChanged(QtProperty*, const QVariant&)), this, SLOT(setValue(QtProperty*, const QVariant&))); _propertyBrowser->addProperty(_topItem); qDebug() << "Creating mapper" << endl; } Mapper::~Mapper() { delete _propertyBrowser; } QWidget* Mapper::getPropertiesEditor() { return _propertyBrowser; } void Mapper::drawShapeContour(QPainter* painter, const Shape& shape, int lineWidth, const QColor& color) { Q_UNUSED(painter); QColor rgbColor = color.toRgb(); glColor4f(rgbColor.redF(), rgbColor.greenF(), rgbColor.blueF(), 1.0f); glLineWidth(lineWidth); glBegin (GL_LINE_STRIP); for (int i = 0; i < shape.nVertices()+1; i++) { const QPointF& v = shape.getVertex(i % shape.nVertices()); glVertex2f( v.x(), v.y() ); } glEnd(); } TextureMapper::TextureMapper(std::tr1::shared_ptr mapping) : Mapper(mapping) { // Assign members pointers. textureMapping = std::tr1::static_pointer_cast(_mapping); Q_CHECK_PTR(textureMapping); texture = std::tr1::static_pointer_cast(textureMapping->getPaint()); Q_CHECK_PTR(texture); inputShape = std::tr1::static_pointer_cast(textureMapping->getInputShape()); Q_CHECK_PTR(inputShape); // Input shape. _inputItem = _variantManager->addProperty(QtVariantPropertyManager::groupTypeId(), QObject::tr("Input shape")); _buildShapeProperty(_inputItem, textureMapping->getInputShape().get()); _topItem->insertSubProperty(_inputItem, 0); // insert before output item } void Mapper::setValue(QtProperty* property, const QVariant& value) { std::map >::iterator it = _propertyToVertex.find(property); if (it != _propertyToVertex.end()) { const QPointF& p = value.toPointF(); Shape* shape = it->second.first; int v = it->second.second; if (shape->getVertex(v) != p) { shape->setVertex(v, p); emit valueChanged(); } } } void Mapper::_buildShapeProperty(QtProperty* shapeItem, Shape* shape) { for (int i=0; inVertices(); i++) { // Add point. QtVariantProperty* pointItem = _variantManager->addProperty(QVariant::PointF, QObject::tr("Point %1").arg(i)); const QPointF& p = shape->getVertex(i); pointItem->setValue(p); shapeItem->addSubProperty(pointItem); _propertyToVertex[pointItem] = std::make_pair(shape, i); } } void Mapper::_updateShapeProperty(QtProperty* shapeItem, Shape* shape) { QList pointItems = shapeItem->subProperties(); for (int i=0; inVertices(); i++) { // XXX mesh control points are not added to properties if (i < pointItems.size()) { QtVariantProperty* pointItem = (QtVariantProperty*)pointItems[i]; const QPointF& p = shape->getVertex(i); pointItem->setValue(p); } } } ColorMapper::ColorMapper(Mapping::ptr mapping) : Mapper(mapping) { color = std::tr1::static_pointer_cast(_mapping->getPaint()); Q_CHECK_PTR(color); } #include "MainWindow.h" void ColorMapper::draw(QPainter* painter) { painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); painter->setBrush(color->getColor()); // Draw shape as polygon. painter->drawPolygon(_mapping->getShape()->toPolygon()); } void ColorMapper::drawControls(QPainter* painter) { } MeshColorMapper::MeshColorMapper(Mapping::ptr mapping) : ColorMapper(mapping) { // Add mesh sub property. Mesh* mesh = (Mesh*)mapping->getShape().get(); _meshItem = _variantManager->addProperty(QVariant::Size, QObject::tr("Dimensions")); _meshItem->setValue(QSize(mesh->nColumns(), mesh->nRows())); _topItem->insertSubProperty(_meshItem, 0); // insert at the beginning } void MeshColorMapper::draw(QPainter* painter) { painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); painter->setBrush(color->getColor()); std::tr1::shared_ptr outputMesh = std::tr1::static_pointer_cast(outputShape); QVector > outputQuads = outputMesh->getQuads2d(); for (int x = 0; x < outputMesh->nHorizontalQuads(); x++) { for (int y = 0; y < outputMesh->nVerticalQuads(); y++) { Quad& outputQuad = outputQuads[x][y]; painter->drawPolygon(outputQuad.toPolygon()); } } } void MeshColorMapper::drawControls(QPainter* painter) { std::tr1::shared_ptr outputMesh = std::tr1::static_pointer_cast(outputShape); QVector outputQuads = outputMesh->getQuads(); for (QVector::const_iterator it = outputQuads.begin(); it != outputQuads.end(); ++it) { drawShapeContour(painter, *it, 1, QColor(0, 0, 255)); } } void MeshColorMapper::setValue(QtProperty* property, const QVariant& value) { if (property == _meshItem) { Mesh* outputMesh = static_cast(_mapping->getShape().get()); QSize size = (static_cast(property))->value().toSize(); if (outputMesh->nColumns() != size.width() || outputMesh->nRows() != size.height()) { outputMesh->resize(size.width(), size.height()); emit valueChanged(); } } else ColorMapper::setValue(property, value); } EllipseColorMapper::EllipseColorMapper(Mapping::ptr mapping) : ColorMapper(mapping) { } void EllipseColorMapper::draw(QPainter* painter) { painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); painter->setBrush(color->getColor()); std::tr1::shared_ptr outputEllipse = std::tr1::static_pointer_cast(outputShape); qreal rotation = outputEllipse->getRotation(); qDebug() << "Rotation: " << rotation << endl; painter->save(); // save painter state painter->resetTransform(); painter->setBrush(color->getColor()); const QPointF& center = outputEllipse->getCenter(); float rx = outputEllipse->getHorizontalAxis().length() / 2; float ry = outputEllipse->getVerticalAxis().length() / 2; painter->translate(center); painter->rotate(rotation); painter->drawEllipse(QPointF(0,0), rx, ry); painter->resetTransform(); for (int i=0; i<4; i++) { if (i==0) painter->setBrush(QColor("#333333")); else if (i==1) painter->setBrush(QColor("#777777")); else if (i==2) painter->setBrush(QColor("#aaaaaa")); else painter->setBrush(QColor("#ffffff")); painter->drawEllipse(outputEllipse->getVertex(i), 5, 5); painter->drawStaticText(outputEllipse->getVertex(i), QString(i)); } painter->restore(); // restore saved painter state } void TextureMapper::updateShape(Shape* shape) { std::tr1::shared_ptr textureMapping = std::tr1::static_pointer_cast(_mapping); Q_CHECK_PTR(textureMapping); std::tr1::shared_ptr texture = std::tr1::static_pointer_cast(textureMapping->getPaint()); Q_CHECK_PTR(texture); Shape* inputShape = textureMapping->getInputShape().get(); Shape* outputShape = textureMapping->getShape().get(); if (shape == inputShape) { _updateShapeProperty(_inputItem, inputShape); } else if (shape == outputShape) { _updateShapeProperty(_outputItem, outputShape); } } void TextureMapper::draw(QPainter* painter) { painter->beginNativePainting(); // Only works for similar shapes. Q_ASSERT( outputShape->nVertices() == outputShape->nVertices()); // Project source texture and sent it to destination. glEnable (GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture->getTextureId()); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->getWidth(), texture->getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->getBits()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // Perform the actual mapping (done by subclasses). _doDraw(painter); glDisable(GL_TEXTURE_2D); painter->endNativePainting(); } void TextureMapper::drawInput(QPainter* painter) { } void TextureMapper::drawControls(QPainter* painter) { drawShapeContour(painter, *outputShape, 3, QColor(0, 0, 255)); } void TextureMapper::drawInputControls(QPainter* painter) { drawShapeContour(painter, *inputShape, 3, QColor(0, 0, 255)); } TriangleTextureMapper::TriangleTextureMapper(std::tr1::shared_ptr mapping) : TextureMapper(mapping) { } void TriangleTextureMapper::_doDraw(QPainter* painter) { glBegin(GL_TRIANGLES); { for (int i = 0; i < inputShape->nVertices(); i++) { const QPointF& inputPoint = inputShape->getVertex(i); const QPointF& outputPoint = outputShape->getVertex(i); Util::correctGlTexCoord( (inputPoint.x() - texture->getX()) / (GLfloat) texture->getWidth(), (inputPoint.y() - texture->getY()) / (GLfloat) texture->getHeight()); glVertex2f( outputPoint.x(), outputPoint.y() ); } } glEnd(); } MeshTextureMapper::MeshTextureMapper(std::tr1::shared_ptr mapping) : TextureMapper(mapping) { // Add mesh sub property. Mesh* mesh = (Mesh*)textureMapping->getShape().get(); _meshItem = _variantManager->addProperty(QVariant::Size, QObject::tr("Dimensions")); _meshItem->setValue(QSize(mesh->nColumns(), mesh->nRows())); _topItem->insertSubProperty(_meshItem, 0); // insert at the beginning } void MeshTextureMapper::setValue(QtProperty* property, const QVariant& value) { if (property == _meshItem) { std::tr1::shared_ptr textureMapping = std::tr1::static_pointer_cast(_mapping); Q_CHECK_PTR(textureMapping); Mesh* outputMesh = static_cast(textureMapping->getShape().get()); Mesh* inputMesh = static_cast(textureMapping->getInputShape().get()); QSize size = (static_cast(property))->value().toSize(); if (outputMesh->nColumns() != size.width() || outputMesh->nRows() != size.height() || inputMesh->nColumns() != size.width() || inputMesh->nRows() != size.height()) { outputMesh->resize(size.width(), size.height()); inputMesh->resize(size.width(), size.height()); emit valueChanged(); } } else TextureMapper::setValue(property, value); } void MeshTextureMapper::drawControls(QPainter* painter) { std::tr1::shared_ptr outputMesh = std::tr1::static_pointer_cast(outputShape); QVector outputQuads = outputMesh->getQuads(); for (QVector::const_iterator it = outputQuads.begin(); it != outputQuads.end(); ++it) { drawShapeContour(painter, *it, 1, QColor(0, 0, 255)); } } void MeshTextureMapper::drawInputControls(QPainter* painter) { std::tr1::shared_ptr inputMesh = std::tr1::static_pointer_cast(inputShape); QVector inputQuads = inputMesh->getQuads(); for (QVector::const_iterator it = inputQuads.begin(); it != inputQuads.end(); ++it) { drawShapeContour(painter, *it, 1, QColor(0, 0, 255)); } } void MeshTextureMapper::_doDraw(QPainter* painter) { std::tr1::shared_ptr outputMesh = std::tr1::static_pointer_cast(outputShape); std::tr1::shared_ptr inputMesh = std::tr1::static_pointer_cast(inputShape); QVector > outputQuads = outputMesh->getQuads2d(); QVector > inputQuads = inputMesh->getQuads2d(); for (int x = 0; x < outputMesh->nHorizontalQuads(); x++) { for (int y = 0; y < outputMesh->nVerticalQuads(); y++) { Quad& outputQuad = outputQuads[x][y]; Quad& inputQuad = inputQuads[x][y]; glBegin(GL_QUADS); for (int i = 0; i < 4; i++) { const QPointF& inputPoint = inputQuad.getVertex(i); const QPointF& outputPoint = outputQuad.getVertex(i); Util::correctGlTexCoord( (inputPoint.x() - texture->getX()) / (GLfloat) texture->getWidth(), (inputPoint.y() - texture->getY()) / (GLfloat) texture->getHeight()); glVertex2f( outputPoint.x(), outputPoint.y() ); } glEnd(); } } }