Exemplo n.º 1
0
// 0___1___2___3
// |  /|  /|  /|
// | / | / | / |
// |/  |/  |/  |
// 4---5---6----7
// |  /|  /|  /|
// | / | / | / |
// |/  |/  |/  |
// 8---9--10--11
// |  /|  /|  /|
// | / | / | / |
// |/  |/  |/  |
// 12--13--14--15
void
ViewerGL::Implementation::drawRenderingVAO(unsigned int mipMapLevel,
                                           int textureIndex,
                                           ViewerGL::DrawPolygonModeEnum polygonMode,
                                           bool background)
{
    // always running in the main thread
    assert( qApp && qApp->thread() == QThread::currentThread() );
    assert( QGLContext::currentContext() == _this->context() );

    bool useShader = _this->getBitDepth() != eImageBitDepthByte;


    ///the texture rectangle in image coordinates. The values in it are multiples of tile size.
    ///
    const TextureRect &roiRounded = this->displayTextures[textureIndex].texture->getTextureRect();
    const TextureRect& roiNotRounded = this->displayTextures[textureIndex].roiNotRoundedToTileSize;

    ///This is the coordinates in the image being rendered where datas are valid, this is in pixel coordinates
    ///at the time we initialize it but we will convert it later to canonical coordinates. See 1)
    const double par = roiRounded.par;
    RectD canonicalRoIRoundedToTileSize;
    roiRounded.toCanonical_noClipping(mipMapLevel, par /*, rod*/, &canonicalRoIRoundedToTileSize);

    RectD canonicalRoINotRounded;
    roiNotRounded.toCanonical_noClipping(mipMapLevel, par, &canonicalRoINotRounded);

    ///the RoD of the image in canonical coords.
    RectD rod = _this->getRoD(textureIndex);

    bool clipToDisplayWindow;
    {
        QMutexLocker l(&this->clipToDisplayWindowMutex);
        clipToDisplayWindow = this->clipToDisplayWindow;
    }
    RectD rectClippedToRoI(canonicalRoIRoundedToTileSize);
    rectClippedToRoI.intersect(rod, &rectClippedToRoI);


    if (clipToDisplayWindow) {
        RectD canonicalProjectFormat;
        this->getProjectFormatCanonical(canonicalProjectFormat);
        rod.intersect(canonicalProjectFormat, &rod);
        rectClippedToRoI.intersect(canonicalProjectFormat, &rectClippedToRoI);
    }

    


    //if user RoI is enabled, clip the rod to that roi
    bool userRoiEnabled;
    {
        QMutexLocker l(&this->userRoIMutex);
        userRoiEnabled = this->userRoIEnabled;
    }


    ////The texture real size (r.w,r.h) might be slightly bigger than the actual
    ////pixel coordinates bounds r.x1,r.x2 r.y1 r.y2 because we clipped these bounds against the bounds
    ////in the ViewerInstance::renderViewer function. That means we need to draw actually only the part of
    ////the texture that contains the bounds.
    ////Notice that r.w and r.h are scaled to the closest Po2 of the current scaling factor, so we need to scale it up
    ////So it is in the same coordinates as the bounds.
    ///Edit: we no longer divide by the closestPo2 since the viewer now computes images at lower resolution by itself, the drawing
    ///doesn't need to be scaled.

    if (userRoiEnabled) {
        {
            QMutexLocker l(&this->userRoIMutex);
            //if the userRoI isn't intersecting the rod, just don't render anything
            if ( !rod.intersect(this->userRoI, &rod) ) {
                return;
            }
        }
        rectClippedToRoI.intersect(rod, &rectClippedToRoI);
        //clipTexCoords<RectD>(canonicalTexRect,rectClippedToRoI,texBottom,texTop,texLeft,texRight);
    }

    if (polygonMode != eDrawPolygonModeWhole) {
        /// draw only  the plane defined by the wipe handle
        QPolygonF polygonPoints, polygonTexCoords;
        RectD floatRectClippedToRoI;
        floatRectClippedToRoI.x1 = rectClippedToRoI.x1;
        floatRectClippedToRoI.y1 = rectClippedToRoI.y1;
        floatRectClippedToRoI.x2 = rectClippedToRoI.x2;
        floatRectClippedToRoI.y2 = rectClippedToRoI.y2;
        Implementation::WipePolygonEnum polyType = this->getWipePolygon(floatRectClippedToRoI, polygonMode == eDrawPolygonModeWipeRight, &polygonPoints);

        if (polyType == Implementation::eWipePolygonEmpty) {
            ///don't draw anything
            return;
        } else if (polyType == Implementation::eWipePolygonPartial) {
            this->getPolygonTextureCoordinates(polygonPoints, canonicalRoIRoundedToTileSize, polygonTexCoords);

            this->bindTextureAndActivateShader(textureIndex, useShader);

            GL_GPU::glBegin(GL_POLYGON);
            for (int i = 0; i < polygonTexCoords.size(); ++i) {
                const QPointF & tCoord = polygonTexCoords[i];
                const QPointF & vCoord = polygonPoints[i];
                GL_GPU::glTexCoord2d( tCoord.x(), tCoord.y() );
                GL_GPU::glVertex2d( vCoord.x(), vCoord.y() );
            }
            GL_GPU::glEnd();

            this->unbindTextureAndReleaseShader(useShader);
        } else {
            ///draw the all polygon as usual
            polygonMode = eDrawPolygonModeWhole;
        }
    }

    if (polygonMode == eDrawPolygonModeWhole) {
        const double pixelCenterOffset = 0.5;
        // draw vertices at the center of the first and last pixel in the texture, with the same texture coordinates
        rectClippedToRoI.x1 += pixelCenterOffset * par;
        rectClippedToRoI.x2 -= pixelCenterOffset * par;
        rectClippedToRoI.y1 += pixelCenterOffset;
        rectClippedToRoI.y2 -= pixelCenterOffset;
        ///Vertices are in canonical coords
        GLfloat vertices[32] = {
            (GLfloat)rod.left(), (GLfloat)rod.top(),    //0
            (GLfloat)rectClippedToRoI.x1 + pixelCenterOffset, (GLfloat)rod.top(),          //1
            (GLfloat)rectClippedToRoI.x2 - pixelCenterOffset, (GLfloat)rod.top(),    //2
            (GLfloat)rod.right(), (GLfloat)rod.top(),   //3
            (GLfloat)rod.left(), (GLfloat)rectClippedToRoI.y2 - pixelCenterOffset, //4
            (GLfloat)rectClippedToRoI.x1,  (GLfloat)rectClippedToRoI.y2,       //5
            (GLfloat)rectClippedToRoI.x2,  (GLfloat)rectClippedToRoI.y2, //6
            (GLfloat)rod.right(), (GLfloat)rectClippedToRoI.y2, //7
            (GLfloat)rod.left(), (GLfloat)rectClippedToRoI.y1,        //8
            (GLfloat)rectClippedToRoI.x1,  (GLfloat)rectClippedToRoI.y1,             //9
            (GLfloat)rectClippedToRoI.x2,  (GLfloat)rectClippedToRoI.y1,       //10
            (GLfloat)rod.right(), (GLfloat)rectClippedToRoI.y1,       //11
            (GLfloat)rod.left(), (GLfloat)rod.bottom(), //12
            (GLfloat)rectClippedToRoI.x1,  (GLfloat)rod.bottom(),       //13
            (GLfloat)rectClippedToRoI.x2,  (GLfloat)rod.bottom(), //14
            (GLfloat)rod.right(), (GLfloat)rod.bottom() //15
        };

        //        GLfloat texBottom =  0;
        //        GLfloat texTop =  (GLfloat)(r.y2 - r.y1)  / (GLfloat)(r.h /** r.closestPo2*/);
        //        GLfloat texLeft = 0;
        //        GLfloat texRight = (GLfloat)(r.x2 - r.x1)  / (GLfloat)(r.w /** r.closestPo2*/);
        GLfloat texBottom = (GLfloat)(rectClippedToRoI.y1 - canonicalRoIRoundedToTileSize.y1)  / canonicalRoIRoundedToTileSize.height();
        GLfloat texTop = (GLfloat)(rectClippedToRoI.y2 - canonicalRoIRoundedToTileSize.y1)  / canonicalRoIRoundedToTileSize.height();
        GLfloat texLeft = (GLfloat)(rectClippedToRoI.x1 - canonicalRoIRoundedToTileSize.x1)  / canonicalRoIRoundedToTileSize.width();
        GLfloat texRight = (GLfloat)(rectClippedToRoI.x2 - canonicalRoIRoundedToTileSize.x1)  / canonicalRoIRoundedToTileSize.width();
        GLfloat renderingTextureCoordinates[32] = {
            texLeft, texTop,   //0
            texLeft, texTop,   //1
            texRight, texTop,  //2
            texRight, texTop,   //3
            texLeft, texTop,   //4
            texLeft, texTop,   //5
            texRight, texTop,   //6
            texRight, texTop,   //7
            texLeft, texBottom,   //8
            texLeft, texBottom,   //9
            texRight, texBottom,    //10
            texRight, texBottom,   //11
            texLeft, texBottom,   // 12
            texLeft, texBottom,   //13
            texRight, texBottom,   //14
            texRight, texBottom    //15
        };


        if ( background && this->viewerTab->isCheckerboardEnabled() && (polygonMode != eDrawPolygonModeWipeRight) ) {
            bool isblend = GL_GPU::glIsEnabled(GL_BLEND);
            if (isblend) {
                GL_GPU::glDisable(GL_BLEND);
            }
            this->drawCheckerboardTexture(rod);
            if (isblend) {
                GL_GPU::glEnable(GL_BLEND);
            }
        }

        this->bindTextureAndActivateShader(textureIndex, useShader);

        glCheckError(GL_GPU);

        GL_GPU::glBindBuffer(GL_ARRAY_BUFFER, this->vboVerticesId);
        GL_GPU::glBufferSubData(GL_ARRAY_BUFFER, 0, 32 * sizeof(GLfloat), vertices);
        GL_GPU::glEnableClientState(GL_VERTEX_ARRAY);
        GL_GPU::glVertexPointer(2, GL_FLOAT, 0, 0);

        GL_GPU::glBindBuffer(GL_ARRAY_BUFFER, this->vboTexturesId);
        GL_GPU::glBufferSubData(GL_ARRAY_BUFFER, 0, 32 * sizeof(GLfloat), renderingTextureCoordinates);
        GL_GPU::glClientActiveTexture(GL_TEXTURE0);
        GL_GPU::glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        GL_GPU::glTexCoordPointer(2, GL_FLOAT, 0, 0);

        GL_GPU::glDisableClientState(GL_COLOR_ARRAY);

        GL_GPU::glBindBuffer(GL_ARRAY_BUFFER, 0);

        GL_GPU::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->iboTriangleStripId);
        GL_GPU::glDrawElements(GL_TRIANGLE_STRIP, 28, GL_UNSIGNED_BYTE, 0);
        glCheckErrorIgnoreOSXBug(GL_GPU);

        GL_GPU::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        GL_GPU::glDisableClientState(GL_VERTEX_ARRAY);
        GL_GPU::glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glCheckError(GL_GPU);

        this->unbindTextureAndReleaseShader(useShader);
    }
} // drawRenderingVAO
void
AnimationModuleViewPrivate::drawCurveEditorScale()
{
    glCheckError(GL_GPU);
    // always running in the main thread
    assert( qApp && qApp->thread() == QThread::currentThread() );

    QPointF btmLeft = curveEditorZoomContext.toZoomCoordinates(0, _publicInterface->height() - 1);
    QPointF topRight = curveEditorZoomContext.toZoomCoordinates(_publicInterface->width() - 1, 0);

    ///don't attempt to draw a scale on a widget with an invalid height/width
    if ( (_publicInterface->height() <= 1) || (_publicInterface->width() <= 1) ) {
        return;
    }

    QFontMetrics fontM = _publicInterface->fontMetrics();
    const double smallestTickSizePixel = 10.; // tick size (in pixels) for alpha = 0.
    const double largestTickSizePixel = 500.; // tick size (in pixels) for alpha = 1.
    double gridR, gridG, gridB;
    SettingsPtr sett = appPTR->getCurrentSettings();
    sett->getAnimationModuleEditorGridColor(&gridR, &gridG, &gridB);


    double scaleR, scaleG, scaleB;
    sett->getAnimationModuleEditorScaleColor(&scaleR, &scaleG, &scaleB);

    QColor scaleColor;
    scaleColor.setRgbF( Image::clamp(scaleR, 0., 1.),
                        Image::clamp(scaleG, 0., 1.),
                        Image::clamp(scaleB, 0., 1.) );


    {
        GLProtectAttrib<GL_GPU> a(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);

        GL_GPU::Enable(GL_BLEND);
        GL_GPU::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        for (int axis = 0; axis < 2; ++axis) {
            const double rangePixel = (axis == 0) ? _publicInterface->width() : _publicInterface->height(); // AXIS-SPECIFIC
            const double range_min = (axis == 0) ? btmLeft.x() : btmLeft.y(); // AXIS-SPECIFIC
            const double range_max = (axis == 0) ? topRight.x() : topRight.y(); // AXIS-SPECIFIC
            const double range = range_max - range_min;
            double smallTickSize;
            bool half_tick;
            ticks_size(range_min, range_max, rangePixel, smallestTickSizePixel, &smallTickSize, &half_tick);
            int m1, m2;
            const int ticks_max = 1000;
            double offset;
            ticks_bounds(range_min, range_max, smallTickSize, half_tick, ticks_max, &offset, &m1, &m2);
            std::vector<int> ticks;
            ticks_fill(half_tick, ticks_max, m1, m2, &ticks);
            const double smallestTickSize = range * smallestTickSizePixel / rangePixel;
            const double largestTickSize = range * largestTickSizePixel / rangePixel;
            const double minTickSizeTextPixel = (axis == 0) ? fontM.width( QLatin1String("00") ) : fontM.height(); // AXIS-SPECIFIC
            const double minTickSizeText = range * minTickSizeTextPixel / rangePixel;
            for (int i = m1; i <= m2; ++i) {
                double value = i * smallTickSize + offset;
                const double tickSize = ticks[i - m1] * smallTickSize;
                const double alpha = ticks_alpha(smallestTickSize, largestTickSize, tickSize);

                glCheckError(GL_GPU);
                GL_GPU::Color4f(gridR, gridG, gridB, alpha);

                GL_GPU::Begin(GL_LINES);
                if (axis == 0) {
                    GL_GPU::Vertex2f( value, btmLeft.y() ); // AXIS-SPECIFIC
                    GL_GPU::Vertex2f( value, topRight.y() ); // AXIS-SPECIFIC
                } else {
                    GL_GPU::Vertex2f(btmLeft.x(), value); // AXIS-SPECIFIC
                    GL_GPU::Vertex2f(topRight.x(), value); // AXIS-SPECIFIC
                }
                GL_GPU::End();
                glCheckErrorIgnoreOSXBug(GL_GPU);

                if (tickSize > minTickSizeText) {
                    const int tickSizePixel = rangePixel * tickSize / range;
                    const QString s = QString::number(value);
                    const int sSizePixel = (axis == 0) ? fontM.width(s) : fontM.height(); // AXIS-SPECIFIC
                    if (tickSizePixel > sSizePixel) {
                        const int sSizeFullPixel = sSizePixel + minTickSizeTextPixel;
                        double alphaText = 1.0; //alpha;
                        if (tickSizePixel < sSizeFullPixel) {
                            // when the text size is between sSizePixel and sSizeFullPixel,
                            // draw it with a lower alpha
                            alphaText *= (tickSizePixel - sSizePixel) / (double)minTickSizeTextPixel;
                        }
                        alphaText = std::min(alphaText, alpha); // don't draw more opaque than tcks
                        QColor c = scaleColor;
                        c.setAlpha(255 * alphaText);
                        if (axis == 0) {
                            _publicInterface->renderText(value, btmLeft.y(), s.toStdString(), c.redF(), c.greenF(), c.blueF(), c.alphaF(), Qt::AlignHCenter);
                        } else {
                            _publicInterface->renderText(btmLeft.x(), value, s.toStdString(), c.redF(), c.greenF(), c.blueF(), c.alphaF(), Qt::AlignVCenter);
                        }
                    }
                }
            }
        }
    } // GLProtectAttrib a(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);


    glCheckError(GL_GPU);
    GL_GPU::Color4f(gridR, gridG, gridB, 1.);
    GL_GPU::Begin(GL_LINES);
    GL_GPU::Vertex2f(AXIS_MIN, 0);
    GL_GPU::Vertex2f(AXIS_MAX, 0);
    GL_GPU::Vertex2f(0, AXIS_MIN);
    GL_GPU::Vertex2f(0, AXIS_MAX);
    GL_GPU::End();


    glCheckErrorIgnoreOSXBug(GL_GPU);
} // drawCurveEditorScale
Exemplo n.º 3
0
void
CurveGui::drawCurve(int curveIndex,
                    int curvesCount)
{
    // always running in the main thread
    assert( qApp && qApp->thread() == QThread::currentThread() );

    AnimItemBasePtr item = _imp->item.lock();
    if (!item) {
        return;
    }

    std::vector<float> vertices, exprVertices;
    const double widgetWidth = _imp->curveWidget->width();
    KeyFrameSet keyframes;
    bool hasDrawnExpr = false;
    if (item->hasExpression(_imp->dimension, _imp->view)) {

        //we have no choice but to evaluate the expression at each time
        for (int i = 0; i < widgetWidth; ++i) {
            double x = _imp->curveWidget->toZoomCoordinates(i, 0).x();
            double y = evaluate(true /*useExpr*/, x);
            exprVertices.push_back(x);
            exprVertices.push_back(y);
        }
        hasDrawnExpr = true;

    }


    QPointF btmLeft = _imp->curveWidget->toZoomCoordinates(0, _imp->curveWidget->height() - 1);
    QPointF topRight = _imp->curveWidget->toZoomCoordinates(_imp->curveWidget->width() - 1, 0);

    


    bool isPeriodic = false;
    std::pair<double,double> parametricRange = std::make_pair(-std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity());

    keyframes = getInternalCurve()->getKeyFrames_mt_safe();
    isPeriodic = getInternalCurve()->isCurvePeriodic();
    parametricRange = getInternalCurve()->getXRange();

    if ( keyframes.empty() ) {
        // Add a horizontal line for constant knobs, except string knobs.
        KnobIPtr isKnob = boost::dynamic_pointer_cast<KnobI>(item->getInternalAnimItem());

        if (isKnob) {
            KnobStringBasePtr isString = boost::dynamic_pointer_cast<KnobStringBase>(isKnob);
            if (!isString) {
                double value = evaluate(false, 0);
                vertices.push_back(btmLeft.x() + 1);
                vertices.push_back(value);
                vertices.push_back(topRight.x() - 1);
                vertices.push_back(value);
            }
        }
    } else {
        try {
            double x1 = 0;
            double x2;

            bool isX1AKey = false;
            KeyFrame x1Key;
            KeyFrameSet::const_iterator lastUpperIt = keyframes.end();

            while ( x1 < (widgetWidth - 1) ) {
                double x, y;
                if (!isX1AKey) {
                    x = _imp->curveWidget->toZoomCoordinates(x1, 0).x();
                    y = evaluate(false, x);
                } else {
                    x = x1Key.getTime();
                    y = x1Key.getValue();
                }

                vertices.push_back( (float)x );
                vertices.push_back( (float)y );
                nextPointForSegment(x, keyframes, isPeriodic, parametricRange.first, parametricRange.second,  &lastUpperIt, &x2, &x1Key, &isX1AKey);
                x1 = x2;
            }
            //also add the last point
            {
                double x = _imp->curveWidget->toZoomCoordinates(x1, 0).x();
                double y = evaluate(false, x);
                vertices.push_back( (float)x );
                vertices.push_back( (float)y );
            }
        } catch (...) {
        }
    }

    // No Expr curve or no vertices for the curve, don't draw anything else
    if (exprVertices.empty() && vertices.empty()) {
        return;
    }

    AnimationModuleSelectionModelPtr selectionModel = item->getModel()->getSelectionModel();
    assert(selectionModel);
    const AnimItemDimViewKeyFramesMap& selectedKeys = selectionModel->getCurrentKeyFramesSelection();


    const KeyFrameWithStringSet* foundThisCurveSelectedKeys = 0;
    {
        AnimItemDimViewIndexID k;
        k.item = item;
        k.dim = _imp->dimension;
        k.view = _imp->view;
        AnimItemDimViewKeyFramesMap::const_iterator foundDimView = selectedKeys.find(k);

        if (foundDimView != selectedKeys.end()) {
            foundThisCurveSelectedKeys = &foundDimView->second;
        }
    }


    {
        GLProtectAttrib<GL_GPU> a(GL_HINT_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_COLOR_BUFFER_BIT | GL_POINT_BIT | GL_CURRENT_BIT);

        // If this is the only curve selected, draw min/max
        if (foundThisCurveSelectedKeys && selectedKeys.size()) {

            // Draw y min/max axis so the user understands why the value is clamped
            Curve::YRange curveYRange = getCurveYRange();
            if (curveYRange.min != INT_MIN &&
                curveYRange.min != -std::numeric_limits<double>::infinity() &&
                curveYRange.max != INT_MAX &&
                curveYRange.max != std::numeric_limits<double>::infinity() ) {
                QColor minMaxColor;
                minMaxColor.setRgbF(0.398979, 0.398979, 0.398979);
                GL_GPU::Color4d(minMaxColor.redF(), minMaxColor.greenF(), minMaxColor.blueF(), 1.);
                GL_GPU::Begin(GL_LINES);
                GL_GPU::Vertex2d(btmLeft.x(), curveYRange.min);
                GL_GPU::Vertex2d(topRight.x(), curveYRange.min);
                GL_GPU::Vertex2d(btmLeft.x(), curveYRange.max);
                GL_GPU::Vertex2d(topRight.x(), curveYRange.max);
                GL_GPU::End();
                GL_GPU::Color4d(1., 1., 1., 1.);

                double xText = _imp->curveWidget->toZoomCoordinates(10, 0).x();

                _imp->curveWidget->renderText( xText, curveYRange.min, tr("min").toStdString(), minMaxColor.redF(), minMaxColor.greenF(), minMaxColor.blueF(), minMaxColor.alphaF());
                _imp->curveWidget->renderText( xText, curveYRange.max, tr("max").toStdString(), minMaxColor.redF(), minMaxColor.greenF(), minMaxColor.blueF(), minMaxColor.alphaF());
            }
        }


        GL_GPU::Color4f(_imp->color[0], _imp->color[1], _imp->color[2], _imp->color[3]);
        GL_GPU::PointSize(_imp->lineWidth);
        GL_GPU::Enable(GL_BLEND);
        GL_GPU::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        GL_GPU::Enable(GL_LINE_SMOOTH);
        GL_GPU::Hint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
        GL_GPU::LineWidth(1.5);
        glCheckError(GL_GPU);
        if (hasDrawnExpr) {
            drawLineStrip(exprVertices, btmLeft, topRight);
            GL_GPU::LineStipple(2, 0xAAAA);
            GL_GPU::Enable(GL_LINE_STIPPLE);
        }
        drawLineStrip(vertices, btmLeft, topRight);
        if (hasDrawnExpr) {
            GL_GPU::Disable(GL_LINE_STIPPLE);
        }

        glCheckErrorIgnoreOSXBug(GL_GPU);

        //render the name of the curve
        GL_GPU::Color4f(1.f, 1.f, 1.f, 1.f);


        double interval = ( topRight.x() - btmLeft.x() ) / (double)curvesCount;
        double textX = _imp->curveWidget->toZoomCoordinates(15, 0).x() + interval * (double)curveIndex;
        double textY;

        CurvePtr internalCurve = _imp->internalCurve.lock();
        QString curveName = getName();
        QColor thisColor;
        thisColor.setRgbF(Image::clamp(_imp->color[0], 0., 1.),
                          Image::clamp(_imp->color[1], 0., 1.),
                          Image::clamp(_imp->color[2], 0., 1.));

        try {
            // Use expression to place the text if the curve is not animated
            textY = evaluate(internalCurve && !internalCurve->isAnimated(), textX);
        } catch (...) {
            // if it fails attempt without expression, this will most likely return a constant value
            textY = evaluate(false /*useExpression*/, textX);
        }

        if ( ( textX >= btmLeft.x() ) && ( textX <= topRight.x() ) && ( textY >= btmLeft.y() ) && ( textY <= topRight.y() ) ) {
            _imp->curveWidget->renderText( textX, textY, curveName.toStdString(), thisColor.redF(), thisColor.greenF(), thisColor.blueF(), thisColor.alphaF());
        }
        GL_GPU::Color4f(_imp->color[0], _imp->color[1], _imp->color[2], _imp->color[3]);

        //draw keyframes
        GL_GPU::PointSize(7.f);
        GL_GPU::Enable(GL_POINT_SMOOTH);


        KeyFrameWithStringSet::const_iterator foundSelectedKey;
        if (foundThisCurveSelectedKeys) {
            foundSelectedKey = foundThisCurveSelectedKeys->end();
        }
        for (KeyFrameSet::const_iterator k = keyframes.begin(); k != keyframes.end(); ++k) {
            const KeyFrame & key = (*k);

            // Do not draw keyframes out of range
            if ( ( key.getTime() < btmLeft.x() ) || ( key.getTime() > topRight.x() ) || ( key.getValue() < btmLeft.y() ) || ( key.getValue() > topRight.y() ) ) {
                continue;
            }

            GL_GPU::Color4f(_imp->color[0], _imp->color[1], _imp->color[2], _imp->color[3]);

            bool drawKeySelected = false;
            if (foundThisCurveSelectedKeys) {
                KeyFrameWithStringSet::const_iterator start = foundSelectedKey == foundThisCurveSelectedKeys->end() ? foundThisCurveSelectedKeys->begin() : foundSelectedKey;
                foundSelectedKey = std::find_if(start, foundThisCurveSelectedKeys->end(), KeyFrameWithStringTimePredicate(key.getTime()));
                drawKeySelected = foundSelectedKey != foundThisCurveSelectedKeys->end();
                if (!drawKeySelected) {
                    // Also draw the keyframe as selected if it is inside the selection rectangle (but not yet selected)
                    RectD selectionRect = _imp->curveWidget->getSelectionRectangle();
                    drawKeySelected |= _imp->curveWidget->_imp->eventTriggeredFromCurveEditor && (!selectionRect.isNull() && selectionRect.contains(key.getTime(), key.getValue()));
                }
            }
            // If the key is selected change its color
            if (drawKeySelected) {
                GL_GPU::Color4f(0.8f, 0.8f, 0.8f, 1.f);
            }


            RectD keyframeBbox = _imp->curveWidget->_imp->getKeyFrameBoundingRectCanonical(_imp->curveWidget->_imp->curveEditorZoomContext, key.getTime(), key.getValue());

            // draw texture of the keyframe
            {
                AnimationModuleViewPrivate::KeyframeTexture texType = AnimationModuleViewPrivate::kfTextureFromKeyframeType( key.getInterpolation(), drawKeySelected);
                if (texType != AnimationModuleViewPrivate::kfTextureNone) {
                    _imp->curveWidget->_imp->drawTexturedKeyframe(texType, keyframeBbox, false /*drawdimed*/);
                }
            }

            
            // Draw tangents if not constant
            bool drawTangents = drawKeySelected && internalCurve->isYComponentMovable() && (key.getInterpolation() != eKeyframeTypeConstant);
            if (drawTangents) {
                QFontMetrics m( _imp->curveWidget->font());


                // If interpolation is not free and not broken display with dashes the tangents lines
                if ( (key.getInterpolation() != eKeyframeTypeFree) && (key.getInterpolation() != eKeyframeTypeBroken) ) {
                    GL_GPU::LineStipple(2, 0xAAAA);
                    GL_GPU::Enable(GL_LINE_STIPPLE);
                }
                
                QPointF leftTanPos, rightTanPos;
                _imp->curveWidget->getKeyTangentPoints(k, keyframes, &leftTanPos, &rightTanPos);

                // Draw the derivatives lines
                GL_GPU::Begin(GL_LINES);
                GL_GPU::Color4f(1., 0.35, 0.35, 1.);
                GL_GPU::Vertex2f( leftTanPos.x(), leftTanPos.y() );
                GL_GPU::Vertex2f(key.getTime(), key.getValue());
                GL_GPU::Vertex2f(key.getTime(), key.getValue());
                GL_GPU::Vertex2f( rightTanPos.x(), rightTanPos.y());
                GL_GPU::End();
                if ( (key.getInterpolation() != eKeyframeTypeFree) && (key.getInterpolation() != eKeyframeTypeBroken) ) {
                    GL_GPU::Disable(GL_LINE_STIPPLE);
                }


                // Draw the tangents handles
                GL_GPU::Begin(GL_POINTS);
                GL_GPU::Vertex2f( leftTanPos.x(), leftTanPos.y() );
                GL_GPU::Vertex2f( rightTanPos.x(), rightTanPos.y());
                GL_GPU::End();

                // If only one keyframe is selected, also draw the coordinates
                if (selectedKeys.size() == 1 && foundThisCurveSelectedKeys && foundThisCurveSelectedKeys->size() == 1) {
                    double rounding = std::pow(10., CURVEWIDGET_DERIVATIVE_ROUND_PRECISION);
                    QString leftDerivStr = QString::fromUtf8("l: %1").arg(std::floor( (key.getLeftDerivative() * rounding) + 0.5 ) / rounding);
                    QString rightDerivStr = QString::fromUtf8("r: %1").arg(std::floor( (key.getRightDerivative() * rounding) + 0.5 ) / rounding);
                    double yLeftWidgetCoord = _imp->curveWidget->toWidgetCoordinates(0, leftTanPos.y()).y();
                    yLeftWidgetCoord += (m.height() + 4);

                    double yRightWidgetCoord = _imp->curveWidget->toWidgetCoordinates(0, rightTanPos.y()).y();
                    yRightWidgetCoord += (m.height() + 4);

                    GL_GPU::Color4f(1., 1., 1., 1.);
                    glCheckFramebufferError(GL_GPU);
                    _imp->curveWidget->renderText( leftTanPos.x(), _imp->curveWidget->toZoomCoordinates(0, yLeftWidgetCoord).y(),
                                              leftDerivStr.toStdString(), 0.9, 0.9, 0.9, 1.);
                    _imp->curveWidget->renderText( rightTanPos.x(), _imp->curveWidget->toZoomCoordinates(0, yRightWidgetCoord).y(),
                                                  rightDerivStr.toStdString(), 0.9, 0.9, 0.9, 1.);


                    QString coordStr = QString::fromUtf8("x: %1, y: %2");
                    coordStr = coordStr.arg(key.getTime()).arg(key.getValue());
                    double yWidgetCoord = _imp->curveWidget->toWidgetCoordinates( 0, key.getValue() ).y();
                    yWidgetCoord += (m.height() + 4);
                    GL_GPU::Color4f(1., 1., 1., 1.);
                    glCheckFramebufferError(GL_GPU);
                    _imp->curveWidget->renderText( key.getTime(), _imp->curveWidget->toZoomCoordinates(0, yWidgetCoord).y(),
                                                  coordStr.toStdString(), 0.9, 0.9, 0.9, 1.);

                }

            } // drawTangents

        } // for (KeyFrameSet::const_iterator k = keyframes.begin(); k != keyframes.end(); ++k) {
    } // GLProtectAttrib(GL_HINT_BIT | GL_ENABLE_BIT | GL_LINE_BIT | GL_COLOR_BUFFER_BIT | GL_POINT_BIT | GL_CURRENT_BIT);

    glCheckError(GL_GPU);
} // drawCurve
Exemplo n.º 4
0
void
TextRenderer::renderText(float x,
                         float y,
                         float scalex,
                         float scaley,
                         const QString &text,
                         const QColor &color,
                         const QFont &font) const
{
    glCheckError();
    boost::shared_ptr<TextRendererPrivate> p;
    FontRenderers::iterator it = _imp->renderers.find(font);
    if ( it != _imp->renderers.end() ) {
        p  = (*it).second;
    } else {
        p = boost::shared_ptr<TextRendererPrivate>( new TextRendererPrivate(font) );
        _imp->renderers[font] = p;
    }
    assert(p);

    GLuint savedTexture;
    glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&savedTexture);
    {
        GLProtectAttrib a(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_TRANSFORM_BIT);
        GLProtectMatrix pr(GL_MODELVIEW);

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_TEXTURE_2D);
        GLuint texture = 0;

        glTranslatef(x, y, 0);
        glColor4f( color.redF(), color.greenF(), color.blueF(), color.alphaF() );
        for (int i = 0; i < text.length(); ++i) {
            CharBitmap *c = p->createCharacter(text[i]);
            if (!c) {
                continue;
            }
            if (texture != c->texID) {
                texture = c->texID;
                glBindTexture(GL_TEXTURE_2D, texture);
                assert( glIsTexture(texture) );
            }
            glCheckError();
            glBegin(GL_QUADS);
            glTexCoord2f(c->xTexCoords[0], c->yTexCoords[0]);
            glVertex2f(0, 0);
            glTexCoord2f(c->xTexCoords[1], c->yTexCoords[0]);
            glVertex2f(c->w * scalex, 0);
            glTexCoord2f(c->xTexCoords[1], c->yTexCoords[1]);
            glVertex2f(c->w * scalex, c->h * scaley);
            glTexCoord2f(c->xTexCoords[0], c->yTexCoords[1]);
            glVertex2f(0, c->h * scaley);
            glEnd();
            glCheckErrorIgnoreOSXBug();
            glTranslatef(c->w * scalex, 0, 0);
            glCheckError();
        }
    } // GLProtectAttrib a(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_TRANSFORM_BIT);
    glBindTexture(GL_TEXTURE_2D, savedTexture);

    glCheckError();
} // renderText