Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Софтварная прорисовка полигона

406
14 июня 2005 года
vitaly2003s
481 / / 27.07.2004
Вобщем вопрос такой:
Кто знает каким образом можно прорисовать полигон имеющий 3 вершины находящийся в 3-х мерном пространстве на плоскость и соответсвенно все точки которые принадлежат данному полигону. Т.е. трансформировать 3-х мерные координаты полигона на 2-х мерную плоскость без использования различных библиотек типа DX,OpenGL и т.д. Т.е. с помощью каких математических преобразований возможно это осуществить? Или хотябы куда копать?
443
14 июня 2005 года
REmindER
292 / / 23.03.2003
Смотря что понимать под всеми точками, принадлежащими к данному полигону. Если речь идет о просто закрашенной поверхности, то это обыкновенная прорисовка треугольника на плоскости. Трансформировать просто: берешь координаты по каким-либо двум из трех осей. Вот тебе и есть проекция. Если хош типа 3д удаление, то умножаешь каждое из двух взятых осевых значений на значение удаления вершины от плоскости просмотра (т.е. по z) деленное на некий видовой портал (или как оно там называется). Вот с его величиной можно поиграться. Неплохо выглядит при 20-25. А вообще на этом сайте есть хорошая подборка статеек.
406
15 июня 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by REmindER
Смотря что понимать под всеми точками, принадлежащими к данному полигону. Если речь идет о просто закрашенной поверхности, то это обыкновенная прорисовка треугольника на плоскости. Трансформировать просто: берешь координаты по каким-либо двум из трех осей. Вот тебе и есть проекция. Если хош типа 3д удаление, то умножаешь каждое из двух взятых осевых значений на значение удаления вершины от плоскости просмотра (т.е. по z) деленное на некий видовой портал (или как оно там называется). Вот с его величиной можно поиграться. Неплохо выглядит при 20-25. А вообще на этом сайте есть хорошая подборка статеек.



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

11K
15 июня 2005 года
N1k1tung
5 / / 20.05.2005
Вообще для этого я могу тебе посоветовать различную литературу по 3D графике - там иногда при описании функций подробно описываются все действия, кот. эта ф-ция производит. Но вот с текстурой будут явные проблемы: лично я нигде не встречал каких-либо описаний по их фильтрации и накладыванию
406
16 июня 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by N1k1tung
Вообще для этого я могу тебе посоветовать различную литературу по 3D графике - там иногда при описании функций подробно описываются все действия, кот. эта ф-ция производит. Но вот с текстурой будут явные проблемы: лично я нигде не встречал каких-либо описаний по их фильтрации и накладыванию



Да так то я сделал 3-д преобразование по матрице но получаются большие искажения при нахождение объекта от центра чем дальше тем больше,вот примерный код с расчетами на c:

struct MATRIX
{
float m11 ;
float m12 ;
float m13 ;
float m14 ;
float m21 ;
float m22 ;
float m23 ;
float m24 ;
float m31 ;
float m32 ;
float m33 ;
float m34 ;
float m41 ;
float m42 ;
float m43 ;
float m44 ;
};

struct TFCoord
{
float x;
float y;
float z;
};

//hwnd - окно куда прорисовать преобразованую точку
//np - координата точки которую будем расчитывать
//Rotmat - глобальная матрица с нужным углом поворота
void DrawPoligone(HWND hwnd_to,TFCoord np,MATRIX Rotmat)
{
RECT rc;
GetClientRect(hwnd_to,&rc);
int screen_height=rc.bottom;
int screen_widht=rc.right;

float x = np.x ;// - (float)pdc->my/2;
float y = np.y ;//- (float)pdc->mx/2;
float z= np.z;

float x3d = x * Rotmat.m11 + y * Rotmat.m21 + z * Rotmat.m31;
float y3d = x * Rotmat.m12 + y * Rotmat.m22 + z * Rotmat.m32;
float z3d = x * Rotmat.m13 + y * Rotmat.m23 + z * Rotmat.m33;
float kf2 = ((1 - (z3d + (screen_widht/2)) / screen_height) * 0.7 + 0.4);
int x4=x3d * kf2 + (screen_widht/2);//координата точки x на 2-d плоскости
int y4=y3d * kf2 + (screen_height/2);//координата точки y на 2-d плоскости

//теперь по координатам x4 и y4 можно прорисовать точку с нужным цаетом в 2-х мерной плоскости,но с данным алгоритмом чем дальше объект от центра тем больше искажения

SetPixel(GetDC(hwnd_to),x4,y4,RGB(10,50,20));
}

