ZX Power
#04
09 января 2000 |
|
Ликбез - алгоритмы быстрой 3D-графики №2. Дополнения и замечания.
Об ошибках статьи "3D графика" в ZX-Power#3 (С) 1999, Пелепейченко Александр __________________________________________ От редакции: В прошлом номере журнала была опублико- вана статья о работе с трехмерными объек- тами, подготовленная нашими друзьями из Avalon - (C) Ruff&Viator. И вот через не- которое время один из читателей сообщил нам о своих замечаниях к вышеупомянутой статье. Публикуем их здесь, рассчитывая на комментарии со стороны Ruff'а... * * * Загрузил я как-то ZX-Power#3 и стал его читать. Собственно, ничего удивительного в этом нет. Так вот, читаю я его, читаю и вдруг натыкаюсь на эту статью. Поскольку я являюсь поклонником 3D графики и разных там эффектов, решаю разобраться в этом способе. К тому же многообещающее предис- ловие разжигает интерес к нижеуказанному способу. Впоследствии я, конечно, понял всю ру- лезность этого способа, но надо сказать, что поначалу я не только не мог врубиться в прилагаемый код, но и ставил под большое сомнение теоретическую часть (в нее я тоже не сразу врубился). Сразу скажу, что спо- соб очень похож на предложенный в SPECTRUM EXPERT#2 "метод средней точки". Внимательно прочитав с десяток раз эту статью, и так и не поняв многого, я решил набить это и проверить его работоспособ- ность. И тут началось самое интересное. Во-первых, в конце процедуры К64 я увидел непонятно откуда взявшийся кусок кода (а точнее даже 2 куска: первый - метка LOOP4 и до конца, второй - то что над этой мет- кой до команды RET). Изучив эти куски я понял, что это подсчет тех же осей, но с учетом ненулевого значения 3D-центра. Во- обще, он (этот кусок) ТАМ не очень нужен (разве что для наглядности). Но... (читай вторую часть статьи). Немного присмотревшись к тексту, я ре- шил, что, вероятнее всего, какая-то часть текста была утеряна. На эту мысль меня на- толкнуло то, что упоминаются рисунки с но- мером 2 и 3, а их там в помине нету. Прим. Ред.: Напечатали все, что было... Оказалось, что координаты точек попута- ны бог знает каким образом, и их печать идет вообще неправильно. Тогда мне стало ясно - ошибки в статье. ALASM был загружен, делать было нечего, и я принялся за отладку программы. Теоре- тическую часть я принял на веру, не прове- ряя ее, а вот код, как оказалось, немного не соответствовал теории. Ошибки щедро одарили подпрограмму AX. Непонятно зачем в самом начале этой проце- дуры было нечто вроде: LD A,E SUB 32 LD E,A ... ; и так далее с регистрами ; L, C , L' Прим. Ред.: Мы их туда не добавляли. :)) Далее, причиной отфонарной печати точек и непонятно какой последовательности хра- нения информации про эти точки было попу- танное местами засылание на стек коорди- нат. Я, конечно, понимаю, что несколько ошибок могут компенсировать друг друга и не считаться ошибками (что могло иметь место в исходниках автора), но в приведен- ном листинге такого не происходило. Веро- ятно, эти ошибки возникли потому, что код в статью писался по памяти. Весь код, ко- торый вы видите здесь, вытянут из уже ра- ботающих исходников, поэтому ошибки подоб- ного рода маловероятны. Я приведу сдесь ВСЮ процедуру AX, так как 80% ее части в POWER#3 являются неверной. На входе в AX в регистрах задаются координаты ключевых то- чек, уже спроектированных в экран. Причем в старшей половине регистра сидит X-коор- дината. TABAX EQU 250 ;вход: ;DE = центр 3D AX LD HX,D ;BC = конец оси z LD LX,E ;HL = конец оси x EXX ;HL'= конец оси y LD A,L ; в POWER#3 PUSH AF ; именно эти PUSH'ы EXX ; оказались LD A,C ; немного PUSH AF ; попутаны LD A,L ; PUSH AF ; LD A,H ; PUSH AF ; EXX ; LD A,H ; PUSH AF ; EXX ; LD A,TABAX LD (VAR),A LD A,B ; в POWER#3 стоит LD A,H LD B,HX CALL K64 ; (*) POP AF LD B,HX CALL K64 POP AF LD B,HX CALL K64 POP AF LD B,LX CALL K64 ; (*) POP AF LD B,LX CALL K64 POP AF LD B,LX CALL K64 RET VAR DEFB 0 Пояснение (*) см. во второй части. Не миновали опечатки и процедуру К64. В том месте, где стоят такие команды (ищите их после метки LOOP3) : LOOP3 ...... DUP 64 SBC HL,DE LD A,H EXX ...... Необходима замена на: DUP 64 LD A,H SBC HL,DE EXX ...... То есть команда LD A,H должна стоять ПЕРЕД SBC HL,DE, иначе таблица оказывается сдвинутой на 1 байт вниз. Больше ошибок и неточностей я не нашел. И несмотря на все вышесказанное, я хочу заметить, что, вероятно, если бы не эти ошибки, я бы так и не разобрался бы с принципом работы этого метода. Конечно, главное - идея, а ошибаться склонен каж- дый. Ну, с ошибками покончено, теперь мои изыскания. часть 2 Метод очень производительный, хотя мож- но сделать его еще быстрее, что несколько раздует К64. Этого можно добиться, если к одной из x-координат при расчете осей при- бавить HX, и то же самое проделать с одной из y-координат, после чего убрать эти при- бавления из процедуры рисования точек. Вы- игрыш будет точно 12 тактов на точке. В этом случае можно приспособить тот кусок кода в К64, о котором я говорил выше.(Мо- жет он и был приспособлен для этого, но коментарий к нему затерялся в редакции). Прим. Ред.: Ну, это уже "наезд"! :)) У нас, в редакции, "затеряться" может только вся статья целиком, но тогда мы ее не на- печатаем... ;)) Для этого нужно именовать его какой-ли- бо меткой, например К64_1. Теперь необходимо CALL K64, помеченные (*) (смотри выше), заменить на CALL K64_1 и убрать команды ADD A,HX и ADD A,LX из процедуры вывода точек. Была идея сделать 4D (5D,6D...) ренде- ринг, однако не было времени, да и без хо- рошей вращалки/леталки делать это нет смысла. А вообще я подумал: "Зачем пользоваться альтернативным регистром hl' в К64, если есть еще неиспользующийся BC??? Тогда (за счет аннулирования EXX'ов) на просчете од- ной оси по обеим координатам удастся сэко- номить еще 8*64*2=1024 тактов + около 256 байт, где 8-сумма EXX'ов в тактах, 64 - у нас там DUP 64, 2 - у одной оси две коор- динаты (x и y). А таких осей 3 штуки..." Подумал я так и накодил более быструю про- цедуру, которая экономит около 3072 тактов на каждом просчете осей. K64 CP B ; эта процедура JP C,LOOP1 ; целиком и полностью SUB B ; вытянута из рабочих LD L,A ; исходников, так что LD H,0 ; ошибки вряд ли ADD HL,HL ; найдутся ADD HL,HL EX DE,HL LD HL,0 LOOP2 LD A,(VAR) LD B,A INC A LD (VAR),A LD C,0 DUP 64 LD A,H ADD HL,DE LD (BC),A INC C EDUP RET LOOP1 LD C,A LD A,B SUB C LD L,A LD H,0 ADD HL,HL ADD HL,HL EX DE,HL LD HL,0 LOOP3 LD A,(VAR) LD B,A INC A LD (VAR),A LD C,0 DUP 64 LD A,H SBC HL,DE LD (BC),A INC C EDUP RET K64_1 CP B JR C,LOOP4 SUB B LD L,A LD H,0 ADD HL,HL ADD HL,HL EX DE,HL LD H,B LD L,0 JP LOOP2 LOOP4 LD C,A LD A,B SUB C LD L,A LD H,0 ADD HL,HL ADD HL,HL EX DE,HL ADD A,C LD H,A LD L,0 JP LOOP3 И еще одно. Если мы уж и стираем с эк- рана избражение для вывода нового, то де- лать это желательно как можно быстрее, что я и предлагаю сделать заменив POP HL:LD (HL),0:POP HL..... таким вариантом: XOR A POP HL:LD (HL),A:POP HL:LD (HL),A... А вообще я так и не смог нарисовать нормальный 3D обьект, состоящий полностью из точек и решил (но еще не сделал) подме- шать draw'ы. Естественно, предложенная стиралка оказалась неприемлимой. Правда, на точках проще отсекать неви- димые и заходящие за экран части, но нари- совать обьект....(у меня после попытки на- рисовать появилась идея сделать мини 3D STUDIO). Проблему перспективы проще всего решить перспективно спроектиравав 3D систему ко- ординат. На этом все. __________________________________________
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября