ПрограммированиеФорумГрафика

Тряска объектов. (4 стр)

Страницы: 1 2 3 4 5 6 7 Следующая »
#45
8:16, 28 июня 2011

-Eugene-
> Кхм... А ты знаешь, что такое мировая матрица? С точки зрения математики?
С точки зрения математики я знаю что это таблица Сколько-нибудьxСколько-нибудь с цифрами. В Direct3D 4x4 первые 3x3 определяют поворот а остальные 7 цифр непонятно что.

#46
8:43, 28 июня 2011

kroonk
Лучше бы ты реально изучил матричную математику. Мировая матрица - матрица перевода из локальной системы координат в глобальную. Т.е. матрица вообще описывает систему координат.

#47
11:26, 28 июня 2011

kroonk
Почитай как представляется float, мантисса (дробная часть <1) умножить на степень (экспонента), поэтому можно представить огромные значения (10^38), но точность относительная, гдето 4-5 десятичных знаков, поэтому напр.
1e6+1=1e6 - идет потеря точности, мелкие слагаемые "глотает"
Видеокарты все работают с float, даже когда координаты double передаешь, они внутри конвертятся, это не решение
Я вижу ты пишешь симулятор космоса
Выход один - считать самому кординаты в double ОТНОСИТЕЛЬНО камеры (вычитать ее позицию), матрицу поворота оставь для DirectX. Для расстояния до самых дальних объектов (звезд) не хватит и точности double, надо хранить в двух числах, скажем 1 double - координаты звезды в больших единицах (вроде световых годов), 2й double - приращение внутри системы, для самой звезды и планет. При наблюдении из др. системы достаточно первого числа, находясь внутри системы - используешь 2е.
При отрисовке кадра рисуешь сначала звезды либо на "небесной сфере", т.е. все на равном (пофиг чему) расстоянии, без z-buffer, либо если учитываешь перекрытия - используй 1ю звездную координату
Потом обнуляешь z-byffer и рисуешь уже объекты внутри системы где ты находишься
Вот, примерно так
Если будут вопросы - пиши

P.S. Глянь мою тему Случайный Космос

#48
11:53, 28 июня 2011

kroonk
Видовая матрица (в OpenGL, в DirectX может отличаться транспонированием)

| 2*near/(right-left)          0                    A        0 |
|        0            2*near/(top-bottom)      B        0 |
|        0                    0                            C        D |
|        0                    0                            -1      0 |

A=(right+left)/(right-left)
B=(top+bottom)/(top-bottom)
C=-(far+near)/(far-near)
D=-2*far*near/(far-near)

При far -> бесконечности
C=-1
D=-2*near

Такую матрицу и передавай
Учитывай, что на расстояниях много больше znear Z-byffer неправильно работает в силу недостаточной точности float, вообще дальние объекты надо отрисовывать с отдельной матрицей проекции (большИм z-near) и отдельным z-buffer, либо же сортировать вручную по расстоянию
Для сфер различного радиуса я вывел что надо сортировать по d^2-r^2, где d-расстояние до центра, r-радиус, что дает длину касательной и корректное перекрытие сфер во всех случаях

#49
14:07, 28 июня 2011

kroonk
> С точки зрения математики я знаю что это таблица Сколько-нибудьxСколько-нибудь
> с цифрами. В Direct3D 4x4 первые 3x3 определяют поворот а остальные 7 цифр
> непонятно что.
Четвёртая строка матрицы (или столбец, не знаю как в DX) содержит сдвиг (т.е. координаты). Т.е. матрица 3*3 описывает поворот и масштабирование (диагональные элементы умножены на фактор масштаба), а ещё одна строка задаёт сдвиг.

Aslan
> Видеокарты все работают с float, даже когда координаты double передаешь, они
> внутри конвертятся, это не решение
Непарвда, считать в double - это решение. Не нужно пользоваться DX-овскими функциями матричной математики, если они все работают в float (не знаю, если лы там double версии). Все вычисления проводи в double - повороты, сдвиги, масштабирование, умножение матриц, в т.ч. и на матрицу проекции. А потом перед самым использованием матрицы переводи её в float и передавай в DX. В OpenGL например есть функция glLoadMatrixd, она принимает double матрицу и сама уже переводит в float и загружает её.

Реализацю С.К. можешь сделать как описал Aslan. Самое главное - процесс переключения С.К. У меня сделано так. Звёзды и галактики задаются в глобальной С.К., где единица 1 парсек. Функция рендера звёзд помещает в отдельный массив звёзды, находящиеся достаточно близко к камере, чтобы их планетные системы нужно было рендерить с планетами, остальные звёзды рисуются просто точками. Потом в этом массиве ищется ближайшая звезда, и С.К. переключается на неё. Т.е. всё что находится в системе этой звезды, рисуется с центром в звезде (ну или барицентре системы, если звезда двойная-тройная), единица расстояния - километр (хотя можно и парсек оставить, это не принципиально, просто так дебажить удобнее). Самое главное, что и движения камеры обрабатываются тоже в этой С.К. Т.е. класс камеры имеет две координаты - double UniversalPos для описания положения камеры в певрой системе и double LocalStarPos для описания положения относительно центра текущей планетной системы. Координаты обновляются приращением, и оно прибавляется одновременно к обоим величинам:

void   UpdatePos(double Shift)
{
    UniversalPos += Shift;
    LocalStarPos += Shift;
}

Просто вторая оказывается точнее, потому что там расстояния не превышают 1 парсека и точности double хватает до метровых расстояний, а в первой (глобальной) системе расстояния могут быть миллиарды парсек, и точности хватает толко до сотых парсека, чего достаточно для звёзд, но недостаточно для планет. При подлёте к новой планетной системе происходит переключение координат:

void  SetLocalStar(double starUniversalPos, ObjectID starID)
{
  if (localStarID == starID) return;
  LocalStarPos = UniversalPos - starUniversalPos;
}

starID - это внутренний id объекта (звезды), проверка делается для того, чтобы переключение происходило только при подлёте к другой звезде (когда та станет ближайшей). Само переключение - это просто вычитание мировых координат камеры ("парсековой" точности) и мировых координат звезды (тоже "парсековой" точности). Дальше все движения вычисляются точно во второй (локальной) С.К., и рендер планет тоже происходит в ней.

Можно ввести ещё несколько аналогичных уровней С.К. - галактический для более точного задания звёзд в галактиках (пока я обхожусь без него) и планетарный - для точного задания мелких объектов на планетах типа деревьев, строений, кораблей. Тебе скорее всего придётся сделать этот ещё один уровень и привязать его к центру корабля. Т.е. расширить немного:

void   UpdatePos(double Shift)
{
    UniversalPos += Shift;
    LocalStarPos += Shift;
    LocalShipPos += Shift;
}

void   SetLocalStar(double starUniversalPos, ObjectID starID)
{
   if (localStarID == starID) return;
   LocalStarPos = UniversalPos - starUniversalPos;
}

void   SetLocalShip(double shipSystemlPos, ShipID shipID)
{
   if (localShipID == ShipID) return;
   LocalShipPos = LocalStarPos - shipSystemlPos;
}

При этом "локальная корабельная" С.К. цепляется за предыдущую - локльную планетную, для большей точночти.

#50
14:13, 28 июня 2011

Ну я понял уже как отдельные системы координат сделать там к примеру надо сделать сначала одну глобальную матрицу и локальную потом глобальную на локальную умножить и всё. И кстати только сейчас попробовал сделать эксперимент посадил камеру на место корабля и камера не трясётся причём не зависимо что я использую float или double а вот если туда корабль посадить то он трясётся. Я передвигаю корабль матрицей то-есть в ней дело.

#51
15:03, 28 июня 2011

kroonk
Ну да, надо пересчитывать все координаты, вычитая позицию камеры, для вращения оставь MODELVIEW MATRIX
> потом глобальную на локальную умножить
Как раз нет, смысл чтоб разнести их друг от друга. Т.е.  звездное небо ты рисуешь координатами UniversalPos, заданными в парсеках (т.е. соизмеримой с ним величиной), LocalStarPos тут можно смело выкинуть, и Frustum ставишь с соответствующим znear (до ближайшей звезды, кроме той которая в непосредств. близости, ее рисуешь как Солнце (планету) )
Планеты внутри системы, где пребываешь рисуешь по LocalStarPos с др. Frustum, выбираешь соотв-й znear
Можно еще один Frustum для мелких объектов (др. кораблей итд)
Каждый раз обнуляешь z-buffer, т.к. в него пишутся разные величины

#52
15:09, 28 июня 2011

Что-то я вообще запутался что такое znear и frustum и как обнулить z-buffer и как тогда правильно реализовать несколько систем координат? Можно рабочий пример приложения с кодом?

#53
15:30, 28 июня 2011

kroonk
Frustum - это область обзора, пирамида, определяемая параметрами твоей камеры, размерами экрана и znear, zfar - ближ. и дальнее расстояния отсечения, может они в DX подругому называются, незнаю
Так вот, допустим расстояния внутри звездной системы несоизмеримы с межзвездными, поэтому далекие звезды и ближние планеты рисуешь в разных системах координат, соотв-о меняешь Frustum и znear, я тебе выше написал формулу для ModelView Matrix без zfar, ей пользуйся.
znear необходимо выбирать в зависимости от того, сколь дальние объекты ты рисуешь, см. выше
Кроме znear там параметры left, right и top, bottom, их ставишь так:

float w=znear*tan(fov); // fov-половина угла обзора по горизонтали (в радианах)
left=-w;
right=w;
float h=w*aspect; // aspect - отношение высота/ширина экрана
top=h;
bottom=-h;

> как обнулить z-buffer
одним вызовом соотв-й функции, читай Help к DX

#54
15:38, 28 июня 2011

А как же менять эти системы координат?

#55
15:39, 28 июня 2011

Aslan
> left, right и top, bottom
Разве это есть в ДХ?

#56
15:51, 28 июня 2011

-Eugene-
я без понятия как в DX, пишу в OpenGL, трудно адаптировать?
P.S. Проще задать через znear, zfar и аспект, если есть такая готовая функция

#57
15:56, 28 июня 2011

kroonk
device->setTransform(...)

#58
16:13, 28 июня 2011

-Eugene-
> device->setTransform(...)
это устанавливает матрицу а как сделать матрицу системы координат и как её трансформировать к примеру что-бы трансформировать мир

 
D3DXMATRIX Matrix;
D3DXMatrixTranslation(&Matrix, x, y, z);
Device->SetTransform(D3DTS_WORLD, &Matrix);

а что писать вместо D3DXMatrixTranslation и D3DTS_WORLD в случае с матрицей системы координат(если такая вообще есть)?

#59
16:16, 28 июня 2011

kroonk
> в случае с матрицей системы координат(если такая вообще есть)?
Ты не понимаешь... ЛЮБАЯ матрица служит для перехода между системами координат.
Но я не могу сейчас сказать, какими именно функциями тебе нужно трансформировать мир... Надо думать.

Страницы: 1 2 3 4 5 6 7 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.