443
16 июня 2005 года
REmindER
292 / / 23.03.2003
Так и есть, т.к. ты используешь плоское проецирование, взяв расстояние до точки по z.

k=n/|zP|

x4 = screencentralX + (xP - currentX - screencentralX) * k;
y4 = screencentralY + (xP - currentY - screencentralY) * k;

Получается, что при удалении от центра видового порта объекты, находящиеся на одинаковом удалении по z, сохраняют свои пропорции, тогда как по идее расстояние до точек каждого объекта увеличивается.

Можно попробовать так:

k=n/sqrt((xP - currentX - screencentralX)^2 + (yP - currentY - screencentralY)^2 + (zP - currentZ)^2)

Сферическое - имитирует проекцию изображения на сетчатку глаза. Но опять же возникнут искажения при повороте изображения. Лучше использовать первый метод, подобрав n так, чтобы искажения были не слишком заметны. Неплохо действует золотое сечение.
391
17 июня 2005 года
Archie
562 / / 03.02.2005
Проще всего задать положение камеры P(x, y, z) и три орта cx, cy, cz - cx, cy - задают плоскость экрана, cz - вектор направления, т.е. куда смотрит камера.
Теперь берем любую точку пространства A(x, y, z) и считаем проекции вектора PA на вектора cx, cy, cz путем скалярного произведения. Получаем проекции Ax, Ay, Az. Теперь считаем координаты точки на экране как: X = Ax / Az, Y = Height - Ay / Az;
Длина вектора cz может задавать фокус камеры, точнее угол обзора (длинее cz - больше угол обзора).
Теперь проецируем три точки треугольника на экран - получаем плоский треугольник. Для текстурирования нужно еще апроксимировать текстурные координаты (u, v) на плоскости - есть куча алгоритмов с разной степенью апроксимации и качеством / скоростью рендеринга.
406
17 июня 2005 года
vitaly2003s
481 / / 27.07.2004
Цитата:
Originally posted by Archie
Проще всего задать положение камеры P(x, y, z) и три орта cx, cy, cz - cx, cy - задают плоскость экрана, cz - вектор направления, т.е. куда смотрит камера.
Теперь берем любую точку пространства A(x, y, z) и считаем проекции вектора PA на вектора cx, cy, cz путем скалярного произведения. Получаем проекции Ax, Ay, Az. Теперь считаем координаты точки на экране как: X = Ax / Az, Y = Height - Ay / Az;
Длина вектора cz может задавать фокус камеры, точнее угол обзора (длинее cz - больше угол обзора).
Теперь проецируем три точки треугольника на экран - получаем плоский треугольник. Для текстурирования нужно еще апроксимировать текстурные координаты (u, v) на плоскости - есть куча алгоритмов с разной степенью апроксимации и качеством / скоростью рендеринга.



Очень интересно.А можно поподробнее здесь,хотя бы написать небольшой примерчик на си как это работает? Или хотябы сайтик где про это можно почитать? (просто че то непонятно какими типами являются cx,cy,cz, какими значениями они инициализируются, и как посчитать проекции Ax,Ay,Az)

8.2K
17 июня 2005 года
Akela
64 / / 13.05.2005
Господа, всё можно сделать не прибегая к подбору каких-либо значений. Для этого нужны:
1. Матрица трансформации (ModelViewMatrix[4][4]):
mv[0][0] mv[0][1] mv[0][2] mv[0][3]
mv[1][0] mv[1][1] mv[1][2] mv[1][3]
mv[2][0] mv[2][1] mv[2][2] mv[2][3]
mv[3][0] mv[3][1] mv[3][2] mv[3][3]

Подмарица:
mv[0][0] mv[0][1] mv[0][2]
mv[1][0] mv[1][1] mv[1][2]
mv[2][0] mv[2][1] mv[2][2]
хранит информацию о поворотах камеры вокруг каждой из осей координат,
столбец:
mv[0][3]
mv[1][3]
mv[2][3]
содержит сдвиги по всем осям,
mv[3][3] осуществляет общее изменение масштаба. Более подробно о других элементах матрицы и о том, как её изменять при вращении и движении камеры можно прочесть в литературе.

Пример 1.
При сдвиге камеры на dx, dy, dz единиц нужно сделать следующее:
mv[0][3] += dx;
mv[1][3] += dy;
mv[2][3] += dz;

Пример 2.
Вращение на угол Angle вокруг оси Х модифицирует матрицу следующим образом:

float XMatrix[4][4];
//отчистить XMatrix нулями
XMatrix[0][0] = 1.0;
XMatrix[1][1] = cos(Angle);
XMatrix[1][2] = -sin(Angle);
XMatrix[2][1] = sin(Angle);
XMatrix[2][2] = cos(Angle);
XMatrix[0][0] = 1.0;

ModelViewMatrix = XMatrix * ModelViewMatrix;

2. Матрица проекции (ProjectionMatrix[4][4]).
Матрица ортогональной проекции:
ProjectionMatrix[ 0] = 2.0 / (right - left);
ProjectionMatrix[ 1] = 0.0;
ProjectionMatrix[ 2] = 0.0;
ProjectionMatrix[ 3] = - (right + left) / (right - left);
ProjectionMatrix[ 4] = 0.0;
ProjectionMatrix[ 5] = 2.0 / (top - bottom);
ProjectionMatrix[ 6] = 0.0;
ProjectionMatrix[ 7] = - (top + bottom) / (top - bottom);
ProjectionMatrix[ 8] = 0.0;
ProjectionMatrix[ 9] = 0.0;
ProjectionMatrix[10] = - 2.0 / (zfar - znear);
ProjectionMatrix[11] = - (zfar + znear) / (zfar - znear);
ProjectionMatrix[12] = 0.0;
ProjectionMatrix[13] = 0.0;
ProjectionMatrix[14] = 0.0;
ProjectionMatrix[15] = 1;

Матрица перспективной проекции:
ProjectionMatrix[ 0] = 2.0 * znear / (right - left);
ProjectionMatrix[ 1] = 0.0;
ProjectionMatrix[ 2] = (right + left) / (right - left);
ProjectionMatrix[ 3] = 0.0;
ProjectionMatrix[ 4] = 0.0;
ProjectionMatrix[ 5] = 2 * znear / (top - bottom);
ProjectionMatrix[ 6] = (top + bottom) / (top - bottom);
ProjectionMatrix[ 7] = 0.0;
ProjectionMatrix[ 8] = 0.0;
ProjectionMatrix[ 9] = 0.0;
ProjectionMatrix[10] = - (zfar + znear) / (zfar - znear);
ProjectionMatrix[11] = - (2 * zfar * znear) / (zfar - znear);
ProjectionMatrix[12] = 0.0;
ProjectionMatrix[13] = 0.0;
ProjectionMatrix[14] = - 1;
ProjectionMatrix[15] = 0.0;

left, right, top, bottom - координата левой, правой, верхней, нижней плоскостей отсечения.
znezr, zfar - расстояния до ближней и дальней плоскости отсечения.

А далее последовательность действий такая:
1. Загрузит в ModelViewMatrix единичную матрицу.
2. Осуществить требуемые перемещения камеры (они модифицмруют матрицу трансформации).
3. Создать по приведенным выше формулам матрицу проекции.
4. Для каждой вершины полигона рассчитать новые координаты:

(vertex0'.x, vertex0'.y, vertex0'.z, vertex0'.w) = ModelViewMatrix * (vertex0.x, vertex0.y, vertex0.z, 1.0);
(vertex0'.x, vertex0'.y, vertex0'.z, vertex0'.w) = ProjectionMatrix * (vertex0'.x, vertex0'.y, vertex0'.z, vertex0'.w);

vertex0'.x = vertex0'.x / vertex0'.w;
vertex0'.y = vertex0'.y / vertex0'.w;
vertex0'.z = vertex0'.z / vertex0'.w;

Если не предполагается реализовывать отсечение невидимых граней vertex0'.z после этого можно отбросить.

vertex0'.x = WindowWidth / 2 - vertex0'.x * WindowWidth / 2;
vertex0'.y = WindowHeight / 2 - vertex0'.y * WindowHeight / 2;

vertex0'.x, vertex0'.y теперь оконные координаты вершины. Что и требовалось получить. Заметьте, никакого шаманства с парамерами.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог