Изобразяване на изгладени линии с текстури =› търсене на много прост пример

Има този сайт...

... където обясняват как да начертаете антиалиасирана линия.

Точно това, което искам!
но...

Не разбирам как да постигна това за проста линия. Намерих онлайн версията на книгата (статията донякъде е извлечена от книгата), изтеглих примерния код (показващ фигура с пръчка, която прави фантастични движения), но се случват толкова много mambojambo... някои странни python скрипт... кръгове като png-изображения и като заглавни файлове, почти всичко е написано в cpp, файловете, които копирам в моя проект, произвеждат много грешки, които не мога да разреша правилно и така нататък, и така нататък. И мисля, че нямам нужда от всички тези фантастични неща, тъй като искам да рисувам линии само в просто приложение, базирано на cocos2d [между другото.... Не исках да използвам AA, но линиите ми са по-дебели от 5px, което прави ги да имат грозни дупки, когато са свързани (напр. в кръг, направен от няколко линии), така че трябва да използвам AA, както изглежда].

И така, някой има ли или е намерил малка част от изпълним примерен код, използвайки принципа, обяснен в свързаната статия?


Бележки:

  1. На снимката виждате дупките:
    http://pimml.de/circles.png

  2. Тук ще намерите кода на споменатия стикмен (AA Lines): http://examples.oreilly.com/9780596804831/readme.html#AaLines

  3. Ето как рисувам моите кръгове:

    int segments = 80;
    CGFloat width = 100;
    CGFloat height = 100;
    CGPoint center = ccp(800,200);  
    
    glDisable(GL_TEXTURE_2D);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    //glEnable(GL_LINE_SMOOTH); // doesn't work on device
    glTranslatef(center.x, center.y, 0.0);
    glLineWidth(3.0f);
    GLfloat vertices[segments*2];
    int count=0;
    for (GLfloat i = 0; i < 360.0f; i+=(360.0f/segments))
    {
        vertices[count++] = (cos(degreesToRadian(i))*width);
        vertices[count++] = (sin(degreesToRadian(i))*height);
    }
    glVertexPointer (2, GL_FLOAT , 0, vertices); 
    glDrawArrays (GL_LINE_LOOP, 0, segments);
    
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnable(GL_TEXTURE_2D);    
    

person Allisone    schedule 08.09.2010    source източник


Отговори (3)


И аз се натъкнах на този проблем. Прекарах известно време в измисляне на това... Използвах решение, подобно на това за известно време (чрез walterBenjamin на Apple.com):

https://devforums.apple.com/message/264670

Това работи, лесно е и изглежда добре, но все още не е най-доброто (за това, което правя). В крайна сметка написах мое собствено решение, което комбинира рисуване на частици от GL Paint с неговото решение за чертане на линия от точка до точка.

Направих масив и при touchesBegin, touchesMoved добавих точка към него:

[currentStroke addObject:[NSValue valueWithCGPoint:point]]

След това итерирам щрихите, както виждате в GL Paint, използвайки GL_Points.

person Beaker    schedule 16.09.2010
comment
Няма проблем. Надявам се да помогна и съжалявам, че не го видях по-рано! - person Beaker; 17.09.2010
comment
Е, вие сте нов тук, така че дори е честно, че моят беше първият въпрос, на който отговорихте, докато вярвах, че никой няма да отговори повече. Но трябва да призная, че вече успешно внедрих техниката AALine с текстури преди два дни (след много болка, причинена от толкова много c++ елементи и библиотеки, които не разбирах, и смесването в рамката obj-c cocos2d). Вашият проработи веднага и сега ще изчистя кода си, ще го оптимизирам и след това ще реша според производителността коя техника да използвам. - person Allisone; 17.09.2010
comment
Може би ще намеря малко време да публикувам тук ясен и прост пример за другата техника. - person Allisone; 17.09.2010
comment
Хах благодаря Бих искал да публикувам кода, но съм под NDA... което е досадно. Както и да е, не мога да публикувам кода, но ако имате конкретни въпроси, сигурен съм, че мога да им отговоря, без да си създавам големи проблеми. Бележка за изпълнението. Методът GL_Paint изглежда страхотно за начертани от потребителя линии, по-добре от метода на допирателната от форумите на Apple, само защото е много по-гладък. Въпреки това може да се забави и трябваше да отделя част от времето за оптимизация... - person Beaker; 17.09.2010

Благодарение на Paul Haeberli, ето някакъв код, който той сподели с мен за изчертаване на антиалиасни кутии, точки и линии:

/*
 *   Antialised 2D points, lines and rectangles for iOS devices
 *
 *   The feathered edge of these primitives is width/2.0.
 *
 *   If you are working in screen space, the width should be 1.0.
 *
 *       Paul Haeberli 2010
 *
 */
void fillSmoothRectangle(CGRect *r, float width)
{
    GLfloat rectVertices[10][2];
    GLfloat curc[4]; 
    GLint   ir, ig, ib, ia;

    // fill the inside of the rectangle
    rectVertices[0][0] = r->origin.x;
    rectVertices[0][1] = r->origin.y;
    rectVertices[1][0] = r->origin.x+r->size.width;
    rectVertices[1][1] = r->origin.y;
    rectVertices[2][0] = r->origin.x;
    rectVertices[2][1] = r->origin.y+r->size.height;
    rectVertices[3][0] = r->origin.x+r->size.width;
    rectVertices[3][1] = r->origin.y+r->size.height;

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, rectVertices);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    rectVertices[0][0] = r->origin.x;
    rectVertices[0][1] = r->origin.y;
    rectVertices[1][0] = r->origin.x-width;
    rectVertices[1][1] = r->origin.y-width;
    rectVertices[2][0] = r->origin.x+r->size.width;
    rectVertices[2][1] = r->origin.y;
    rectVertices[3][0] = r->origin.x+r->size.width+width;
    rectVertices[3][1] = r->origin.y-width;
    rectVertices[4][0] = r->origin.x+r->size.width;
    rectVertices[4][1] = r->origin.y+r->size.height;
    rectVertices[5][0] = r->origin.x+r->size.width+width;
    rectVertices[5][1] = r->origin.y+r->size.height+width;
    rectVertices[6][0] = r->origin.x;
    rectVertices[6][1] = r->origin.y+r->size.height;
    rectVertices[7][0] = r->origin.x-width;
    rectVertices[7][1] = r->origin.y+r->size.height+width;
    rectVertices[8][0] = r->origin.x;
    rectVertices[8][1] = r->origin.y;
    rectVertices[9][0] = r->origin.x-width;
    rectVertices[9][1] = r->origin.y-width;

    glGetFloatv(GL_CURRENT_COLOR, curc);
    ir = 255.0*curc[0];
    ig = 255.0*curc[1];
    ib = 255.0*curc[2];
    ia = 255.0*curc[3];

    const GLubyte rectColors[] = {
        ir, ig, ib, ia,
        ir, ig, ib, 0,
        ir, ig, ib, ia,
        ir, ig, ib, 0,
        ir, ig, ib, ia,
        ir, ig, ib, 0,
        ir, ig, ib, ia,
        ir, ig, ib, 0,
        ir, ig, ib, ia,
        ir, ig, ib, 0,
        ir, ig, ib, ia,
        ir, ig, ib, 0,
    };

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, rectVertices);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, rectColors);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 10);
    glDisableClientState(GL_COLOR_ARRAY);
}

void drawSmoothLine(CGPoint *pos1, CGPoint *pos2, float width)
{
    GLfloat lineVertices[12], curc[4]; 
    GLint   ir, ig, ib, ia;
    CGPoint dir, tan;

    width = width*8;
    dir.x = pos2->x - pos1->x;
    dir.y = pos2->y - pos1->y;
    float len = sqrtf(dir.x*dir.x+dir.y*dir.y);
    if(len<0.00001)
        return;
    dir.x = dir.x/len;
    dir.y = dir.y/len;
    tan.x = -width*dir.y;
    tan.y = width*dir.x;

    lineVertices[0] = pos1->x + tan.x;
    lineVertices[1] = pos1->y + tan.y;
    lineVertices[2] = pos2->x + tan.x;
    lineVertices[3] = pos2->y + tan.y;
    lineVertices[4] = pos1->x;
    lineVertices[5] = pos1->y;
    lineVertices[6] = pos2->x;
    lineVertices[7] = pos2->y;
    lineVertices[8] = pos1->x - tan.x;
    lineVertices[9] = pos1->y - tan.y;
    lineVertices[10] = pos2->x - tan.x;
    lineVertices[11] = pos2->y - tan.y;

    glGetFloatv(GL_CURRENT_COLOR,curc);
    ir = 255.0*curc[0];
    ig = 255.0*curc[1];
    ib = 255.0*curc[2];
    ia = 255.0*curc[3];

    const GLubyte lineColors[] = {
        ir, ig, ib, 0,
        ir, ig, ib, 0,
        ir, ig, ib, ia,
        ir, ig, ib, ia,
        ir, ig, ib, 0,
        ir, ig, ib, 0,
    };

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, lineVertices);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, lineColors);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
    glDisableClientState(GL_COLOR_ARRAY);
}


void drawSmoothPoint(CGPoint *pos, float width)
{
    GLfloat pntVertices[12], curc[4]; 
    GLint   ir, ig, ib, ia;

    pntVertices[0] = pos->x;
    pntVertices[1] = pos->y;
    pntVertices[2] = pos->x - width;
    pntVertices[3] = pos->y - width;
    pntVertices[4] = pos->x - width;
    pntVertices[5] = pos->y + width;
    pntVertices[6] = pos->x + width;
    pntVertices[7] = pos->y + width;
    pntVertices[8] = pos->x + width;
    pntVertices[9] = pos->y - width;
    pntVertices[10] = pos->x - width;
    pntVertices[11] = pos->y - width;

    glGetFloatv(GL_CURRENT_COLOR,curc);
    ir = 255.0*curc[0];
    ig = 255.0*curc[1];
    ib = 255.0*curc[2];
    ia = 255.0*curc[3];

    const GLubyte pntColors[] = {
        ir, ig, ib, ia,
        ir, ig, ib, 0,
        ir, ig, ib, 0,
        ir, ig, ib, 0,
        ir, ig, ib, 0,
        ir, ig, ib, 0,
    };

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, pntVertices);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, pntColors);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
    glDisableClientState(GL_COLOR_ARRAY);
}
person snibbe    schedule 23.01.2011

Съжалявам - прочетох въпроса твърде бързо - изтълкувах погрешно целта ви.
person AechoLiu    schedule 08.09.2010
comment
Работи ли върху кръг от 10 px? Имате ли работещ примерен код? - person Allisone; 09.09.2010
comment
Проблемът ми е, че моята текстура е начертана с правоъгълник и ръбовете се нуждаят от анти-алиас. Когато разглеждам този сайт и получавам връзката, решавам проблема си, като преначертавам линиите по ръбовете отново. Сега работи добре. Но моите кодове са opengl-es, а не cocos2d. - person AechoLiu; 09.09.2010
comment
Cocos2d използва OpenGL-es. Това е просто хубава рамка с много лесни за използване неща като спрайтове, менюта, анимации, преходи на сцени и т.н. - person Allisone; 09.09.2010
comment
Може би някой ден ще науча Cocos2d. Но моят проект в момента използва iPhone-SDK и opengl-es. Аз не съм шеф, така че... - person AechoLiu; 09.09.2010