Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 |

 

  Вопрос: Перспектива (трехмерная графика) Добавлено: 02.11.05 18:39  

Автор вопроса:  Victor | Web-сайт: vt-dbnz.narod.ru | ICQ: 345743490 
Я тут начал писать элементарный 3-хмерный движок. Пока он занимается только отображением точек в пространстве.
Вот вроде все написал, но столкнулся с проблемой.

перспектива корявая.

Очень сильная. Когда точки подползают к краю экрана, фигура неестественно вытягивается.

Это поправляемо простым растягиванием (сужением кругозора). Но беда в том, что когда вроде хорошо настроил, то при плавании взникает эффект подзорной трубы.

Подскажите, как правильно настроить перспективу.

Ответить

  Ответы Всего ответов: 23  

Номер ответа: 1
Автор ответа:
 Victor



ICQ: 345743490 

Вопросов: 42
Ответов: 385
 Web-сайт: vt-dbnz.narod.ru
 Профиль | | #1
Добавлено: 02.11.05 21:09
Да. И еще. Как быть с вращением? Вокруг какой точки крутить вид при движении мышью?

Ответить

Номер ответа: 2
Автор ответа:
 vito



Разработчик Offline Client

Вопросов: 23
Ответов: 879
 Web-сайт: softvito.narod2.ru
 Профиль | | #2
Добавлено: 02.11.05 22:05
Ты где програмишь в директе или open GL?

Очень сильная. Когда точки подползают к краю экрана, фигура неестественно вытягивается.

Приведи пример кода, если не секрет.

Ответить

Номер ответа: 3
Автор ответа:
 Victor



ICQ: 345743490 

Вопросов: 42
Ответов: 385
 Web-сайт: vt-dbnz.narod.ru
 Профиль | | #3
Добавлено: 02.11.05 23:27
GDI. И ничего больше.

Кажется, разобрался сам. Взгляни.
http://vt-dbnz.narod.ru/persp.rar
(18kb)

Че-то все равно перспектива подхрамывает, хотя уже не так плохо.

Ответить

Номер ответа: 4
Автор ответа:
 Victor



ICQ: 345743490 

Вопросов: 42
Ответов: 385
 Web-сайт: vt-dbnz.narod.ru
 Профиль | | #4
Добавлено: 02.11.05 23:32
Вот самое интересное.


Type TriVector
    x As Double
    y As Double
    z As Double
End Type

Type ColorPoint
    Pos As TriVector
    Color As RGBQUAD
End Type

Type typLookVectorReserved
    vMoveAhead As TriVector
End Type

Type typLookVector
    Org As TriVector
    ZVector As TriVector
    YVector As TriVector
    XVector As TriVector
    Length As Double
    Reserved As typLookVectorReserved
    MoveAhead As Double
    PixelsPerMeter As Double
End Type

Public Type PointZ
    x As Double
    y As Double
    z As Double
End Type

Public LookVector As typLookVector


Public Function PerspectiveTransform(Vct As TriVector, _
                                     Result As PointZ) As Boolean
Dim VctX As TriVector
Dim VctY As TriVector
Dim VctZ As TriVector
Dim r As TriVector
Dim rz As TriVector
Dim lrz As Double
Dim k As Double
r.x = Vct.x - LookVector.Org.x + LookVector.Reserved.vMoveAhead.x
r.y = Vct.y - LookVector.Org.y + LookVector.Reserved.vMoveAhead.y
r.z = Vct.z - LookVector.Org.z + LookVector.Reserved.vMoveAhead.z
lrz = ProjectVector(r, LookVector.ZVector, rz)
If lrz < 0.001 * LookVector.Length Then
    PerspectiveTransform = False
    Exit Function
Else
    PerspectiveTransform = True
    'resume
End If

Result.z = VectorLength(r)

k = LookVector.Length / lrz

r.x = r.x * k
r.y = r.y * k
r.z = r.z * k

Result.x = ProjectVector(r, LookVector.XVector, rz)
Result.y = ProjectVector(r, LookVector.YVector, rz)
End Function

Public Function ProjectVector(ByRef VectorToProject As TriVector, _
                              ByRef VectorProjectTo As TriVector, _
                              ByRef Result As TriVector) As Double
Dim L As Double
Dim tmpVec As TriVector
Dim t As Double
tmpVec = VectorProjectTo
Normalize tmpVec
t = tmpVec.x * VectorToProject.x + _
    tmpVec.y * VectorToProject.y + _
    tmpVec.z * VectorToProject.z
Result.x = tmpVec.x * t
Result.y = tmpVec.y * t
Result.z = tmpVec.z * t
ProjectVector = t
End Function

Public Sub DrawPixels(ByRef Data() As RGBQUAD, _
                      ByRef Points() As ColorPoint, _
                      Optional ByVal Cls As Boolean)
Dim w As Long, h As Long
Dim i As Long
Dim x As Long, y As Long
Dim cx As Long, cy As Long
Dim pz As PointZ
w = UBound(Data, 1) + 1
h = UBound(Data, 2) + 1
If Cls Then
    ZeroMemory Data(0, 0), w * h * 4
