как заставить закрутиться кубик
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.217.37] |
|
|
правила раздела Алгоритмы

как заставить закрутиться кубик
|
Сообщ.
#1
,
|
|
|
|
Народ вот кусок функции рисующий линию в 3хмерных координатах
void CKubikDlg::draw3dline(int x1,int y1,int z1,int x2,int y2,int z2,int ch) { float kx1,kx2,ky1,ky2; kx1 = x1 + x1 * (z1 * 0.007); ky1 = y1 + y1 * (z1 * 0.007); kx2 = x2 + x2 * (z2 * 0.007); ky2 = y2 + y2 * (z2 * 0.007); line(kx1,ky1,kx2,ky2,ch); } А как заставить его крутиться програмно, причем не по ламерски как в тесте директ 3Д, а по нажатию клавишь? При чем вертеться он должен на трёх осях симетрии(куба)Типа как глобус. Да, чуть не забыл, должен быть эфект фокуса, это когда дальние грани куба меньше передних. |
|
Сообщ.
#2
,
|
|
|
|
Вращай точки куба. Создай матрицу оборота или кватернионы оборота. Для матриц: создай матрицы оборота вокруг всех осей и перемножь (помня, что порядок умножения играет роль).
Что у тебя за ф-ия проекции какая-то странная. Обычно берется x1 = x*C/z, y1 = y*C/z, а константа C высчитывается в зависимости от угла видения и величины окна-экрана. Фокус.. толщину линии сделай зависимой от z.. При нажатии определенной клавиши оборачивай куб на данный угол. |
|
Сообщ.
#3
,
|
|||
|
|
Вопрос достаточно объемный чтобы ответить на него одним постом. Проще работать с векторами. Значит нужен соответствующий класс. Все преобразования с векторами удобно делать в матричной форме --- класс матрицы Классы всех примитивов: отрезок, параллелепипед, и тд. Класс пространства с экранной плоскостью и со свойствами перспективы (проецирования). В общем, тут вариантов может быть много. При таком подходе, повернуть примитив вокруг одной из своих осей достаточно просто. Нужно перемножить матрицу вершин на матрицу вращения. Примерно так
Необходимо правильно математически реализовать вектора, матрицы, перспективу и их свойства. Как вариант смотри ниже |
|
Сообщ.
#4
,
|
|||
|
|
|
|
Сообщ.
#5
,
|
|||
|
|
|
|
Сообщ.
#6
,
|
|||
|
|
|
|
Сообщ.
#7
,
|
|||
|
|
|
|
Сообщ.
#8
,
|
|||
|
|
|
|
Сообщ.
#9
,
|
|||
|
|
|
|
Сообщ.
#10
,
|
|||
|
|
|
|
Сообщ.
#11
,
|
|||
|
|
|
|
Сообщ.
#12
,
|
|||||
|
|
|
|
Сообщ.
#13
,
|
|
|
|
а ещё говорят, что с++ - лаконичный язык!!
да я на паскале 3д екшын написал в ~600 строк, включая мыша и вывод на екран!!! а если только ядро, то ~200 строк http://enzyme.nm.ru/vrash.rar /action.exe выходить буквой q |
|
Сообщ.
#14
,
|
|
|
|
Лаконичный-лаконичный
Если теперь забыть про внутренности етой векторно-матричной библиотеки, то вся программа будет написана в виде vect2 = vect1 * matr3; |
|
Сообщ.
#15
,
|
|
|
|
ну так у меня тоже приблизительно так, правда у меня матрица каждый раз заново считается
только если её считать заранее, наверняка моя программа станет ещё меньше, со всеми внутренностями! |
|
Сообщ.
#16
,
|
|
|
|
2 wormball
что то я не заметил что у тебя меньше кода полностью программа с сорцами (управляется стрелками, +, -, правой кнопкой мыши) |
|
Сообщ.
#17
,
|
|
|
|
утебя 52 килобайта, уменя 14 килобайт
тебя наверное ввели в заблуждение остальные файлы, которые там есь. собственно исходников екшына четыре: action.pas, kol_mov.pas, _13h.pas и mouse.pas . зы. уменя там оказывается есь архив в чистом виде http://enzyme.nm.ru/prog/action.rar ззы. только ето немного более ранняя версия Прикреплённый файл action.rar (35.95 Кбайт, скачиваний: 193)
|
|
Сообщ.
#18
,
|
|
|
|
Блин ну вы даёте...Перемножать матрицы долго, Вот фукция поворота любой точки на плоскости вокруг данной на угол 4 пи/180. Применив такую фукцию к каждой точке куба спроектированой на одну из трёх плоскостей(те про одну из трех координат забываем), он повернётся мать его... Только надо обратить внимание на /*float Abs(float)*/.......
void CKubikDlg::TurnVertex(int cx,int cy, float &x,float &y,int q) { float u,a,b,c; a=cx-x;b=cy-y;c=sqrt(a*a+b*; u = acos(Abs(a) / c) + q*(4*3.14/180) * b / Abs( * a / Abs(a) ; x=cx+c*cos(u)* a / (Abs(a) * (-1)); y=cy+c*sin(u)* b / (Abs( * (-1)); } сорец может дам попозжЕ. |
|
Сообщ.
#19
,
|
|
|
|
прямо скажем, не лучшее решение во избежание смайликов - удалить их к чёртовой бабушке в исходнике. лучше бы выключил галку со смайлами или писал бы всё в [code]
более того, ты ошибаешься, что перемножать матрицы долго. там всего 9 умножений, как и у тебя, а у тебя ещё и синусы с корнями, что куда дольше. |
|
Сообщ.
#20
,
|
|
|
|
vect2 - это типа координаты вершины, а чё такое vect1? matr3-типа матрица поворота, лады. тогда
как она заполняется, если надо повернуть на Альфа градусов по XY, по часовой стрелке? |
|
Сообщ.
#21
,
|
|||||
|
|
Тебе же MeG сорс выложил, там все есть. Осталось только copy-paste
каждую вершину.
з.ы. тут vect1 - исходные координаты, vect2 - конечные координаты (после оборота-перемещения). |
|
Сообщ.
#22
,
|
|||||||||
|
|
Тут произошло разделение понятий. vect2 и vect1 нужно понимать как список вершин гарфического примитива. В моих сорцах вектор --- это направленный отрезок из начала координат в данную точку, а список координат содержится в соответствующем классе примитива. Если тебе нужно вращать параллелепипед:
Дальше нужно поворачивать примитив и отображать его
CParallelepiped содержит в себе массив своих вершин CVector m_Vertex[8]; и ребер int m_Segments[12][12]; // номера начальной и конечной вершин (векторов вершин) Функция Matrix RotateX (double);
это глобальная функция, она не является членом какого-либо класса. Создает матрицу поворота вокруг начала координат. Внутри нее создается объект класса Matrix. Возвращает объект класса Matrix.
В строчке Rmatrix = RotateX(0.5); используется оператрор присваивания по умолчанию, то есть матрица возвращаемая из RotateX() копируется один в один в матрицу Rmatrix. Для чего так сделано? Чтобы иметь однообразную запись для любых афинных преобразований. Rmatrix = RotateX(.) * RotateY(.) * Scale(.) * Translate(.); --- повернуть, повернуть, отмасштабировать, переместить. Таким образом можно получить любые преобразования объекта в пространстве. |
|
Сообщ.
#23
,
|
|
|
|
2 Serg-Zerg
Вокруг чего ты собрался вращать? Вокруг начала координат, вокруг одного из ребер примитива, вокруг геометрического центра примитива, вокруг оси коодинат, вокруг некоторой прямой? |
|
Сообщ.
#24
,
|
|||||||||||||||||
|
|
Афинные преобразования в пространстве в общем виде Про координаты. Чтобы иметь возможность сделать любые преобразования примитива в трехмерном пространстве, необходимо использовать однородные координаты! то есть A(x, y, z, 1) --- четыре кооринаты, четвертая координата имеет геометрический смысл масштаба. Хранить четвертую координату не нужно, достаточно во всех алгоритмах преобразования приводить ее к единице. Соответственно матрицы преобразования тоже размера 4х4 Матрицы в общем виде
Вокруг оси Y на угол A
Вокруг оси Z на угол A
A --- вдоль оси X, B --- вдоль оси Y, C --- вдоль оси Z. A > 0, B > 0, C > 0.
относительно плоскости XY
относительно плоскости YZ
относительно плоскости XZ
a, b, c --- вектор переноса
|
|
Сообщ.
#25
,
|
|
|
|
Проекции
Что это такое? Есть трехмерное пространство, в этом пространстве резмещены трехмерные объекты. Нужно каким-то образом показать эти трехмерные объекты на плоском экране. Для этого и существуют проекции.Видов проекций огромное количество. Преимущественно применяется параллельное и центральное проектирование (у каждого из них есть несколько подвидов) Помещаем в наше пространство плоскость --- экранную плоскость, на нее мы будем проектировать наши трехмерные объекты, и изображение на этой плоскости будем выводить на экан монитора. Дальше нужно задать направление проектирования. Для этого помещаем в пространство камеру. Камера имеет положение в пространстве и направление взгляда (вектор). Для того чтоб на экранной плоскости чтото было видно, необходимо: направить камеру на наши трехмерные объекты, и разместить экранную плоскость между камерой и объектами. Обычно, экранная плоскость перпендикулярна направлению взгляда камеры, это позволяет упростить расчеты. Удобно экранную плоскость разместить в начале координат нашего пространства, на одной из координатных проскостей, например XY. Камеру разместить на оси Z и направить в начало координат O(0, 0, 0). Камера будет описываться двумя векторами: положение Position(0, 0, -100) и направление Direction(0, 0, 1). Все трехмерные объекты размещаем по другую сторону экранной плоскости, для всех точек объектов координата Z будет больше нуля. Проектируем. На входе у нас массив трехмерных координат объектов в пространстве. На выходе массив двухмерных координат на экранной плоскости. Паралельное проектирование (то которое тебе не нравится, нарушается перспектива), тут, по сути, камера не нужна Матрица проектирования на плоскость параллельную координатной плоскости XY | 1 0 0 0 | | 0 1 0 0 | | 0 0 0 0 | | 0 0 k 1 | k --- это смещение экранной плоскости воль оси Z Как это применить? Берем все координаты трехмерных объектов и перемножаем на эту матрицу проектирования, получаем множество точек у которых координата z равна нулю (x, y, 0). Просто выводим эти точки на экран по X и Y, изображение готово. Если матрицу проектирования домножать на матрицу поворота (поворачивать экранную плоскость), можно получить различные виды паралельного проектирования: диметрию, триметрию, изометрию. Еще немного извратившись с этой матрицей проектирования, можно получить свободную и кабинетную параллельные проекции. Центральное (перспективное) проектирование Матрица перспективного проектирования на плоскость XY, (z = 0) Камера находится в точке (0, 0, c) | 1 0 0 0 | | 0 1 0 0 | | 0 0 0 -1/c| | 0 0 0 1 | Матрица перспективного проектирования на плоскость XY, для камеры в любой точке (a, b, c)пространства | 1 0 0 -1/a | | 0 1 0 -1/b | | 0 0 0 -1/c | | 0 0 k 1 | k --- это смещение экранной плоскости воль оси Z Применять матрицы перспективного проектирования так же как и матрицы параллельного проектирования. Для изменения вида проекции остаточно просто сменить одну матрицу на другую. |
|
Сообщ.
#26
,
|
|||
|
|
Мечтал вокруг геометрического центра, но думаю вокруг оси коодинат будет более чем достаточно. |
|
Сообщ.
#27
,
|
|||
|
|
Чтобы повернуть объект вокруг своего геометрического центра нужно: - найти координаты этого геометрического центра - переместить объект в начало координат - повернуть объект на требуемый угол - переместить объект на пержнее место
|
|
Сообщ.
#28
,
|
|||||
|
|
а ещё курсовую по графике писал!! матрица проектирования переводит трёхмерный вектор в двумерный, стало быть она размера 3*2 и выглядит так (для плоскости ху): 1 0 0 0 1 0
враньё! при перспективе используется нелинейное преобразование - там вращают точку матрицей поворота и делят х и у на разность между z и точкой, в которой находится центр камеры, тоесь точкой (0, 0, -с).
|
|
Сообщ.
#29
,
|
|
|
|
Не горячитесь
|
|
Сообщ.
#30
,
|
|
|
|
всёравно перспективу матрицей не опишешь!!
|
|
Сообщ.
#31
,
|
|
|
|
Матрицей чисел.
|
|
Сообщ.
#32
,
|
|||
|
|
ты открой глазки пошире, увидишь исходники еще можешь подумать, и написать уравнение проекции и переложить его на матрицу |
|
Сообщ.
#33
,
|
|||
|
|
исходники то понятное дело работают. просто дело в том что матрицы - ето по определению умножение на некоторые числа, а сдесь идёт деление на z - компоненту входного вектора.
уменя как ты помнишь свои исходники есь, так что сей путь я тоже прошёл |
|
Сообщ.
#34
,
|
|||||
|
|
после умножения вектора на матрицу, результирующий вектор в однородных координатах (a, b, c, d) приводится к виду (a/d, b/d, c/d, 1) (смотри выше), где и происходит деление на z (для данной матрицы) Добавлено в специально для wormball
|
|
Сообщ.
#35
,
|
|
|
|
ну так z у тебя каждый раз разное, так что ты не сможешь как с поворотом сначала вычислить одну матрицу, а потом на неё умножать
|
|
Сообщ.
#36
,
|
|||
|
|
сам прочти что написал в матрице нет z |
|
Сообщ.
#37
,
|
|
|
|
уже прочёл
|
|
Сообщ.
#38
,
|
|
|
|
Усе ж гораздо проще можно показать: вот у нас есть рельсы. Мы стоим между ними, и смотрим туда вдаль, куда они уходят. Как они будут выглядеть на фотографии, и как -- после обработки каждой из их точек линейным оператором?
|
|
Сообщ.
#39
,
|
|
|
|
а чо ж ты тогда так защищаешь матрицы?? помоему с самого начала было ясно, что линейным оператором перспективы не получить
|
|
Сообщ.
#40
,
|
|
|
|
wоrmball прав в том, что при построении матрицы перспективного проецирования с помощью входного вектора пропадает смысл использовать матрицу (исходный смысл был в том, что много преобразований для разных точек можно сложить в одно; матрицу проецирования к этим преобразованиям не зачислишь).
|
|
Сообщ.
#41
,
|
|
|
|
vot!!
зы. только щас понял, что вас было двое, а не один. щас пойду находить отличия во взглядах |
|
Сообщ.
#42
,
|
|
|
|
такето что получается, что у мега каждое умножение сопровождается делением?? так же нефефективно
|
|
Сообщ.
#43
,
|
|||
|
|
Только для тех векторов где четвертая координата отлична от единицы. Смотри исходники, прежде чем коментировать |
|
Сообщ.
#44
,
|
|
|
|
не хочу я ети тонны де**ма раскапывать!! всё равно, что ни говори, ето нелинейный оператор!
|
|
Сообщ.
#45
,
|
|
|
|
не понимаю сыр-бора. никто точку в пространстве вертеть не умеет, что ли? а восемь?
а матрицы эти я бы все на фиг повыкидывал. еще для них класс писать - слишком много чести. там больше все нули в этих матрицах поворота перемножаются и складываются, а времени при типе double тратиться немеренно, так что лучше сразу формулу писать без всякиз еб*чих матриц. |
|
Сообщ.
#46
,
|
|
|
|
Так чтоже получается, мой способ, который был прозван неявным поворотом, оказывается мало того самым простым, так еще и быстрым для конкретной задачи, полчаса програмли+4часа разгрёба глюков=готово...
|
|
Сообщ.
#47
,
|
|
|
|
Быстрее всего и проще взять готовую библиотеку работы с матрицами от интела, опимизированную под MMX, где премножение вектора на матрицу делается за один такт
|
|
Сообщ.
#48
,
|
|||
|
|
Gde etu biblioteku vziat pod VC++ ? |
|
Сообщ.
#49
,
|
|
|
|
|
Сообщ.
#50
,
|
|||
|
|
ну так матрицы нужны, чтобы синусы каждый раз не вычислять, а нули перемножаются только вначале. а с фиксированной точкой ето геморрой |
|
Сообщ.
#51
,
|
|||||
|
|
так, если ты повернул кубик, тебе в любом случае предстоит посчитать синус, хоть ты в матрице, хоть нет. и потом, что ты имел в виду, что с фиксированной точкой геморой? вроде бы в компе с плавающей точкой вычисление производится или я что-то подзабыл-попутал? вроде полигональную модель не представить путево в целых числах? в общем, колись! |
|
Сообщ.
#52
,
|
|
|
|
Считать его не надо. Его надо брать из один раз для фиксированного шага угла рассчитанной sincos-таблицы.
А матрицами или не матрицами, действительно по=, в рассуждении использования SIMD-команд процессора... |
|
Сообщ.
#53
,
|
|||||||
|
|
да, но с матрицами тебе его надо будет один раз посчитать, а потом умножать все точки на одну и ту же матрицу.
помоему если ты щитаешь синусы один раз, а потом тысячу точек вертишь, то ты врядли на синусе много секономишь, к тому же талбица будет много памяти занимать.
я лично етим никогда не занимался, но говорят особо извращённые люди представляют вещественные числа как целые, а потом считают их целочисленной математикой. для етого даже ммх придумали. говорят получается быстрее. |
|
Сообщ.
#54
,
|
|||||||||||
|
|
я про матрицы упомянул в том смысле, что когда ты матрицы множишь, то там много лишних операций выполняется. с моей точки зрения представление преобразований в виде перемножения матриц для компа - это не совсем рационально. зачем использовать матрицы, когда можно преобразования написать, типа
чем писать перемножения матриц, типа V = V*M; так как там делается много лишнего из-за разряженности матрицы. |
|
Сообщ.
#55
,
|
|
|
|
не понял я тебя..... чойто за код ты понаписал??
|
|
Сообщ.
#56
,
|
|||||
|
|
ну, вот как поворачивается точка на плоскости
а при записи того же в матричном представлении, да еще в однородных координатах, как это любят делать, будет куча умножения на ноль, которую не понятно зачем делать. |
|
Сообщ.
#57
,
|
|
|
|
ну так на ноль можно не умножать, если не хочешь, зато у тебя куча синусов. и с помощью матриц можно поворачивать не только в плоскости ху, и можно несколько поворотов представлять как один.
говорят есь ищо кватернионы, с их помощью тоже можно вращать |
|
Сообщ.
#58
,
|
|||
|
|
уже устал с тобой спорить. ты не хочешь понять, что тебе говорю. я сам делал, как ты говоришь и проповедую и это тормозит комп. |
|
Сообщ.
#59
,
|
|
|
|
а мож у тебя процедура неправильная, или ты каждый раз синус вычислял?? а без матриц не тормозит?? покажи процедуру
|
|
Сообщ.
#60
,
|
|||
|
|
Спасибо всем учасникам, лабу здал, вот только МОЯ ф-ия проекции преподу не понравилась как правильно считать эту const C? |
|
Сообщ.
#61
,
|
|||||||||
|
|
вот, что я пытался сказать. я написал вот так:
а если написать вот так:
то при v = M*v; будет происходить вот, что:
что есть не так круто, как первое. не знаю, вообще, как эти матрицы вообще используются здесь, если они столько ресурсов жрут. |
|
Сообщ.
#62
,
|
|
|
|
Матрицы используются 4x4 (кстати, ето Cyrix придумал, а не Intel), и размеры операционных векторов у SIMD-инструкций, как вы уже догадываетесь, тоже 4 эл-та, типа float или fixed 16.16
Итого умножение матрицы 4x4 на вектор 4 занимает 12 векторных операций -- 4 х загрузка, умножение, суммирование елементов. Как правило ето быстрее, чем работа по "оптимизированным" формулам, где поток операндов _меньше_, но _не_регулярен_ и параллельных операций нет... |
|
Сообщ.
#63
,
|
|||||||||
|
|
Например так: C = 360*Resx/(2*PI*angle) angle - угол поля зрения в градусах, Resx - разрешение окна по х, PI = 3.1415926535 Добавлено в
Обычно поворот состоит из 3-х поворотов вокруг 3-х осей. По твоему способу придется каждую точку повернуть 3 раза. Используя матрицу - 1 раз. Если к этому прибавить перемещение, то у тебя будут 4 действия (3 поворота + перемещение); используя матрицу - 1 действие. |
|
Сообщ.
#64
,
|
|||||||||||
|
|
ну, с этой точки зрения, я согласен. наверное, действительно, эффект дает о себе знать, при большом количестве поворотов и все такого. хм, да действительно. спасибо за подсказанную идейку. |
|
Сообщ.
#65
,
|
|||||||
|
|
именно ето я и хотел сказать
а ето я вобще не понял. я в етих с++ных заморочках ничо не понимаю, наверное у тебя тормозит не изза матриц, а именно изза них |