Просмотр полной версии : Быстрое вращение в 3Д
Пытался найти оптимальный способ поворота точек в пространстве, несколько раз почитал статью из ZX Power #3,#4 (можно по ссылке http://zxdn.narod.ru/coding/zpw3gf3d.txt), но так до конца и не въехал.
внимание вопрос:
Может кто попроще объяснить алгоритм?
В смысле просто алгоритм поворота точки вокруг другой на определенный градус или именно конкретно оптимизированный?
Интересует алгоритм работы
http://zxdn.narod.ru/coding/zpw3gf3d.txt
Т.е. что хранится в таблица, какие таблицы, когда какие вычисления и т.п.
Естественно интересует конкретно оптимизированный вокруг начала координат)
В этих исходниках и идеях есть только расчет экранных координат по известным координатам ортов. Вращения ортов там нет.
Судя по тому, сколько радости доставило автору статьи его открытие, еще больше его удивит, что матрица преобразования собственно и составляется из координат ортов, что при раскрытии и дает те же формулы для экранных координат.
В этом смысле смущают, во-первых, сравнение формул для вычисления экранных координат с вращением ортов (две формулы с синусами и косинусами в начале статьи) с формулами для расчета того же по уже повернутым ортам и, во-вторых, противопоставление умножения в этих формулах ("каким бы быстрым оно ни было") тому же умножению в таблицах.
Далее, смущают упоминания ELITE. Опять же, во-первых, в ELITE считается несколько объектов, каждый со своими углами поворота, что по предложенному методу будет означать вычисление таблицы умножения для каждого объекта. Во-вторых, в ELITE дапазоны значений координат объектов куда как шире 64 делений и используются "настоящие" 8- и 16-разрядные умножения. В-третьих, для сравнения, в ELITE умножение считается по таблицам квадратов, что с учетом необходимости генерирования таблиц умножения по методу автора статьи, вряд ли медленнее.
Хорошо, тогда вопрос номер 2:
Кто нито занимался оптимизацией поворота только по двум осям Ох, Оу (в 99% случаев с эффектами заглаза) на основе таблиц.
Самый простой вариант конечно допустим поворот по Ох берем из таблицы, остальное честно считаем.
Какие нито сферические или свои системы координат ктонито использовал (Пусть даже для нечестного с математической точки зрения вращения)?
Кто нито занимался оптимизацией поворота только по двум осям Ох, Оу (в 99% случаев с эффектами заглаза) на основе таблиц.
Самый простой вариант конечно допустим поворот по Ох берем из таблицы, остальное честно считаем.
Какие нито сферические или свои системы координат ктонито использовал (Пусть даже для нечестного с математической точки зрения вращения)?
Если среди Ox и Oy нет оси, которая перпендикулярна экрану, то точки будут вращаться по окружности, проекция которой, в общем случае, будет эллипсом, оси которого будут горизонтальным и вертикальным отрезками, т.е. эллипс будет без наклона -- ровно так, как его только и можно нарисовать быстро. Вращение вокруг горизонтальной оси будет изменять отношение малой оси эллипса к большой: a = b * sin(alpha), где alpha -- угол повотора. Вращение вокруг вертикальной оси будет перемещать точку по дуге получившегося эллипса. Имея представление об алгоритме построения эллписов в растре, это можно сделать быстро даже без таблиц.
Вот почитай: Поворот 3D вектора за шесть умножений (http://www.enlight.ru/faq3d/articles/73.htm), может поможет))
Если среди Ox и Oy нет оси, которая перпендикулярна экрану, то точки будут вращаться по окружности, проекция которой, в общем случае, будет эллипсом, оси которого будут горизонтальным и вертикальным отрезками, т.е. эллипс будет без наклона -- ровно так, как его только и можно нарисовать быстро. Вращение вокруг горизонтальной оси будет изменять отношение малой оси эллипса к большой: a = b * sin(alpha), где alpha -- угол повотора. Вращение вокруг вертикальной оси будет перемещать точку по дуге получившегося эллипса. Имея представление об алгоритме построения эллписов в растре, это можно сделать быстро даже без таблиц.
Прорабатывал приблизительно такую идею, брал в качестве координат Z, угол Ox, угол Oy. Сломал голову как предыдущий поворот отражается на следующем, ответ эллипс спас от взрыва мозга :)
Подумаю на досуге, хотя уже сделал тупо на основе таблиц coord*sin(alpha), coord*cos(alpha) и таблицы проецирования,
без оптимизации порядка 215 тактов что вполне приемлемо (предыдущий вариант был 110, но пока не знаю как учет эллипса скажется)
Главное как решишь вопрос поделись сорцом, уверен пригодится не только мне.
Сам в 3D вообще не шарю, а тут еще оптимизация...
Добавлено через 1 минуту
Странно что CJ молчит. Не все же у них анимация? ;)
Ну код для ротатора на основе таблиц произведений координат на sin/cos углов я думаю не сложно написать.
Вот например: :)
//----------------------------------------
// 3D 2-Axis table rotator
//----------------------------------------
; Максимально возможная длина по осям в одну сторону 15
; (т.е. общая длина оси в обе стороны 31, что
; в принципе вполне достаточно для чанковых эффектов,
; но если нужно например для диапазона в 256 т.е. для
; точек, то можно соответственным образом подкорректировать
; таблицу проекций, считая ее умножая координаты на 4)
; Вычисление таблицы проекций здесь не приводится
; Считать ее можно так:
; PX = X0 + (X*CamDist)/(CamDist+Z));
; PY = Y0 + (Y*CamDist)/(CamDist+Z));
; Для диапазона координат -XYZMAX..0..+XYZMAX
; или для диапазона -127..0..+127
; PX = X0 + (4*X*CamDist)/(CamDist+Z*4));
; PY = Y0 + (4*Y*CamDist)/(CamDist+Z*4));
; где X0,Y0 - координаты центра экрана
; CamDist - расстояние до камеры (подбираем на глаз)
; Диапазон изменения угла вращения 0..127
; Поворот осуществляется вокруг осей Ox,Oy
; по адресу Ay - угол вращения вокруг Oy
; по адресу Ax - угол вращения вокруг Ox
//----------------------------------------
// Переменные и константы
//----------------------------------------
XYZMAX EQU 15 ; максимальная длина по осям (в одну сторону)
COR_PZ EQU #E0+XYZMAX ; коэффициент для Z
COR_Z EQU #C0+XYZMAX
COR_PX EQU XYZMAX
COR_PY EQU #20+XYZMAX
; Начальные координаты точек хранятся в формате
; X=X+COR_Z
; Y=Y+COR_Z
; Z=Z+COR_Z
; (т.е. с прибавленным смещением до начала таблиц)
//----------------------------------------
// Формулы вращения
//----------------------------------------
; OX:
; y =y*cos(Ay) - z*sin(Ay)
; z =y*sin(Ay) + z*cos(Ay)
; OY:
; x =x*cos(Ax) - z*sin(Ax)
; z =x*sin(Ax) + z*cos(Ax)
//----------------------------------------
// Формат хранения таблиц:
//----------------------------------------
; Таблица произведений:
; #C000 #C080
; +--------------+--------------+
; Coord| Coord*cos(A) | Coord*sin(A) |
; +--------------+--------------+
; Alpha Alpha
; Таблица проекций
; #E000 #E020
; +------+------+
; Z| PX | PY |
; +------+------+
; X Y
; вообще говоря можно таблицу проекций
; совместить с таблицей произведений,
; уменьшив при этом диапазон угла
; вращений до 0..95, как показано ниже,
; но приведенные тут значения соответствуют
; верхним таблицам
; #C000 #C060 #C080 #C0E0
; +--------------+-----+-------------+-----+
; Coord| Coord*cos(A) | PX |Coord*sin(A) | PY |Z
; +--------------+-----+-------------+-----+
; Alpha X Alpha Y
//----------------------------------------
// Создание таблицы произведений:
//----------------------------------------
; Изначально имеем таблицу cosA,sinA со значениями*256 (т.е. макс знач =1 в старшем байте)
; Можно написать генерилку, а можно расчитать на бейсике/паскале
; var
; alpha: integer;
; sc_tbl: array [0..255] of word;
; for alpha:=0 to 127 do
; begin
; sc_tbl[alpha]:=trunc(256*Cos(alpha*Pi/64));
; sc_tbl[alpha+128]:=trunc(256*Sin(alpha*Pi/64));
; end;
; далее считаем на асме
SC_TBL INCBIN "SC_TBL" ; Сгенерированная таблица [512 байт]
TMP_SC EQU #???? ; временная таблица, изначально содержит нули [512 байт]
CALC_TBL_PROIZV
; таблицы считаем накопительным сложением
//--- нулевой ряд
LD HL,#C000+XYZMAX*256
LD D,H
LD E,L
INC E
LD (HL),0
LD BC,255
LDIR
//--- положительный ряд
EXX
LD HL,#C000+256+XYZMAX*256
LD C,XYZMAX
SCC1 EXX
LD IX,TMP_SC
LD HL,SC_TBL
EXX
LD B,0
SCC0 EXX
LD E,(IX)
INC IX
LD D,(IX)
INC IX
LD C,(HL)
INC HL
LD B,(HL)
INC HL
EX DE,HL
ADD HL,BC
EX DE,HL
LD (IX-2),E
LD (IX-1),D
LD A,D
EXX
LD (HL),A
INC HL
DEC B
JP NZ,SCC0
DEC C
JP NZ,SCC1
//--- отрицательный ряд
LD HL,#C000+256+XYZMAX*256
LD DE,#C000-256+XYZMAX*256
LD C,XYZMAX
SSC3 LD B,0
PUSH DE
SSC2 LD A,(HL)
INC HL
NEG
LD (DE),A
INC DE
DJNZ SSC2
POP DE
PUSH HL
LD HL,0-256
ADD HL,DE
EX DE,HL
POP HL
DEC C
JP NZ,SSC3
//---
RET
//----------------------------------------
// Вращение и проецирование:
//----------------------------------------
; in: D-y E-x С-z
; out: D-py,E-px,A-z спроецированные координаты
//----
ROT3D //--- вращение по оси OY:
LD L,0 ;7
Ay EQU $-1
LD H,E ;4 (HL)=X*cosA
LD A,(HL) ;7 A=X*cosA
LD H,C ;4
SET 7,L ;8 (HL)=Z*sinA
SUB (HL) ;7 A=X*cosA-Z*sinA
ADD A,COR_PX ;7
LD B,A ;4
LD H,E ;4
LD A,(HL) ;7
LD H,C ;4
RES 7,L ;8
ADD A,(HL) ;7
ADD A,COR_Z ;7
LD C,A ;4 // 49+24+16=89
//--- вращение по оси OX:
LD L,0 ;7
Ax EQU $-1
LD H,D ;4
LD A,(HL) ;7
LD H,C ;4
SET 7,L ;8
SUB (HL) ;7
ADD A,COR_PY ;7
LD E,A ;4
LD H,D ;4
LD A,(HL) ;7
LD H,C ;4
RES 7,L ;8
ADD A,(HL) ;7
ADD A,COR_PZ ;7 // 49+24+16=89
//--- проецирование
LD H,A ;4
LD L,E ;4
LD D,(HL) ;7
LD L,C ;4
LD E,(HL) ;7
SUB COR_PZ-XYZMAX ;7 // 12+21=33 нормализация Z в диапазоне 0..XYZMAX*2+1
//---
RET
Ну код для ротатора на основе таблиц произведений координат на sin/cos углов я думаю не сложно написать.
Вершины дрожать будут?
По опыту: младшим байтом таблицы лучше адресовать радиус, а старшим- угол поворота. Ибо гранулярность угла (~6 градуса для 16к-таблицы и ~3 градуса для 32к-таблицы) не так мешает, как ограничение на длину. Тем более что для маленьких радиусов половина таблицы будет иметь одинаковые значения.
В разделе кодинга TaganNews две статьи писал на эту тему. С примерами.
Вершины дрожать будут?
Надо смотреть.
При малых шагах по углам вращений и низком фпс наверняка будут.
но если подобрать шаги и достаточно динамично по фпс сделать то незаметно дрожания.
а вообще да, никто не мешает как Vitamin предложил взять диапазон угла 64 (старший байт адреса таблицы), а диапазон координат 128 (младший).
И хранить тока coord*cos(alpha), а sin получать увеличением угла на нужное значение. А по адресам где младший байт больше 128 хранить проекции без добавления X0,Y0 (при этом в старшем байте берем Z/2)
В принципе можно и для чанков так сказать из большего в меньшее, т.е. в таблице храним проекции поделенные на коэффициент.
А-а, ну нафик, слишком сложно для меня.
Да и демка не игра, заранее просчитать координаты, сцена будет динамичнее и зрелищнее.
Все равно два с половиной человек поймет, что оно не совсем реалтайм, а кому-то что то доказывать... ушли уже те времена.
Странно что CJ молчит. Не все же у них анимация?
везде и всегда!
честная математика для 3D у нас сделана в HARM, TRAUMWERK и WEED - причем в WEED используется немного измененные исходники из Spectrum Expert'a (X-Trade). В чанковом 3D движок я писал полностью сам, но опирался опять же на x-trade'овские сорцы - отличие в скорости есть, но не сказать что сильно уж значительное. Еще использовались некоторые математические процедуры от Baze/3SC (немного оптимизированные), которые можно посмотреть у него на страничке.
Вспоминаем IRIS :) Часть 3.5MHz называется :)
http://zxaaa.untergrund.net/DISKI/disk50.zip
Поворот одной точки по трем осям (оптимизация возможна):
;IX - pointer to <x,y,z> coords (input)
;IY - pointer to <x,y> coords (output)
LD A,(RX)
AND 252
RRA
SCF
RRA
LD H,A
LD L,(IX+1) ;Y
LD B,L
LD C,(HL) ;Y*SIN(RX)
LD L,(IX+2) ;Z
LD E,(HL) ;Z*SIN(RX)
LD A,H
ADD A,16
AND 191
LD H,A
LD A,(HL) ;Z*COS(RX)
ADD A,C
LD C,A ;Z'= Z*COS(RX)+Y*SIN(RX)
LD L,B ;Y
LD A,(HL) ;Y*COS(RX)
SUB E
LD E,A ;Y''=Y*COS(RX)-Z*SIN(RX)
LD A,(RY)
AND 252
RRA
SCF
RRA
LD H,A
LD L,C
LD C,(HL) ;Z'*SIN(RY)
LD A,H
ADD A,16
AND 191
LD H,A
LD L,(IX) ;X
LD A,(HL) ;X*COS(RY)
ADD A,C
LD C,A ;X''=X*COS(RY)+Z'*SIN(RY)
LD A,(RZ)
AND 252
RRA
SCF
RRA
LD H,A
LD L,C
LD B,(HL) ;X''*SIN(RZ)
LD L,E
LD E,(HL) ;Y''*SIN(RZ)
LD A,H
ADD A,16
AND 191
LD H,A
LD A,(HL) ;X''*COS(RZ)
ADD A,B
ADD A,96
LD (IY+1),A ;Y'''
LD L,C
LD A,(HL) ;Y''*COS(RZ)
SUB E
ADD A,128
LD (IY),A ;X'''
INC IX
INC IX
INC IX
INC IY
INC IY
И расчет таблицы:
DECRUNT LD HL,#8000
DCR PUSH HL
LD A,H
SUB #80
ADD A,A
ADD A,A
LD H,L
CALL HSINA
POP HL
LD (HL),A
INC HL
LD A,H
CP 192
JR NZ,DCR
RET
HSINA ;A=H*SIN A
LD D,'SINUS
LD E,A
LD A,(DE)
HMULAA AND A
JP M,NEGE
BIT 7,H
JR Z,ALPOS
EX AF,AF'
LD A,H
NEG
LD H,A
EX AF,AF'
JR NEGRES
ALPOS CALL MULS
ADD HL,HL
LD A,H
RET
NEGE NEG
BIT 7,H
JR Z,NEGRES
EX AF,AF'
LD A,H
NEG
LD H,A
EX AF,AF'
JR ALPOS
NEGRES CALL MULS
ADD HL,HL
LD A,H
NEG
RET
HMULA AND A
JP M,NEGE1
BIT 7,H
JR Z,ALPOS1
EX AF,AF'
LD A,H
NEG
LD H,A
EX AF,AF'
JR NEGRES1
ALPOS1 CALL MULS
ADD HL,HL
RET
NEGE1 NEG
BIT 7,H
JR Z,NEGRES1
EX AF,AF'
LD A,H
NEG
LD H,A
EX AF,AF'
JR ALPOS1
NEGRES1 CALL MULS
ADD HL,HL
LD A,H
CPL
LD H,A
LD A,L
CPL
LD L,A
INC HL
RET
MULS ;HL=H*A
LD L,0
LD D,L
LD E,A
CWERT DUP 8
ADD HL,HL
JR NC,$+3
ADD HL,DE
EDUP
RET
Вспоминаем IRIS :) Часть 3.5MHz называется :)
http://zxaaa.untergrund.net/DISKI/disk50.zip
Опа на... а мужики то не знают...
Первый раз вижу. Интересно что еще интересного я пропустил.
Единственное что смущает - пирамида с такой же скоростью крутится как и многогранные объекты, если прикинуть что там гдето порядка 30 полигонов и в пирамиде тока четыре.
смешные вы.. тут думаешь, что 256 итераций поворота то мало для красивых эффектов, а вы это чистло до 64 сокращаете..
Единственное что смущает - пирамида с такой же скоростью крутится как и многогранные объекты, если прикинуть что там гдето порядка 30 полигонов и в пирамиде тока четыре.
дык - может там везде 50фпс??? щас смотреть неохота - это же гдето там в середине...
Единственное что смущает - пирамида с такой же скоростью крутится как и многогранные объекты, если прикинуть что там гдето порядка 30 полигонов и в пирамиде тока четыре.
Ничего подобного. Пирамида крутится плавно, все 50фпс давит, а вот более сложные фигуры медленнее. Особенно это заметно на "шаре".
Поворот одной точки по трем осям (оптимизация возможна):
Перспективу как то можно задавать?
Перспективу как то можно задавать?
Нет. Там соптимизирован расчет так, что повернутая "глубина" не вычисляется. А без нее масштаб не получишь.
смешные вы.. тут думаешь, что 256 итераций поворота то мало для красивых эффектов, а вы это чистло до 64 сокращаете..
Как сказал один из великих, все зависит от...
Например построй окружность для коодинатной оси -12..+12 при максимальном радиусе 12, и посчитай скока получается точек на окружности. Их получается 68.
Т.е. в данном случае ограничение 64 вполне гармонично вписывается, если брать 256 то только на каждом 3-4 шаге будет поворот по максимальному радиусу, про внутренние молчим :)
Каждому частному случаю частная реализация :)
Читайте ACN #54, там показано, как надо вертеть.
Evgeny Muchkin
21.05.2009, 16:33
alone, жаль тока, что без пояснялок.
Читайте ACN #54, там показано, как надо вертеть.
Ничего там не показано... исходник там как сказали выше уже, да еще и без комментов и описания принципов работы...
А это разные вещи. Лучше знать идею и писать код, чем смотреть исходник и угадывать идею :)
А так ничего координально нового там нет:)
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot