Exemplo n.º 1
0
void ColorWheel::setColor(const Colour &rgb)
{
    float r = rgb[0], g = rgb[1], b = rgb[2];

    float max = std::max({ r, g, b });
    float min = std::min({ r, g, b });
    float l = (max + min) / 2;

    if (max == min) {
        mHue = 0.;
        mBlack = 1. - l;
        mWhite = l;
    }
    else {
        float d = max - min, h;
        /* float s = l > 0.5 ? d / (2 - max - min) : d / (max + min); */
        if (max == r)
            h = (g - b) / d + (g < b ? 6 : 0);
        else if (max == g)
            h = (b - r) / d + 2;
        else
            h = (r - g) / d + 4;
        h /= 6;

        mHue = h;

        vec3 pt(rgb.r, rgb.g, rgb.b);
        Colour c = hue2rgb(mHue);
        vec3 a(c.r, c.g, c.b);
        vec3 b(0, 0, 0);
        vec3 w(1, 1, 1);

        vec3 bary = calcBarycentric(pt, a, w, b);

        /*	Eigen::Matrix<float, 4, 3> M;
        	M.topLeftCorner<3, 1>() = hue2rgb(h).head<3>();
        	M(3, 0) = 1.;
        	M.col(1) = vec4{ 0., 0., 0., 1. };
        	M.col(2) = vec4{ 1., 1., 1., 1. };

        	vec4 rgb4{ rgb[0], rgb[1], rgb[2], 1. };
        	vec3 bary = M.colPivHouseholderQr().solve(rgb4); */

        mBlack = bary[1];
        mWhite = bary[2];
    }
}
Exemplo n.º 2
0
void addCubic(glm::vec3 cp[4], Geometry<RCubicVertex>& cubicGeom, Geometry<glm::vec2>& triGeom)
{
    glm::vec3   bezierBasisCP[4*4];
    glm::vec4   klmn[4*4];
    int         count;
    float       subdPt[3];

    memcpy(bezierBasisCP, cp, 4*sizeof(glm::vec3));
    implicitizeRationalBezierCubic(bezierBasisCP, klmn, count, subdPt);

    glm::vec2   tri[4] = {
        cp[0]._xy()/cp[0].z,
        cp[1]._xy()/cp[1].z,
        cp[2]._xy()/cp[2].z,
        cp[3]._xy()/cp[3].z,
    };

    glm::vec3 bary;
    glm::vec2 pt;

    float ttt[] = {0, 1, 0.5f, 0.75f, 0.25f, 0.333333f, 0.4f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f};
    for (size_t i=0; i<ARRAY_SIZE(ttt); ++i)
    {
        evalRationalBezier(ml::as<float>(cp),  ttt[i], pt);

        calcBarycentric(tri[0], tri[1], tri[3], pt, bary);
        assert(glm::equalEpsilonGTX(pt, bary.x*tri[0]+bary.y*tri[1]+bary.z*tri[3], ml::EPS7));

        glm::vec3 scale = bary/glm::vec3(cp[0].z, cp[1].z, cp[3].z);
        glm::vec4 klmnI = (scale.x*klmn[0] + scale.y*klmn[1] + scale.z*klmn[3])/(scale.x + scale.y + scale.z);

        float f = klmnI.x*klmnI.x*klmnI.x - klmnI.y*klmnI.z*klmnI.w;

        assert(ml::equalE(f, 0, 0.01f));
    }

    glm::vec2   intervals[4] = {glm::vec2(0, 1)};
    glm::vec2*  intervalLast = intervals+4;
    size_t      intervalCount = 1;

    for (int i=0; i<count; i++)
    {
        float   t = subdPt[i];
        int     left = 0;
        int         right = intervalCount++;

        while (left<right && !(ml::lessThenE(intervals[left].x, t) && ml::lessThenE(t, intervals[left].y)))
            ++left;

        if (left==right) continue;

        glm::vec2 oldInterval = intervals[left];

        intervals[left]  = glm::vec2(oldInterval.x, t);
        intervals[right] = glm::vec2(t, oldInterval.y);

        left*=4; right*=4;

        float tt = (t-oldInterval.x)/(oldInterval.y-oldInterval.x);

        cubic::subdivide(bezierBasisCP+left, tt, bezierBasisCP+left, bezierBasisCP+right);
        cubic::subdivide(klmn+left, tt, klmn+left, klmn+right);
    }

    size_t cvertBase = cubicGeom.vertices.size();
    size_t tvertBase = triGeom.vertices.size();

    cubicGeom.vertices.resize(cvertBase+4*intervalCount);

    for (size_t base=0; base<4*intervalCount; base+=4, cvertBase+=4)
    {
        correctOrient(klmn+base);

        cubicGeom.vertices[cvertBase+0].pos = glm::vec4(bezierBasisCP[base+0].x, bezierBasisCP[base+0].y, 0, bezierBasisCP[base+0].z);
        cubicGeom.vertices[cvertBase+0].klmn = klmn[base+0];
        cubicGeom.vertices[cvertBase+1].pos = glm::vec4(bezierBasisCP[base+1].x, bezierBasisCP[base+1].y, 0, bezierBasisCP[base+1].z);
        cubicGeom.vertices[cvertBase+1].klmn = klmn[base+1];
        cubicGeom.vertices[cvertBase+2].pos = glm::vec4(bezierBasisCP[base+2].x, bezierBasisCP[base+2].y, 0, bezierBasisCP[base+2].z);
        cubicGeom.vertices[cvertBase+2].klmn = klmn[base+2];
        cubicGeom.vertices[cvertBase+3].pos = glm::vec4(bezierBasisCP[base+3].x, bezierBasisCP[base+3].y, 0, bezierBasisCP[base+3].z);
        cubicGeom.vertices[cvertBase+3].klmn = klmn[base+3];

        cubicGeom.indices.pushBack(cvertBase+0); cubicGeom.indices.pushBack(cvertBase+1); cubicGeom.indices.pushBack(cvertBase+2);
        cubicGeom.indices.pushBack(cvertBase+0); cubicGeom.indices.pushBack(cvertBase+2); cubicGeom.indices.pushBack(cvertBase+3);

        if (intervalCount==1) break;

        //we assume first iinterval is at the beginning of the curve
        if (base==0)
        {
            triGeom.vertices.pushBack(glm::vec2(bezierBasisCP[base+0].x, bezierBasisCP[base+0].y)/bezierBasisCP[base+0].z);
        }
        else
        {
            triGeom.vertices.pushBack(glm::vec2(bezierBasisCP[base+0].x, bezierBasisCP[base+0].y)/bezierBasisCP[base+0].z);
            triGeom.vertices.pushBack(glm::vec2(bezierBasisCP[base+3].x, bezierBasisCP[base+3].y)/bezierBasisCP[base+3].z);

            triGeom.indices.pushBack(tvertBase); triGeom.indices.pushBack(tvertBase+base/2-1); triGeom.indices.pushBack(tvertBase+base/2);
        }
    }
}
Exemplo n.º 3
0
void addDistanceTransformCubic(glm::vec3 cp[4], Geometry<RCubicVertex>& distTransGeom)
{
    glm::vec4   klmn[4];
    int         count;
    float       subdPt[3];

    implicitizeRationalBezierCubic(cp, klmn, count, subdPt);

    glm::vec2	tri[4] = {
        cp[0]._xy()/cp[0].z,
        cp[1]._xy()/cp[1].z,
        cp[2]._xy()/cp[2].z,
        cp[3]._xy()/cp[3].z,
    };

    glm::vec3 bary;
    glm::vec2 pt;

    glm::vec2 pts[] = {
        glm::vec2(-10, 0),
        glm::vec2(10, 0),
        //glm::vec2(-10, 20),
        //glm::vec2(10, 20),
        //glm::vec2(0, 20),
        glm::vec2(0, 0),
        glm::vec2(-10, 10),
        glm::vec2(10, 10),
        glm::vec2(0, 10),
        glm::vec2(-11, 0),
        glm::vec2(11, 0)
    };

    for (size_t i=0; i<ARRAY_SIZE(pts); ++i)
    {
        pt = pts[i];

        calcBarycentric(tri[0], tri[1], tri[3], pt, bary);
        assert(glm::equalEpsilonGTX(pt, bary.x*tri[0]+bary.y*tri[1]+bary.z*tri[3], ml::EPS7));

        glm::vec3 scale = bary/glm::vec3(cp[0].z, cp[1].z, cp[3].z);
        glm::vec4 klmnI1 = (scale.x*klmn[0] + scale.y*klmn[1] + scale.z*klmn[3])/(scale.x + scale.y + scale.z);

        float f1  = klmnI1.x*klmnI1.x*klmnI1.x - klmnI1.y*klmnI1.z*klmnI1.w;
        float iw1 = scale.x+scale.y+scale.z;

        calcBarycentric(tri[1], tri[2], tri[3], pt, bary);
        assert(glm::equalEpsilonGTX(pt, bary.x*tri[1]+bary.y*tri[2]+bary.z*tri[3], ml::EPS7));
        scale = bary/glm::vec3(cp[1].z, cp[2].z, cp[3].z);
        glm::vec4 klmnI2 = (scale.x*klmn[1] + scale.y*klmn[2] + scale.z*klmn[3])/(scale.x + scale.y + scale.z);

        float f2  = klmnI2.x*klmnI2.x*klmnI2.x - klmnI2.y*klmnI2.z*klmnI2.w;
        float iw2 = scale.x+scale.y+scale.z;

        glm::vec4 sc = klmnI1/klmnI2;
        float s2s = iw2/iw1;

        assert(ml::equalE(f1*iw1*iw1*iw1, f2*iw2*iw2*iw2, ml::EPS5));
        //assert(ml::equalE(iw1, iw2));

        calcBarycentric(tri[1], tri[2], pt, tri[3], bary);
        assert(glm::equalEpsilonGTX(tri[3], bary.x*tri[1]+bary.y*tri[2]+bary.z*pt, ml::EPS7));
        scale = bary/glm::vec3(cp[1].z, cp[2].z, 1/iw2);
        glm::vec4 klmnII = (scale.x*klmn[1] + scale.y*klmn[2] + scale.z*klmnI2)/(scale.x + scale.y + scale.z);

        float f3  = klmnII.x*klmnII.x*klmnII.x - klmnII.y*klmnII.z*klmnII.w;
        float iw3 = scale.x+scale.y+scale.z;

        assert(ml::equalE(cp[3].z, 1/iw3, ml::EPS5));
        assert(glm::equalEpsilonGTX(klmn[3], klmnII, ml::EPS7));
    }

    glm::vec2 n1 = glm::normalize(perpendicularCCW(tri[1]-tri[0]));
    glm::vec2 n2 = glm::normalize(perpendicularCCW(tri[2]-tri[1]));
    glm::vec2 n3 = glm::normalize(perpendicularCCW(tri[3]-tri[2]));

    glm::vec2 o1 = 10.0f*n1;
    glm::vec2 o2 = 10.0f*calcOffsetN(n1, n2);
    glm::vec2 o3 = 10.0f*calcOffsetN(n2, n3);
    glm::vec2 o4 = 10.0f*n3;

    size_t base = distTransGeom.vertices.size();
    distTransGeom.vertices.resize(base+6);

    float iw;
    float fv;
    glm::vec4 klmnN;

    pt = tri[0]+o1;//glm::vec2(-40, 0);//tri[0]+o1;
    calcBarycentric(tri[0], tri[1], tri[2], pt, bary);
    assert(glm::equalEpsilonGTX(pt, bary.x*tri[0]+bary.y*tri[1]+bary.z*tri[3], ml::EPS7));
    klmnN = distTransGeom.vertices[base+0].klmn = perspectiveInterpolate(bary, glm::vec3(cp[0].z, cp[1].z, cp[2].z), klmn[0], klmn[1], klmn[2], iw);
    //distTransGeom.vertices[base+0].klmn.x = -distTransGeom.vertices[base+0].klmn.x;
    //distTransGeom.vertices[base+0].klmn.z = -distTransGeom.vertices[base+0].klmn.z;
    fv  = klmnN.x*klmnN.x*klmnN.x - klmnN.y*klmnN.z*klmnN.w;
    distTransGeom.vertices[base+0].pos = glm::vec4(pt, 0, 1)/iw;

    pt = tri[1]+o2;//glm::vec2(-40, 100);//tri[1]+o2;
    calcBarycentric(tri[0], tri[1], tri[2], pt, bary);
    klmnN = distTransGeom.vertices[base+1].klmn = perspectiveInterpolate(bary, glm::vec3(cp[0].z, cp[1].z, cp[2].z), klmn[0], klmn[1], klmn[2], iw);
    fv  = klmnN.x*klmnN.x*klmnN.x - klmnN.y*klmnN.z*klmnN.w;
    distTransGeom.vertices[base+1].pos = glm::vec4(pt, 0, 1)/iw;

    pt = tri[2]+o3;//glm::vec2(40, 100);//tri[2]+o3;
    calcBarycentric(tri[0], tri[1], tri[2], pt, bary);
    klmnN = distTransGeom.vertices[base+2].klmn = perspectiveInterpolate(bary, glm::vec3(cp[0].z, cp[1].z, cp[2].z), klmn[0], klmn[1], klmn[2], iw);
    fv  = klmnN.x*klmnN.x*klmnN.x - klmnN.y*klmnN.z*klmnN.w;
    distTransGeom.vertices[base+2].pos = glm::vec4(pt, 0, 1)/iw;

    pt = tri[3]+o4;
    calcBarycentric(tri[0], tri[1], tri[2], pt, bary);
    klmnN = distTransGeom.vertices[base+3].klmn = perspectiveInterpolate(bary, glm::vec3(cp[0].z, cp[1].z, cp[2].z), klmn[0], klmn[1], klmn[2], iw);
    fv  = klmnN.x*klmnN.x*klmnN.x - klmnN.y*klmnN.z*klmnN.w;
    distTransGeom.vertices[base+3].pos = glm::vec4(pt, 0, 1)/iw;

    pt = tri[3]-o4;
    calcBarycentric(tri[0], tri[1], tri[2], pt, bary);
    klmnN = distTransGeom.vertices[base+4].klmn = perspectiveInterpolate(bary, glm::vec3(cp[0].z, cp[1].z, cp[2].z), klmn[0], klmn[1], klmn[2], iw);
    fv  = klmnN.x*klmnN.x*klmnN.x - klmnN.y*klmnN.z*klmnN.w;
    distTransGeom.vertices[base+4].pos = glm::vec4(pt, 0, 1)/iw;

    pt = tri[0]-o1;//glm::vec2(40, 0);//tri[0]-o1;
    calcBarycentric(tri[0], tri[1], tri[2], pt, bary);
    klmnN = distTransGeom.vertices[base+5].klmn = perspectiveInterpolate(bary, glm::vec3(cp[0].z, cp[1].z, cp[2].z), klmn[0], klmn[1], klmn[2], iw);
    fv  = klmnN.x*klmnN.x*klmnN.x - klmnN.y*klmnN.z*klmnN.w;
    distTransGeom.vertices[base+5].pos = glm::vec4(pt, 0, 1)/iw;

    distTransGeom.indices.pushBack(base+0);
    distTransGeom.indices.pushBack(base+1);
    distTransGeom.indices.pushBack(base+5);

    distTransGeom.indices.pushBack(base+1);
    distTransGeom.indices.pushBack(base+2);
    distTransGeom.indices.pushBack(base+5);

    distTransGeom.indices.pushBack(base+2);
    distTransGeom.indices.pushBack(base+3);
    distTransGeom.indices.pushBack(base+4);

    distTransGeom.indices.pushBack(base+2);
    distTransGeom.indices.pushBack(base+4);
    distTransGeom.indices.pushBack(base+5);
}
Exemplo n.º 4
0
ColorWheel::Region ColorWheel::adjustPosition(const ivec2 &p, Region consideredRegions)
{

    float x = p.x - mPos.x, y = p.y - mPos.y, w = mSize.x, h = mSize.y;

    float cx = w*0.5f;
    float cy = h*0.5f;
    float r1 = (w < h ? w : h) * 0.5f - 5.0f;
    float r0 = r1 * .75f;

    x -= cx;
    y -= cy;

    float mr = glm::sqrt(x*x + y*y);

    if ((consideredRegions & OuterCircle) &&
            ((mr >= r0 && mr <= r1) || (consideredRegions == OuterCircle))) {
        if (!(consideredRegions & OuterCircle))
            return None;
        mHue = std::atan(y / x);
        if (x < 0)
            mHue += NVG_PI;
        mHue /= 2 * NVG_PI;

        if (mCallback)
            mCallback(color());

        return OuterCircle;
    }

    float r = r0 - 6;

    float hueAngle = float(NVG_PI * 2) * mHue;
    const float angle = float(NVG_PI * 120 / 180);
    glm::vec2 a(r * glm::cos(hueAngle + angle), r * glm::sin(hueAngle + angle));
    glm::vec2 b(r * glm::cos(hueAngle - angle), r * glm::sin(hueAngle - angle));
    glm::vec2 c(r * glm::cos(hueAngle), r * glm::sin(hueAngle));

    vec3 bary = calcBarycentric(vec2(x, y), a, b, c);

    float l0 = bary[0], l1 = bary[1], l2 = bary[2];
    bool triangleTest = l0 >= 0 && l0 <= 1.f && l1 >= 0.f && l1 <= 1.f && l2 >= 0.f && l2 <= 1.f;

    if ((consideredRegions & InnerTriangle) &&
            (triangleTest || consideredRegions == InnerTriangle)) {
        if (!(consideredRegions & InnerTriangle))
            return None;
        l0 = std::min(std::max(0.f, l0), 1.f);
        l1 = std::min(std::max(0.f, l1), 1.f);
        l2 = std::min(std::max(0.f, l2), 1.f);
        float sum = l0 + l1 + l2;
        l0 /= sum;
        l1 /= sum;
        mWhite = l0;
        mBlack = l1;
        if (mCallback)
            mCallback(color());
        return InnerTriangle;
    }
    return None;
}