forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   C++ (http://forum.boolean.name/forumdisplay.php?f=22)
-   -   передвижение с помощью матриц (http://forum.boolean.name/showthread.php?t=15333)

HolyDel 24.08.2011 14:00

Ответ: передвижение с помощью матриц
 
хранить трансформацию объекта в матрице - имхо неправильно. ИМХО, матриц нужна лишь для родительских отношений и чтобы скормить ее ГАПИ. А так - vec3 позиция, vec3 scale и кватернион на ориентацию. Если что то менялось пересчитываем локальную матрицу и матрицы всех потомков.

Mind 26.08.2011 19:21

Ответ: передвижение с помощью матриц
 
Как я понял матрицы нужны для конечного результата, а двигать объекты надо через вектора...
Объясните простой пример:
1)загружаю модель шара("shar.x")
2)создаю матрици мира,вида,проэкции.
3)теперь чтобы передвинуть шар нужно каждую вершину передвинуть на общее/определенное значение. ДА?
Так вот:

Код:


....
....

D3DXLoadMeshFromX(L"shar.x",D3DXMESH_SYSTEMMEM,d3d_device,NULL,&pMeshBuffer,NULL,&dwNumber,&pMesh);

  D3DXMATRIX matWorld;
  D3DXMATRIX matView;
  D3DXMATRIX matProj;

  matWorld._11 = 1; matWorld._12 = 0; matWorld._13 = 0; matWorld._14 = 0;
  matWorld._21 = 0; matWorld._22 = 1; matWorld._23 = 0; matWorld._24 = 0;
  matWorld._31 = 0; matWorld._32 = 0; matWorld._33 = 1; matWorld._34 = 0;
  matWorld._41 = 0; matWorld._42 = 0; matWorld._43 = -10; matWorld._44 = 1;
  d3d-device->SetTransform(D3DTS_WORLD,&matWorld);


 matView._11 = 1; matView._12 = 0; matView._13 = 0; matView._14 = 0;
 matView._21 = 0; matView._22 = 1; matView._23 = 0; matView._24 = 0;
 matView._31 = 0; matView._32 = 0; matView._33 = 1; matView._34 = 0;
 matView._41 = 0; matView._42 = 0; matView._43 = 0;matView._44 = 1;
 d3d-device->SetTransform(D3DTS_VIEW,&matView);


  matProj._11 = 1; matProj._12 = 0; matProj._13 = 0; matProj._14 = 0;
  matProj._21 = 0; matProj._22 = 1; matProj._23 = 0; matProj._24 = 0;
  matProj._31 = 0; matProj._32 = 0; matProj._33 = 1000/999; matProj._34 = 1;
  matProj._41 = 0; matProj._42 = 0; matProj._43 = -1000/999; matProj._44 = 0;

  d3d-device->SetTransform(D3DTS_PROJECTION,&matProj);

while(1)
{

....
....

d3d-device->BeginScene();


        for(DWORD i=0;i<dwNumber;i++)
        {
        pMesh->DrawSubset(0);
        }
//Что сдесь написать чтобы передвинуть точку/точки в пространстве (Локальном)???

dev->EndScene();
dev->Present(NULL,NULL,NULL,NULL);
....
....

return 0;
}

Как можно обратьться к любой вершине загруженного объекта??

alcoSHoLiK 26.08.2011 20:05

Ответ: передвижение с помощью матриц
 
Вершины двигать не нужно. Важно понимать, что происходит во время рендера. Каждая вершина, которая поступает на графический конвеер, умножается на матрицу World, View и Projection. В итоге получаются экранные координаты вершины.

Чтобы переместить объект в мире тебе надо изменить матрицу World перед рендером этого объекта. Чтобы перемещать независимо несколько объектов, надо сохранять матрицу World до трансформации и восстанавливать после.

Для примера, продемонстрирую процесс в OpenGL коде. В OpenGL вместо отдельных матриц World и View используется одна modelview матрица. Сути это не меняет, т.к. эта матрица является произведением world на view.
Код:

// все функции трансформации работают с текущей матрицей

glPushMatrix(); // сохраним матрицу на стеке

// Переместим и отмасштабируем modelview матрицу
glTranslatef(1, -1, 10);
glScalef(2, 3, 1);

// Отрисуем объект
glDrawArrays(...);

// Восстановим modelview матрицу
glPopMatrix();

Таким образом, идеологически, ты трансформируешь систему координат перед рендером объекта, и наблюдателю кажется, что объект перестился. На самом деле, объект остается на месте в локальной системе координат, а переместился наблюдатель.

Аналогичным образом можно независимо двигать, вращать и масштабировать несколько объектов, надо просто каждого из них обернуть в вызовы push/pop:
Код:

for (int i = 0; i < OBJECT_COUNT; ++i) {
    glPushMatrix();

    // трансформируем что надо и рисуем объект

    glPopMatrix();
}

Все трансформации координат относительны.

Mind 26.08.2011 21:23

Ответ: передвижение с помощью матриц
 