End If
If AryDims(AryPtr(Points)) <> 1 Then
    Exit Sub
End If
cx = w \ 2
cy = h \ 2
For i = 0 To UBound(Points)
    If PerspectiveTransform(Points(i).Pos, pz) Then
        x = cx + pz.x * LookVector.PixelsPerMeter
        y = cy - pz.y * LookVector.PixelsPerMeter
        If x >= 0 And y >= 0 And x < w And y < h Then
            ;Data(x, y) = Points(i).Color
        End If
    End If
Next i
End Sub


Вопрос в том, как правильно рассчитать LookVector.Length.

Ответить

Номер ответа: 5
Автор ответа:
 vito



Разработчик Offline Client

Вопросов: 23
Ответов: 879
 Web-сайт: softvito.narod2.ru
 Профиль | | #5
Добавлено: 03.11.05 00:03
Супер!

Но, извини конечно, нафига столько мучений и изобретений велосипеда?
Есть какие - то веские причины использовать GDI?

Я в подобных случаях работаю с open GL. Никаких проблем с перспективой и скорость значительно выше?

Так на всякий случай, на VB это тоже можно( в смысле open GL) без всяких проблем.

Ответить

Номер ответа: 6
Автор ответа:
 vito



Разработчик Offline Client

Вопросов: 23
Ответов: 879
 Web-сайт: softvito.narod2.ru
 Профиль | | #6
Добавлено: 03.11.05 00:06
Я пока в твой код внимательно не смотрел, но корректно спроецировать 3D сцену на экран (2D) еще та задачка.

Ответить

Номер ответа: 7
Автор ответа:
 Victor



ICQ: 345743490 

Вопросов: 42
Ответов: 385
 Web-сайт: vt-dbnz.narod.ru
 Профиль | | #7
Добавлено: 03.11.05 00:23
Хочешь сказать, что если бы я взял в руки OpenGL, мне бы не пришлось возится с векторами? Как-то мне с трудом верится. Почитать что ли ради интереса этот OpenGL...


Есть какие - то веские причины использовать GDI?
Как ни странно, есть, и очень простая. Я c OpenGL не знаком. Мне показалось, что запрограммировать геометрию будет проще, так как задачка для 3D самая примитивная.

Ответить

Номер ответа: 8
Автор ответа:
 Victor



ICQ: 345743490 

Вопросов: 42
Ответов: 385
 Web-сайт: vt-dbnz.narod.ru
 Профиль | | #8
Добавлено: 03.11.05 00:28
Я пока в твой код внимательно не смотрел, но корректно спроецировать 3D сцену на экран (2D) еще та задачка.

Мне тоже раньше так казалось. А тут вдруг как-то вроде все не так уж сложно... Всего лишь вектора, да вектора. Считаю себе проекции, и все.
Вообще, 3D-графику первый раз программирую. Уж никогда бы не подумал, что возникнут проблемы с формой перспективы, а они возникли. Мало того, они оказались самыми сложными (для меня).

Ответить

Номер ответа: 9
Автор ответа:
 vito



Разработчик Offline Client

Вопросов: 23
Ответов: 879
 Web-сайт: softvito.narod2.ru
 Профиль | | #9
Добавлено: 03.11.05 00:56
Хочешь сказать, что если бы я взял в руки OpenGL, мне бы не пришлось возится с векторами?


Да нет, смотря как возится. Но OpenGL предоставляет мощный математический аппарат для работы в 3D. Если хочешь разобраться с проекциями - посмотри как это сделано в OpenGL.

Если резюмировать - то OpenGL освобаждает от рутины, позволяя концентрироваться на реализации задачи. К примеру ID не считала зазорным использовать эту библиотеку.

Очень неплохие русские доки по ней есть на RSDN.

Ответить

Номер ответа: 10
Автор ответа:
 Страшный Сон



Вопросов: 46
Ответов: 848
 Профиль | | #10 Добавлено: 03.11.05 11:46
У меня тоже есть небольшой пример 3D-движка... по сути, я недавно начал делать спрайтовый 2D-движок, но благодаря Z-буферу он может отображать и 3D. Там в пространстве размещены спрайты-шары, которые притягиваются друг к другу до определенного предела, а потом отталкиваются, стремясь сохранить постоянное расстояние между собой. А искажение перспективы - явление нормальное, оно есть везде, во всех играх.

Ответить

Номер ответа: 11
Автор ответа:
 Pashenko



ICQ: 176176951 

Вопросов: 14
Ответов: 655
 Профиль | | #11 Добавлено: 03.11.05 12:00
Чтобы не было искажения, необходимо учитывать положение глаз пользователя.
Например, мои глаза находятся на расстоянии ~0,5м от экрана, перпендикуляр, опущенный на экран пересекает его (экран) по горизонтали по центру, по вертикали в верхней четверти.
Иными словами, при запуске программы спрашиваешь пользователя о положении еглаз и отрисовываешь проекции на экран для этой точки. Если всё грамотно сделать, никаких искажений не будет.

Ответить

Номер ответа: 12
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #12 Добавлено: 03.11.05 12:29
Вообще-то "глаза пользователя" с точки зрения игры - это плоскость монитора...

Ответить

Номер ответа: 13
Автор ответа:
 Pashenko



ICQ: 176176951 

Вопросов: 14
Ответов: 655
 Профиль | | #13 Добавлено: 03.11.05 12:41
Вообще-то "глаза пользователя" с точки зрения игры - это плоскость монитора...

Вот из-за этого искажения и получаются :-(
А вообще-то, если проекция на плоскость идёт параллельными лучами, то и перспективы никакой не будет.
Перспектива появится только при проецировании сходящимися лучами (в идеальнос случае лучи сходятся в точку, но могут быть и другие варианты).Соответственно, точка пересечения проецирующих лучей должна находиться ПОЗАДИ плоскости, на которую проецируем. Если эта точка находится НА ПЛОСКОСТИ, то, что бы не проецировали, получим только эту точку и больше ничего. Если точка находится ПЕРЕД плоскостью, получим перевёрнутое изображение проецируемых объектов.

Вот так-то...
Обычная геометрия.

Ответить

Номер ответа: 14
Автор ответа:
 Pashenko



ICQ: 176176951 

Вопросов: 14
Ответов: 655
 Профиль | | #14 Добавлено: 03.11.05 12:47
Кстати, в наших с вами глазах плоскость проецирования (сетчатка) находится на задней поверхности глаза, а точка пересечения проецирующих лучей внутри глаза, то есть ПЕРЕД плоскостью. Соответственно, изображение на сетчатке получается перевёрнутым. Ещё раз изображение переворачивает мозг, на основе жизненного опыта (новорождённые, например, так и видят весь мир перевёрнутым вверх ногами).

Ответить

Номер ответа: 15
Автор ответа:
 Victor



ICQ: 345743490 

Вопросов: 42
Ответов: 385
 Web-сайт: vt-dbnz.narod.ru
 Профиль | | #15
Добавлено: 03.11.05 13:44
Вот результаты попыток.
Чтобы не было искажения, необходимо учитывать положение глаз пользователя.
Например, мои глаза находятся на расстоянии ~0,5м от экрана, перпендикуляр, опущенный на экран пересекает его (экран) по горизонтали по центру, по вертикали в верхней четверти.
Иными словами, при запуске программы спрашиваешь пользователя о положении еглаз и отрисовываешь проекции на экран для этой точки. Если всё грамотно сделать, никаких искажений не будет.

Да, я так делал. И вроде как их нет, но эффект подзорной трубы угнетает. Потом я догадался написать туда расстояние глаза-монитор/2, и все стало нормально (по крайней мере перспектива приемлимая и эффект подзорной трубы не слишком силен). Но вот почему именно d/2?

У меня глазами является точка. И вокруг нее производится поворот. Когда у меня был эффект подзорной трубы, я подумал, не сделать ли мне так, чтобы камера вращалась вокруг центральной точки этой плоскости. Но это выглядело уродски по той простой причине, что для этого нужен на экране герой, вокруг которого будет крутиться камера, а у меня его нет (и не будет).
Вообще-то "глаза пользователя" с точки зрения игры - это плоскость монитора...
Как я только что написал, это не работает. Плоскость монитора это стекло, через которое глаза смотрят на мир внутри.

лучи сходятся в точку, но могут быть и другие варианты
А какие еще варианты могут быть?

Кстати, в наших с вами глазах плоскость проецирования (сетчатка) находится на задней поверхности глаза, а точка пересечения проецирующих лучей внутри глаза, то есть ПЕРЕД плоскостью.
Забавно. В глазе нет плоскости, а есть поверхность сферы (почти). А где пересекаются лучи? Когда светло, можно с хорошей точностью утверждать, что в зрачке (в узкой дырочке, через которую они туда и попадают). А вот в темноте я даже затрудняюсь сказать, где. Но где-то в глазу. Вообще, там все преломляется, и не понятно о чем говорить: о реальном ходе лучей или о том, как бы они пошли, если бы не преломлялись.

К примеру ID не считала зазорным использовать эту библиотеку.
Кто такая ID? Крутая фирма чтоли?

ЗЫ. Загнал я туда линии напряженности. Выглядит неплохо. Для вида еще туман сделал. Не хватает только Z-буфера. Но это потом как-нибудь.
ЗЗЫ. Работает медленно. Там 36782 точки, и даже exe немного подтормаживает. А в среде разработки все еще хуже. И это, надо заметить, после ускорения алгоритма - ненужных вычислений там уже почти нет.
Смотрите.
http://vt-dbnz.narod.ru/field.rar
(22kb)
Там строятся линии напряженности поля 1/r. И в программе можно легко поправить на 1/r^2.

Ответить

Страница: 1 | 2 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам