Столкнулся с такой проблемой существующих процедур рисования окружности, которые можно, в частности, найти здесь на форуме. Например, алгоритм из "Библии демомейкера" в OVER 1 рисует такую окружность:
Столкнулся с такой проблемой существующих процедур рисования окружности, которые можно, в частности, найти здесь на форуме. Например, алгоритм из "Библии демомейкера" в OVER 1 рисует такую окружность:
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
То есть некоторые точки рисуются по два раза. И даже если вообще никто не рисует окружности в режиме OVER 1, то всё равно это - потеря производительности.
Стандартная ПЗУ'шная процедура такой проблемы не имеет.
Хотелось бы найти быструю и корректную в этом смысле процедуру. Что посоветуете?
Есть у меня ещё одна процедура (не помню откуда брал), интересная тем, что радиус можно задавать двухбайтовым числом. И можно рисовать за пределами экрана.
Скрытый текст
Код:void Basic_CIRCLEW_EI (unsigned char cx, unsigned char cy, int radius) __naked { __asm LD IY, #0x5C3A POP DE POP BC ; BC = YX POP HL ; HL = radius PUSH HL PUSH BC PUSH DE LD A, H OR L RET Z BIT 7, H RET NZ PUSH IX DI LD D, #0 LD E, C LD C, B LD B, D PUSH DE LD DE, #0 PUSH DE PUSH BC PUSH HL LD IX, #0 ADD IX, SP PUSH HL EXX POP HL ADD HL, HL EX DE, HL LD HL, #3 AND A SBC HL, DE EXX JR ENT1$ CIRCLOOP1$: AND A SBC HL, DE JP M, EXT1$ POP DE POP HL ADD HL, DE EX DE, HL POP BC POP HL ADD HL, BC LD SP, IX CALL WRAP1$ POP BC POP HL POP DE ADD HL, DE EX DE, HL POP HL ADD HL, BC LD SP, IX CALL WRAP1$ POP DE POP HL AND A SBC HL, DE EX DE, HL POP BC POP HL AND A SBC HL, BC LD SP, IX CALL WRAP1$ POP BC POP HL POP DE AND A SBC HL, DE EX DE, HL POP HL AND A SBC HL, BC LD SP, IX CALL WRAP1$ ENT1$: POP DE POP HL ADD HL, DE EX DE, HL POP BC POP HL AND A SBC HL, BC LD SP, IX CALL WRAP1$ POP BC POP HL POP DE ADD HL, DE EX DE, HL POP HL AND A SBC HL, BC LD SP, IX CALL WRAP1$ POP DE POP HL AND A SBC HL, DE EX DE, HL POP BC POP HL ADD HL, BC LD SP, IX CALL WRAP1$ POP BC POP HL POP DE LD (POSITIV1$+1), DE AND A SBC HL, DE EX DE, HL POP HL ADD HL, BC LD SP, IX CALL WRAP1$ EXX EX DE, HL BIT 7, D JR Z, POSITIV1$ LD HL, (POSITIV1$+1) ADD HL, HL ADD HL, HL LD BC, #6 JR CALCDONE1$ POSITIV1$: LD HL, #0 POP BC DEC BC PUSH BC AND A SBC HL, BC ADD HL, HL ADD HL, HL LD BC, #0xA CALCDONE1$: ADD HL, BC ADD HL, DE EXX POP HL POP DE POP DE INC DE PUSH DE LD SP, IX JP CIRCLOOP1$ EXT1$: LD HL, #8 ADD HL, SP LD SP, HL POP IX EI RET WRAP1$: LD A, D OR A RET NZ LD A, H OR A RET NZ LD A, E CP #0xB0 RET NC LD B, E LD C, L JP 0x22E5 __endasm; }[свернуть]
Но у неё та же проблема:
shurik-ua, спасибо конечно. Но уточню: мне нужна не теория и алгоритм на псевдобейсике, а нормальный отлаженный код на ассемблере Z80. Или совет как пофиксить упомянутые выше процедуры.
Вторую хотелось бы отладить особенно, потому что она редкостная - большинство процедур, которые я здесь встречал, имеют однобайтовые аргументы.
Возможно рисует по две точки как раз из за упрощения/ускорения рисования, просто пожертвовали лишними проверками или точностью алгоритма
Мы хотим получить круто оптимизированный код на ассемблере, чтобы он прямо пиксель в пиксель повторял результат рисования бейсиковского круга? Или можно немножко переставить пикселки в углах, главное чтобы два раза в одном месте не рисовалось, и смотрелось правильно?
Вход определим. X,Y,Z- целые? байт? слово(2 байта) со знаком?
Результат:
На весь экран? (256x192)
Круг частично выходит за экран?
Атрибуты красим? (инк, папер, яркость мигание)
Как опции можно сделать круги с заливкой. Нужно?
В этой процедуре последнюю точку не печатать (если уже была).
Например так (новая подпрограмма печати точки)
Код:WRAP1 LD A, D OR A RET NZ LD A, E CP #B0 RET NC LD A, H OR A RET NZ LD B, E LD C, L WRAP2 LD HL,0 LD (WRAP2+1),BC SBC HL,BC RET Z JP #22E5
Фикс Destr'а рабочий и, в принципе, меня устраивает. Благодарю!
Думаю, можно.
Сейчас у меня просто стоит задача получить хоть какую-то окружность в OVER 1. Но в общем-то:
1. Для библиотеки Basic (ZXDev) нужна процедура окружности. CIRCLEROM там уже есть. CIRCLE задумана как то же самое, но быстрый вариант (все параметры - беззнаковые байты) и не позволяет рисовать за пределами экрана. CIRCLEW - то же самое, но все параметры - слова со знаком. Такой процедуры я не нашёл, поэтому пока удовольствовался процедурой, где координаты - байты без знака, а радиус - слово со знаком. Она умеет рисовать за пределами экрана не всю окружность, а только её часть.
Можно поспорить с тем, нужна ли CIRCLEW непосредственно в библиотеке Basic, но уже пускай будет - по аналогии с RND (результат - байт) и RNDW (результат - слово).
2. Для библиотеки Gfx, которую я недавно начал формировать, пригодились бы и другие варианты окружности, в т.ч. и залитой. Так что буду благодарен.
Последний раз редактировалось Oleg N. Cher; 17.09.2015 в 19:17.
Не могу сказать, сколько раз рисуются точки, - это, вообще, странно слышать, что одна точка несколько раз рисуется. Зачем, также, этот кривой ПЗУшный алгоритм? - разве он не через DRAW рисует? - окружности с малыми радиусами получаются КРИВЫЕ (либо у меня другой бейсик зашит?!).
Рекомендую алгоритм Мичнера. Мне его окружности больше глаз радуют. Сам пока использую сишную процедуру, на асме только рисование точек (под TS-Config). Но давненько хотелось целиком на асм переложить. Может, после работы займусь.
Код:/*--------------------------------------------------- V_MIcirc * Генерирует 1/8 окружности по алгоритму Мичнера */ void V_MIcirc (int xc, int yc, int r, int pixel) { int x, y, d; x= 0; y= r; d= 5 - 2*r; while (x < y) { Pixel_circle(xc, yc, x, y, pixel,MyVPage); if (d < 0) d= d + 4*x + 6; else { d= d + 4*(x-y) + 10; --y; }; ++x; }; if (x == y) Pixel_circle(xc, yc, x, y, pixel, MyVPage); } /* V_MIcirc */ void Pixel_circle(int xc, int yc, int x, int y, int pixel, int pg) __naked { xc,yc,x,y,pixel,pg; __asm di pop af pop hl ; xc ld (5$+1),hl ex de,hl pop hl ld (9$+1),hl ; yc pop hl ld (10$+1),hl ld b,h ld c,l ; x pop hl ld (11$+1),hl ; y pop hl ld a,l ld (7$+1),a pop hl ld a,l ld (6$+1),a ld hl,#-14 add hl,sp ld sp,hl ei ; plot8(xc+x, yc+y); ex de,hl add hl,bc ex de,hl 9$: ld hl,#0 ; yc val 11$: ld bc,#0 ; y val add hl,bc call 2$ ; plot8(xc+y, yc+x); 5$: ld hl,#0 ; xc val ld bc,(11$+1) add hl,bc ex de,hl ld hl,(9$+1) 10$: ld bc,#0 ; x val add hl,bc call 2$ ; plot8(xc+y, yc-x); ld hl,(5$+1) ld bc,(11$+1) add hl,bc ex de,hl ld hl,(9$+1) ld bc,(10$+1) or a,a sbc hl,bc call 2$ ; plot8(xc+x, yc-y); ld hl,(5$+1) ld bc,(10$+1) add hl,bc ex de,hl ld hl,(9$+1) ld bc,(11$+1) or a,a sbc hl,bc call 2$ ; plot8(xc-x, yc-y); ld hl,(5$+1) ld bc,(10$+1) or a,a sbc hl,bc ex de,hl ld hl,(9$+1) ld bc,(11$+1) or a,a sbc hl,bc call 2$ ; plot8(xc-y, yc-x); ld hl,(5$+1) ld bc,(11$+1) or a,a sbc hl,bc ex de,hl ld hl,(9$+1) ld bc,(10$+1) or a,a sbc hl,bc call 2$ ; plot8(xc-y, yc+x); ld hl,(5$+1) ld bc,(11$+1) or a,a sbc hl,bc ex de,hl ld hl,(9$+1) ld bc,(10$+1) add hl,bc call 2$ ; plot8(xc-x, yc+y); ld hl,(5$+1) ld bc,(10$+1) or a,a sbc hl,bc ex de,hl ld hl,(9$+1) ld bc,(11$+1) add hl,bc call 2$ ei ret 2$: ;--- plot routine --- для 0-го окна. ; DE = X ; HL = Y ;--- rom off --- di ld a,#0x0E ; // RAM|NoMAP|WE|BASIC-128 ld bc,#0x21af ;_MemConfig out (c),a ;--------------- add hl,hl ld a,l add a,d and a,#0x3f ld d,a add hl,hl add hl,hl ld a,h 6$: add a,#0x00 ; сюда при чтении аргументов занести номер видеостраницы. ld b,#0x10 ; 0-е окно. out (c),a 7$: ld a,#0x00 ; сюда при чтении аргументов занести значение цвета. ld (de),a ;--- rom on --- ld a,#0x04 ; // ROM|MAP|WP|BASIC-128 ld b,#0x21 ; _MemConfig out (c),a ld b,#0x10 ld a,#3 out (c),a ei ;--------------- ret __endasm; }
Последний раз редактировалось Sergey; 18.09.2015 в 08:36.
С уважением,
Gris / Red Triangle.
_____________________________________
ZX-EVO/TS-Labs config/NGS/HDD/SD-card
Amiga A1200/Blizzard 1230@50/32/60GB
Amiga A1200/Apollo 1260@66/32/60GB
UnAmiga (C5) AGA GM7123 VideoDAC
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)