alcoSHoLiK Спасибо большое без тебя бы долго разбирался :)

Mind 26.08.2011 22:35

Ответ: передвижение с помощью матриц
 
Появился еще вопрос:
Как мне сделать сдиг тела а потом поворот в локальных координатах?
Делаю вот так:
Код:

  RotateEntity(matWorldRY,mx);
  MoveEntity(matWorldPos,UP1,0,UP2);
  D3DXMatrixMultiply(&matWorld,&matWorldPos,&matWorldRY);
  SetTransform(WORLD,matWorld);
        pMesh->DrawSubset(0);

когда позиция = 0 то тело крутится как бы вокруг своей оси, а когда передвигаеться дальше тополучаеться что тело это child каой-то оси, т.е оно движеться не вокруг своей оси а вокруг другой как ребёнок вокруг парента? Что надо написать чтобы тело крутилось вокруг себя?

Функция поворота такая:

Код:

void RotateEntity(D3DXMATRIX& m,double angle)
{
 
  m._11 = cos(angle);  m._12 = 0;          m._13 = -sin(angle);  m._14 = 0;
  m._21 = 0;  m._22 = 1;  m._23 = 0;  m._24 = 0;
  m._31 = sin(angle);  m._32 = 0;  m._33 = cos(angle);  m._34 = 0;
  m._41 = 0;  m._42 = 0;          m._43 = 0;  m._44 = 1;

}

а передвижения:

Код:

void MoveEntity(D3DXMATRIX& m,float dx,float dy,float dz)
{
 

  m._11 = 1;  m._12 = 0;          m._13 = 0;  m._14 = 0;
  m._21 = 0;  m._22 = 1;    m._23 = 0;  m._24 = 0;
  m._31 = 0;  m._32 = 0;    m._33 = 1;  m._34 = 0;
  m._41 += dx;  m._42 += dy;          m._43 +=-dz;  m._44 = 1;

}


alcoSHoLiK 27.08.2011 00:47

Ответ: передвижение с помощью матриц
 
Попробуй поменять местами функции MoveEntity и RotateEntity. Должно получиться

Код:

  MoveEntity(matWorldPos,UP1,0,UP2);
  RotateEntity(matWorldRY,mx);
  D3DXMatrixMultiply(&matWorld,&matWorldPos,&matWorldRY);
  SetTransform(WORLD,matWorld);
        pMesh->DrawSubset(0);

Правка:
Пардон, не внимательно глянул. Вызовы MoveEntity и RotateEntity пусть остаются как есть, а вот в вызове D3DXMatrixMultiply надо поменять местами matWorldPos и matWorldRY.

---

Наблюдаемый тобой эффект (поворот объект вокруг другой оси после перемещения) можно объяснить таким образом. Матрица поворота в действительности всегда поворачивает вокруг начала координат. Если объект находится в начале координат, то будет казаться, что он поворачивается вокруг своей оси. На самом деле он поворачивается вокруг оси, которая проходит через начало координат, это сразу становится заметным при смещении объекта.

Как же повернуть объект вокруг своей оси? В общем случае это делается за три шага:
1) построить вектор из начала координат в центр объекта и переместить объект вдоль этого вектора так, чтобы его центр оказался в начале координат
2) повернуть объект (или систему координат -- все относительно)
3) вернуть объект на прежнее место, переместив его вдоль построенного ранее вектора в обратную сторону

В твоем частном случае должно быть достаточно поменять местами порядок умножения матрицы смещения и матрицы поворота, чтобы достичь желаемого эффекта.

Mind 27.08.2011 11:18

Ответ: передвижение с помощью матриц
 
Хм... пулучилось. А раньше чето пробывал и не получалось(правда там все почти было по другму написано).Спасибо.
Цитата:

Как же повернуть объект вокруг своей оси? В общем случае это делается за три шага:
1) построить вектор из начала координат в центр объекта и переместить объект вдоль этого вектора так, чтобы его центр оказался в начале координат
2) повернуть объект (или систему координат -- все относительно)
3) вернуть объект на прежнее место, переместив его вдоль построенного ранее вектора в обратную сторону
А это я так понял ты написал для самостаятельно построеной матрицы чтобы повернуть объект.ДА?
т.к у меня все получилось благодаря этому:
Цитата:

В твоем частном случае должно быть достаточно поменять местами порядок умножения матрицы смещения и матрицы поворота, чтобы достичь желаемого эффекта.

alcoSHoLiK 27.08.2011 18:21

Ответ: передвижение с помощью матриц
 
Цитата:

Сообщение от Mind (Сообщение 200258)
А это я так понял ты написал для самостаятельно построеной матрицы чтобы повернуть объект.ДА?

Это я описал общий случай. Если после проделанных для объекта трансформаций ты захочешь его снова повернуть вокруг своей оси где-нибудь дальше в коде (например, при выполнении какого-то условия), тебе придется проделать три шага вместо двух, т.к. объект уже не находится в начале координат после первого перемещения.


Часовой пояс GMT +4, время: 10:23.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot