PDA

Просмотр полной версии : Быстрая заливка треугольников...на синклер Бэйсике



ALKO
26.06.2023, 10:16
Я так понимаю, есть два варианта рисования треугольника с заливкой:
Проверять границы по Point (этот алгоритм у меня есть)
Рисовать рядок линий с изменяемым значением Plot и длины Draw (такого у меня нет. С равнобедренным проще. А рисовать по заданным трëм вершинам сложновато).

В теории, какой из вариантов быстрее? Склоняюсь к версии, что второй, так как первый варик более универсален, и может сгодиться и для окружностей. Универсальность, значит слоупочность.

По второму варику не могу сообразить математически. Там походу ещë нужно как-то последовательность вершин отсортировать, в зависимости от положения бëдер. Сложновато...

- - - Добавлено - - -

ещë недостаток заливки по проверке границ, всегда будет виден wireframe (при заливке диззерингом, например). Некрасиво. Так что, так или иначе, нужно рисовать триангл с ходу, массивом линий.

Bedazzle
26.06.2023, 11:47
ещë недостаток заливки по проверке границ, всегда будет виден wireframe (при заливке диззерингом, например).

Нарисовать тремя линиями треугольник.
Залить.
Стереть тремя линиями треугольник.

b2m
26.06.2023, 11:48
Для начала можно упростить задачу: есть одна верхняя точка и две нижние с одинаковой координатой Y, но с произвольной координатой X. Проведём две линии из верхней точки в нижние. Нужно рисовать обе линии одновременно, так чтобы были известны обе точки на одной горизонтальной линии (которую мы и заполняем). То есть нужно реализовать алгоритм рисования линии (тот-же Брезенхем), но чтобы он работал с двумя линиями одновременно.

ALKO
26.06.2023, 11:54
Нарисовать тремя линиями треугольник.
Залить.
Стереть тремя линиями треугольник.

если по Over 1, то всë равно следы останутся.

- - - Добавлено - - -


Для начала можно упростить задачу: есть одна верхняя точка и две нижние с одинаковой координатой Y, но с произвольной координатой X. Проведём две линии из верхней точки в нижние. Нужно рисовать обе линии одновременно, так чтобы были известны обе точки на одной горизонтальной линии (которую мы и заполняем). То есть нужно реализовать алгоритм рисования линии (тот-же Брезенхем), но чтобы он работал с двумя линиями одновременно.

я тоже теоретически думал о том, чтоб поделить треугольник на два с одним основанием... но всë равно дальше теории не осиливаю. В матеше нуб.

ALKO
26.06.2023, 12:46
примерно так и заливается пол в Eidolon
https://worldofspectrum.net/pub/sinclair/screens/in-game/e/EidolonThe.gif

ну там трапеции, да с прямым основанием. Мне же нужна геометрия погибче. И желательно с возможностью заливки диззерингом в том числе.

Reobne
26.06.2023, 14:39
Вот примитивнейшая заливка на бейсике:
950..970 сортировка вершин по игреку
980 подгонка, чтобы первые два игрека были целые и не равны между собой

Destr
26.06.2023, 18:32
нужно рисовать триангл с ходу, массивом линий.
Вторая половина статьи посвящена заливке полигона (http://zxpress.ru/article.php?id=11766)
А тут заливка конкретно треугольника с примером на СИ (https://compgraphics.info/2D/triangle_rasterization.php) - на бейсике почти так-же.
На спеке хорошо заливать побайтно, только понадобится несколько процедур (для линии целиком в байт попадающей, для линии начало и конец которой в соседних байтах и для линии между началом и концом от 1 до 31 байта). Хорошо юзается для этого табличка, но на бейсике наверное быстрей будет применять математику.

ALKO
26.06.2023, 20:55
Процедурка, подогнанная от Reobne - по кайфу аще.:v2_dizzy_punk:

ZX_NOVOSIB
26.06.2023, 21:41
В теории, какой из вариантов быстрее?
На асме. Чем асм не устраивает?

ALKO
27.06.2023, 09:14
На асме. Чем асм не устраивает?

сложная матеша - камень преткновения.
конвертация пикселя xy в адрес - тоже. Тем более если ускорять - нужно таблицы драконить, а это снова нужно понимание матешы. (на больших пространствах можно ищо ускорить заливкой атрибутами, не задевая пиксельный слой, кстати. Но это если Solid, а не Dithering).
Мне реалтайм, а-ля Another World, в общем-то не нужон (хотя было бы круто, но сложновато). Достаточно и скорости около той что было в "22 позиции"

Bedazzle
27.06.2023, 10:54
конвертация пикселя xy в адрес - тоже.

Есть же готовые процедуры?

Destr
27.06.2023, 11:32
сложная матеша - камень преткновения
На самом деле не такая уж и сложная. Всё можно реализовать Брезенхемом (это только сложения и вычитания)
Конвертация XY в адрес вообще по табличке классической.
Раз ты любитель бейсика - можно асм-функцию забацать и вызывать её через FN как это рекомендовал Инфорком (http://zxpress.ru/book_articles.php?id=1541).

Andrew771
01.07.2023, 00:08
Возможно, будет интересен EOR Fill (https://zx-pk.ru/threads/25777-eor-fill)

ALKO
07.07.2023, 01:19
EOR не пробовал.
Но вот что я уже забабахал на алгоритме, который предоставил Reobne:

https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExcDMydnU0ZWducGt5MnB6cmJ5NGczNzl rMnVxeXl3cXR2dWJxYnp2cCZlcD12MV9pbnRlcm5hbF9naWZfY nlfaWQmY3Q9Zw/5V3ILNTYsMcQonAaMQ/giphy.gif


Если влом смотреть гифку
https://i2.paste.pics/25474f6700abd2c1aef86905f5d442c4.png (https://i2.paste.pics/25474f6700abd2c1aef86905f5d442c4.png)

Reobne
07.07.2023, 23:37
Как ты так нарисовал? В каком-то векторном редакторе на ПиСи, потом экспортировал в треугольники и линии? Или всё на Спектруме? А программку на бейсике - откомпилировал?

Треугольники треугольниками, но в основном в этой картинке многоугольники.

goodboy
08.07.2023, 08:17
вот что я уже забабахал
похожа на Ivy из SoulCalibur

ALKO
08.07.2023, 12:51
похожа на Ivy из SoulCalibur

Она и есть. Моя первая (и последняя) компьюторная любофб. Буратины из ПС1 не могли так впечатлить, как впечатлила в своё время дримка своими округлостями. Но тогда, гаде в 2001-ом, когда я впервые увидел сей божественный графин, я загорелся желанием таки засунуть полиговны в хз-спектрум (ибо дримки были разве что в игровых клубах, а в нашей нищей семейке лишь Горбатый на отечественных микросхемах).
И вот наконец-то воплощаю в жызнь давнюю мечту.

- - - Добавлено - - -


реугольники треугольниками, но в основном в этой картинке многоугольники.
Состоящие из треугольников, как это сделано в любой современной игре.

- - - Добавлено - - -


В каком-то векторном редакторе на ПиСи, потом экспортировал в треугольники и линии? Или всё на Спектруме?

За пару дней набросал свой редактор на SDL (возможно, применю его в отношении сеги и DOS ega|cga, а также для вуды на OpenGL 1.0.)

Destr
08.07.2023, 13:23
За пару дней набросал свой редактор на SDL
Ну вот ещё-бы вывод побыстрей.
Вот процедура с произвольной заливкой (кажется из 3Dlame) - прикрутить сумеешь наверное.



DEVICE ZXSPECTRUM48
DISPLAY "END=", END
STARTFORSNA EQU #8000
ORG STARTFORSNA
DI
LD SP,#8000
CALL DECRUN
LD HL,#2020,DE,#90E0,BC,#10a5:CALL TRIUGOL:JR $

TRIUGOL ;[ рисовалка треугольников с текстурой
; HL=вершина1, DE=вершина2, BC=вершина3
LD (AAA),HL,(BBB),DE,(CCC),BC

SORT ;[ сортировка пузырьковым методом
LD B,2
SORT1 PUSH BC:LD B,2:LD IX,AAA
SORT2 LD A,(IX+1):CP (IX+3):JP C,SORT3
LD H,(IX+3):LD L,(IX+2):LD C,(IX)
LD (IX+3),A:LD (IX+2),C:LD (IX+1),H:LD (IX),L
SORT3 INC IX,IX:DJNZ SORT2
POP BC:DJNZ SORT1 ;]
LD HL,(BBB),DE,(AAA),LY,D
LD A,H:CP D:JP Z,TRIU2
SUB D:LD C,A:EXA
CALL CALK
PUSH DE:EXX:POP DE:EXX
LD HL,(CCC),DE,(AAA)
LD A,H:SUB D:LD C,A
CALL CALK
PUSH DE:EXX:POP BC:EXX
LD HL,(AAA),B,L,C,0:LD (CRD1+1),BC,(CRD2+1),BC
CALL TRI3
EXA:LD B,A
CALL TRI2
LD HL,(CCC),DE,(BBB)
LD A,H:SUB D:LD C,A:EXA
CALL CALK
PUSH DE:EXX:POP DE:EXX
TRIU1 EXA:OR A:RET Z:LD B,A:JP TRI2
TRIU2 LD HL,(CCC),DE,(AAA)
LD A,H:SUB D:RET Z
LD C,A:EXA
CALL CALK
PUSH DE:EXX:POP DE:EXX
LD HL,(CCC),DE,(BBB)
LD A,H:SUB D:LD C,A
CALL CALK
PUSH DE:EXX:POP BC:EXX
LD HL,(AAA),DE,(BBB)
LD B,L,C,0,(CRD1+1),BC
LD B,E,(CRD2+1),BC
CALL TRI3
JP TRIU1
LINEM LD A,LY:AND 7:PUSH HL
L_TEXTU LD HL,(F_MASK),E,A,D,0:ADD HL,DE
LD A,(HL)
CPL ; CPL если нужна инверсия, NOP если не нужна
POP HL:LD HY,A
LD A,B:SUB C:JP NC,LINEM1
LD A,B:LD B,C:LD C,A
LINEM1 LD A,C,D,#F8:AND D:RRA:RRA:RRA:ADD A,L:LD L,A
LD A,C:AND D:LD E,A
LD A,B:AND D:CP E
JP NZ,LINEM3
LD A,C:AND 7:ADD A,low MASKA_A:LD E,A
LD A,high MASKA_A:ADC A,0:LD D,A
LD A,(DE)
LD C,A
LD A,B:AND 7:ADD A,8:ADD A,low MASKA_A:LD E,A:LD A,D:ADC A,0:LD D,A
LD A,(DE):AND C:LD E,A:CPL:AND (HL)
LD B,A:LD A,E:AND HY:OR B:LD (HL),A
RET
LINEM3 LD E,C
LD A,C:AND D:LD C,A
LD A,E:AND 7:ADD A,low MASKA_A:LD E,A
LD A,high MASKA_A:ADC A,0:LD D,A
LD A,(DE):LD E,A:CPL:AND (HL):LD (HL),A
LD A,E:AND HY:OR (HL):LD (HL),A:INC L
LD A,B:AND 7:ADD A,8:ADD A,low MASKA_A:LD E,A
LD A,D:ADC A,0:LD D,A
LD A,(DE):LD E,A
LD A,B:AND #F8:SUB C:SUB 8:JP Z,LINEM4
RRA:RRA:RRA:LD B,A:LD A,HY
LINEM5 LD (HL),A
INC L:DJNZ LINEM5
LINEM4 LD A,E:CPL:AND (HL):LD B,A:LD A,E:AND HY:OR B:LD (HL),A ;**

RET
CALK LD B,0
LD A,L:SUB E:LD E,B:JP NC,CALK1
NEG:LD D,A:CALL DIV
LD A,E:CPL:LD E,A
LD A,D:CPL:LD D,A
INC DE
RET
CALK1 LD D,A:JP DIV
TRI2 PUSH BC:EXX
CRD1 LD HL,0:ADD HL,DE:LD (CRD1+1),HL
LD A,H:LD (TRI2_+1),A
CRD2 LD HL,0:ADD HL,BC:LD (CRD2+1),HL
LD A,H:EXX
TRI2_ LD C,0:LD B,A:LD L,(IX):LD H,(IX+1)
CALL LINEM
INC LY:INC IX,IX
POP BC:DJNZ TRI2
RET
TRI3 LD L,H:LD H,0:LD BC,TSCRB:ADD HL,HL:ADD HL,BC:PUSH HL:POP IX
RET
;]
DIV ;[ DE = DE/BC с округлением ответа
PUSH BC
LD A,B:CPL:LD B,A
LD A,C:CPL:LD C,A
INC BC
LD HL,0
LD A,E
ADD A,A
RL D
DUP 16
ADC HL,HL
ADD HL,BC
JP C,$+5
SBC HL,BC
RLA
RL D
EDUP
LD E,A
POP BC
SRL B
RR C
OR A:SBC HL,BC:RET C
INC DE
RET
;]

DECRUN ;[ делаем табличку адресов в экране
LD DE,#4000:LD HL,TSCRB:LD B,#c0
DECR4 LD (HL),E:INC HL:LD (HL),D:INC HL:CALL DW_DE
DECR5 DJNZ DECR4
DW_DE INC D:LD A,D:AND 7:RET NZ
LD A,E:ADD A,32:LD E,A:RET C
LD A,D:SUB 8:LD D,A
RET
;]

;[
AAA DW 0
BBB DW 0
CCC DW 0
F_MASK DW #3C00+8*"D" ; адрес знакоместа чем заливать
TSCRB DS 384
;]
MASKA_A DB #FF,#7F,#3F,#1F,#0F,#07,#03,#01,#80,#C0,#E0,#F0,#F 8,#FC,#FE,#FF
END
SAVESNA "basic-poly_text.sna",STARTFORSNA
LABELSLIST "user.l"


Формат SJASM, но это не принципиально.
Один раз вызвать декрюнчер, потом юзать.
Для примера заливается литерой "D" со включеной инверсией. Можно регулировать.
Размер вместе с табличкой - #044F (1103 байта)