Я уже давно борюсь с этим. Пытаюсь определить экранные координаты вершин в модели на экране своего NDS с помощью devKitPro. Библиотека, кажется, реализует некоторые функции OpenGL, но, в частности, отсутствует функция gluProject, которая (я предполагаю) позволила бы мне сделать именно это, легко.
Я уже давно пытаюсь вычислить координаты экрана вручную, используя матрицы проекции, которые хранятся в регистрах DS, но мне не очень повезло, даже когда я пытался построить матрицу проекции с нуля на основе Документация OpenGL. Вот код, который я пытаюсь использовать:
void get2DPoint(v16 x, v16 y, v16 z, float &result_x, float &result_y)
{
//Wait for the graphics engine to be ready
/*while (*(int*)(0x04000600) & BIT(27))
continue;*/
//Read in the matrix that we're currently transforming with
double currentMatrix[4][4]; int i;
for (i = 0; i < 16; i++)
currentMatrix[0][i] =
(double(((int*)0x04000640)[i]))/(double(1<<12));
//Now this hurts-- take that matrix, and multiply it by the projection matrix, so we obtain
//proper screen coordinates.
double f = 1.0 / tan(70.0/2.0);
double aspect = 256.0/192.0;
double zNear = 0.1;
double zFar = 40.0;
double projectionMatrix[4][4] =
{
{ (f/aspect), 0.0, 0.0, 0.0 },
{ 0.0, f, 0.0, 0.0 },
{ 0.0, 0.0, ((zFar + zNear) / (zNear - zFar)), ((2*zFar*zNear)/(zNear - zFar)) },
{ 0.0, 0.0, -1.0, 0.0 },
};
double finalMatrix[4][4];
//Ugh...
int mx = 0; int my = 0;
for (my = 0; my < 4; my++)
for (mx = 0; mx < 4; mx++)
finalMatrix[mx][my] =
currentMatrix[my][0] * projectionMatrix[0][mx] +
currentMatrix[my][1] * projectionMatrix[1][mx] +
currentMatrix[my][2] * projectionMatrix[2][mx] +
currentMatrix[my][3] * projectionMatrix[3][mx] ;
double dx = ((double)x) / (double(1<<12));
double dy = ((double)y) / (double(1<<12));
double dz = ((double)z) / (double(1<<12));
result_x = dx*finalMatrix[0][0] + dy*finalMatrix[0][1] + dz*finalMatrix[0][2] + finalMatrix[0][3];
result_y = dx*finalMatrix[1][0] + dy*finalMatrix[1][1] + dz*finalMatrix[1][2] + finalMatrix[1][3];
result_x = ((result_x*1.0) + 4.0)*32.0;
result_y = ((result_y*1.0) + 4.0)*32.0;
printf("Result: %f, %f\n", result_x, result_y);
}
Требуется много сдвигов, DS работает внутри, используя нотацию с фиксированной точкой, и мне нужно преобразовать это в удвоение, чтобы работать с ним. То, что я получаю, кажется несколько правильным - пиксели идеально переводятся, если я использую плоский четырехугольник, обращенный к экрану, но вращение шаткое. Кроме того, поскольку я использую проекционную матрицу (которая учитывает ширину/высоту экрана?), последние шаги, которые мне нужно использовать, кажутся совсем неправильными. Разве проекционная матрица не должна делать шаг к разрешению экрана для меня?
Я довольно новичок во всем этом, я неплохо разбираюсь в матричной математике, но я не так хорошо разбираюсь в 3D-графике, как хотел бы. Кто-нибудь здесь знает способ, учитывая трехмерные непреобразованные координаты вершин модели, а также учитывая матрицы, которые будут к ней применяться, фактически получить экранные координаты без использования функции OpenGL gluProject? Вы видите что-то явно очевидное, чего мне не хватает в моем коде? (Я уточню, когда это будет возможно, я знаю, что это грубо, это прототип, над которым я работаю, чистота не является приоритетом)
Огромное спасибо!
PS: Насколько я понимаю, currentMatrix, который я извлекаю из регистров DS, должен давать мне комбинированную матрицу проекции, перевода и вращения, поскольку это должна быть точная матрица, которая будет использоваться. для перевода собственным оборудованием DS, по крайней мере, согласно спецификации на GBATEK. На практике, похоже, на самом деле к нему не применяются координаты проекции, что, я полагаю, как-то связано с моими проблемами. Но я не уверен, так как сам расчет проекции не дает других результатов.