-
Есть проблемка с камерой: Допустим, когда начинаешь вертеть мышкой по/против часовой стрелки, камера, как и положено поворачивается вверх/вниз/влево/вправо, но при этом она ещё начинает переворачивается по/против часовой стрелки? Не подскажите, в чём проблем-ка.
P.S. Или посоветуйте что нужно улучшить.
Код движение камеры мышкой:
...
Xi, Yi : Single; Cursor : TPoint
...
GetCursorPos(Cursor); SetCursorPos(800 div 2, 600 div 2);
Xi := Xi + (Cursor.X - 400)/100 * 0.1; Yi := Yi - (300 - Cursor.Y)/100 * 0.1;
RotateLR(Xi); RotateUD(Yi); Xi := 0; Yi := 0;
...
Код модуля камеры:
SLCamera = packed record CameraType : (FP, FREE);//камера для первого лица/свободная камера
View, Proj : TD3DMatrix;
Xi, Yi : Single;
LR, UD, LK, PS : TD3DXVECTOR3; end;
var D3DDevice : IDirect3DDevice9;
procedure GetViewMatrix; var X, Y, Z : Single; begin with SLCamera do begin D3DXVec3Normalize(LK, LK);
D3DXVec3Cross (UD, LK, LR); D3DXVec3Normalize(UD, UD);
D3DXVec3Cross (LR, UD, LK); D3DXVec3Normalize(LR, LR);
X := -D3DXVec3Dot(LR, PS); Y := -D3DXVec3Dot(UD, PS); Z := -D3DXVec3Dot(LK, PS);
with View do begin m[0, 0] := LR.x; m[0, 1] := UD.x; m[0, 2] := LK.x; m[0, 3] := 0.0;
m[1, 0] := LR.y; m[1, 1] := UD.y; m[1, 2] := LK.y; m[1, 3] := 0.0;
m[2, 0] := LR.z; m[2, 1] := UD.z; m[2, 2] := LK.z; m[2, 3] := 0.0;
m[3, 0] := X; m[3, 1] := Y; m[3, 2] := Z; m[3, 3] := 1.0; end;
D3DDevice.SetTransform(D3DTS_VIEW, View);
D3DXMatrixPerspectiveFovLH(Proj, D3DX_PI / 4, 1.0, 1.0, 1000.0); D3DDevice.SetTransform(D3DTS_PROJECTION, Proj); end; end;
{ движение влево/вправо } procedure MoveLR(Step : Single); begin with SLCamera do case CameraType of FP : PS := D3DXVECTOR3(PS.x + LR.x * Step, 0.0, PS.z + LR.z * Step); FREE : PS := D3DXVECTOR3(PS.x + LR.x * Step, PS.y + LR.y * Step, PS.z + LR.z * Step); end;
GetViewMatrix; end;
{ движение вверх/вниз } procedure MoveUD(Step : Single); begin with SLCamera do If CameraType = FREE then begin PS.x := PS.x + UD.x * Step; PS.y := PS.y + UD.y * Step; PS.z := PS.z + UD.z * Step; end;
GetViewMatrix; end;
{ движение вперёд/назад } procedure MoveFB(Step : Single); begin with SLCamera do case CameraType of FP : PS := D3DXVECTOR3(PS.x + LK.x * Step, 0.0, PS.z + LK.z * Step); FREE : begin PS.x := PS.x + LK.x * Step; PS.y := PS.y + LK.y * Step; PS.z := PS.z + LK.z * Step; end; end;
GetViewMatrix; end;
{ поаорот влево/вправо } procedure RotateLR(Step : Single); var Mat : TD3DXMatrix; begin with SLCamera do begin case CameraType of FP : D3DXMatrixRotationY (Mat, Step); FREE : D3DXMatrixRotationAxis(Mat, UD, Step); end;
D3DXVec3TransformCoord(LR, LR, Mat); D3DXVec3TransformCoord(LK, LK, Mat); end;
GetViewMatrix; end;
{ поворот вверх/вниз } procedure RotateUD(Step : Single); var Mat : TD3DXMatrix; begin with SLCamera do begin D3DXMatrixRotationAxis(Mat, LR, Step);
D3DXVec3TransformCoord( UD, UD, Mat); D3DXVec3TransformCoord( LK, LK, Mat); end;
GetViewMatrix; end;
{ поворот по/против часовой стрелки } procedure RotateUC(Step : Single); var Mat : TD3DXMatrix; begin with SLEngine.SLCamera do If CameraType = FREE then begin D3DXMatrixRotationAxis(Mat, LK, Step);
D3DXVec3TransformCoord( LR, LR, Mat); D3DXVec3TransformCoord( UD, UD, Mat); end;
GetViewMatrix; end;
end.
-
В примерах к DX SDK не вращается - видимо из-за того, что вращение там делается через кватернионы. В DX8 это класс D3DUtil.CD3DArcBall. В принципе, само по себе вращение не порок, оно присутствует в некоторых коммерческих CAD, например. Даже логично - крутим мышкой вокруг объекта -> поворачиваем объект относительно перпендикулярной экрану оси.
-
Понятно! Последний вопрос: Как сделать поворот камеры вокруг какого-либо объекта, например дома, как это сделано, допустим, в Sims'ах? P.S. Использование нмжеприведённого кода не предлагать: RotateLR( 0.02); MoveLR (-0.02); если ошибаюсь, то RotateLR(-0.02); MoveLR ( 0.02);
-
Обычно формируют матрицу вращения относительно 0-й точки, потом умножают её на матрицу перемещения в точку, относительно которой нужно крутить. Правда, в моём тесте для достижения нужного результата пришлось перемещать в обратном направлении. То ли у меня что-то напутано, то ли действительно так и есть.
-
Можешь написать исходный текст?
-
Я так понял, что в [0] как раз и есть вращение камеры вокруг объекта (толком не вникал), а проблема в том, чтобы сделать вращение относительно произвольной точки. Если нет... можно заранее подготовить видовую матрицу, направленную в 0 (тем же GetViewMatrix) и потом умножать её на матрицу вращения, полученную D3DXMatrixRotationAxis. Матрица перемещения - D3DXMatrixTranslation. Потом ещё раз D3DXMatrixMultiply, потом SetTransform(D3DTS_VIEW, ...).
-
Спасибо, по-экспериментируем))
-
Чё т не выходит! Так можешь написать исходник процедуры, которая ворочает камеру вокруг точки, плиз!
-
...
-
Нет у меня конкретной процедуры, нужно выдирать куски из разных мест, а это долго. Умножаешь матрицы в правильном порядке? Т.е. порядок передачи параметров в функцию имеет значение. И чем всё-таки CD3DArcBall не угодил? Хотя в примерах SDK он в основном применяется к матрице модели, фактически можно применять и к видовой. Рекомендация глобального характера - см. ветку про текстуры, качай книги по ссылкам, читай.
-
Я понял, что надо так (хотя и не работает):
LK : TD3DXVECTOR3; procedure Axis(Step : Single); var Mat : TD3DXMatrix; begin D3DXMatrixRotationAxis(Mat, LK, Step); D3DXMatrixTranslation (Mat, Step, 0.0, 0.0); D3DXMatrixMultiply (Mat, Mat, Mat); Device.SetTransform ( D3DTS_VIEW, Mat); end; Или нет?
-
Лучше, наверное, будет этот код (и он тож не работает): procedure Axis(Step : Single); var matTrans, matRot, matWorld : TD3DXMatrix; begin D3DXMatrixTranslation(matTrans, 0.0, 0.0, 10.0); D3DXMatrixRotationYawPitchRoll(matRot, D3DXToRadian(Step), 0.0, 0.0);
matWorld.m[0, 0] := matRot.m[0, 0] * matTrans.m[0, 0]; matWorld.m[0, 1] := matRot.m[0, 1] * matTrans.m[0, 1]; matWorld.m[0, 2] := matRot.m[0, 2] * matTrans.m[0, 2]; matWorld.m[0, 3] := matRot.m[0, 3] * matTrans.m[0, 3];
matWorld.m[1, 0] := matRot.m[1, 0] * matTrans.m[1, 0]; matWorld.m[1, 1] := matRot.m[1, 1] * matTrans.m[1, 1]; matWorld.m[1, 2] := matRot.m[1, 2] * matTrans.m[1, 2]; matWorld.m[1, 3] := matRot.m[1, 3] * matTrans.m[1, 3];
matWorld.m[2, 0] := matRot.m[2, 0] * matTrans.m[2, 0]; matWorld.m[2, 1] := matRot.m[2, 1] * matTrans.m[2, 1]; matWorld.m[2, 2] := matRot.m[2, 2] * matTrans.m[2, 2]; matWorld.m[2, 3] := matRot.m[2, 3] * matTrans.m[2, 3];
matWorld.m[3, 0] := matRot.m[3, 0] * matTrans.m[3, 0]; matWorld.m[3, 1] := matRot.m[3, 1] * matTrans.m[3, 1]; matWorld.m[3, 2] := matRot.m[3, 2] * matTrans.m[3, 2]; matWorld.m[3, 3] := matRot.m[3, 3] * matTrans.m[3, 3];
Device.SetTransform(D3DTS_WORLD, matWorld); end; end;
Пробовал изменять Device.SetTransform(D3DTS_WORLD, matWorld) на Device.SetTransform(D3DTS_VIEW, matWorld) => Объекты вообще исчезают(((
-
А, всё!!! Въехал наконец-то)))
|