Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Игры";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];

Вниз

Клик!   Найти похожие ветки 

 
Bryke   (2004-12-05 16:30) [0]

Как в играх типа "Warcraft" определяется координата на 3D-ландшафте, куда кликнул геймер?
Мож кто знает...


 
TButton ©   (2004-12-05 17:30) [1]

элементарно.
ибо курсор есть объект, который мняет свое положение на карте игры в соответсвии с перемещением мыши.

даже если это не так, это как-то можно сделать, ибо, натыкался на исходники програмули, которая рисовала пирамидку, реагируя на наведение мыши на опр. полигон.


 
DeadMeat ©   (2004-12-05 18:29) [2]

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

---
...Death Is Only The Begining...


 
dimodim-modern   (2004-12-05 22:35) [3]

Screentoworld акак начет screentovector = объясни


 
wiz ©   (2004-12-06 07:32) [4]

задача абсолютно аналогична проверке "попадает ли выбранный полигон (или тайл) в Frustum камеры"... только в данном случае нужно frustum строить не по всему экрану, а только вокруг курсора.

Это не самый оптимальный вариант, зато наверняка сработает :)

---
бритва Оккама: "Не создавайте сущности сверх необходимого"


 
Bryke   (2004-12-06 12:40) [5]


> Вообще это зависит, от того, на чем ты пишешь... D3D или
> OGL...

Пишу на D3D (чистом)


 
Bryke   (2004-12-06 12:46) [6]

wiz,
Подробнее можно?
Или скинь на мыло.


 
П7   (2004-12-06 15:41) [7]

На http://GameDev.ru есть пара статей на эту тему. Далее принцыпы можно подчерпнуть из исходников к конкурсу по DrkBASIC"у. Был там у них такой конкурс, мол определить координаты в 3D"пространстве, искать через рамблер. В книге "OpenGL в проектах Delphi" расказывается пара способов этого фокуса. Ну и... РАМБЛЕР твой друг! (:


 
wiz ©   (2004-12-07 06:52) [8]

2 Bryke: "Яndex - найдётся всё"... проверил - первые 5-10 ссылок на запрос "frustum" - твои :)

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

PS: ну это всё конечно я говорю для _нерегулярной_ сетки, такой, как в warcraft 3 и подобных... если сетка регулярная (например карта высот), то использование описанных выше способов (конечно) будет, в некотором роде, идиотизмом - можно сделать всё проще и быстрее. Как? Впитайте в свои вены "Аналитическую геометрию" - и ответ придёт сам собой :)


 
Sapersky   (2004-12-07 11:15) [9]

Если "чистый D3D" подразумевает использование D3DX, то сначала D3DXUnproject, потом raycast-функции - D3DXBoxBoundProbe (D3DXSphereBoundProbe), D3DXIntersect (D3DXIntersectSubset) или D3DXIntersectTri. Если нужны исходники подобных ф-ий - они есть, например, в GLScene (VectorGeometry.pas).

если сетка регулярная (например карта высот), [...] можно сделать всё проще и быстрее

Вот, например - спроецировать луч на плоскость карты, определить ячейки сетки, в которые он попадает (нарисовать "растровую линию" на карте высот, алгоритмом Брезенхема или ещё как) и проверять последовательно (от начала луча) эту "линию".


 
Bryke   (2004-12-07 15:13) [10]


> Если "чистый D3D" подразумевает использование D3DX, то

Я не использую d3dx, использую dxgutils.
Существуют ли еще способы?


 
Sapersky   (2004-12-07 18:09) [11]

UnProject можно и вручную расписать:

// InvViewMat - инвертированная видовая матрица - инвертирование в DXGUtils должно быть
// HalfViewSize - половина размера окна вывода
procedure VectorUnProject(Const Src : TVector; Const InvViewMat : TMatrix;
                                       Const ProjMat : TMatrix; Const HalfViewSize : TPoint;
                                       Var Dir, Offset : TVector);
Var v : TVector;
begin
v.x :=  ( ( Src.x / HalfViewSize.x ) - 1) / ProjMat._11;
v.y := -( ( Src.y / HalfViewSize.y ) - 1) / ProjMat._22;
v.z := 1.0;

With InvViewMat do begin
 Dir.x  := v.x * _11 + v.y * _21 + v.z * _31;
 Dir.y  := v.x * _12 + v.y * _22 + v.z * _32;
 Dir.z  := v.x * _13 + v.y * _23 + v.z * _33;
 Offset := Vector(_41, _42, _43);
end;
end;

Offset, Dir - начальная точка и направление луча, в кот. преобразуются коорд. мыши.
Спроецировать луч на плоскость (напр. XY) можно так:

StartAtPlane.x:=Offset.x; StartAtPlane.y:=Offset.y; StartAtPlane.z:=0; // ну это сугубо для ясности :)
EndAtPlane:=VectorAdd(Offset, VectorMulS(Dir, - Offset.z / Dir.z) );

Проверка пересечения луча с треугольником, сферой, произвольной плоскостью - см., повторяю, исходники GLScene (OGL, D3D - в данном случае неважно, это чистая геометрия) или вот:

http://www.geometryalgorithms.com/algorithm_archive.htm


 
MsShtaer   (2004-12-07 21:38) [12]

Ребята в шейдерах есть команда MRT (Multi Render Target). Когда воспроизводите сцену, воспроизводите коды полигонов на вторую таргет. А потом просто проверьте цвет пикселей. Быстро и просто.


 
Bryke   (2004-12-08 22:29) [13]


> Быстро и просто.

А еще ресурсоемко.:)


 
Bryke   (2004-12-08 22:48) [14]

Sapersky,
спасибо буду разбираться.


 
cyborg ©   (2004-12-09 09:52) [15]


> [12] MsShtaer   (07.12.04 21:38)

Интересно, разжуй пожалуйста ;)


 
Sapersky   (2004-12-09 13:52) [16]

Насколько я понял, это то же самое, что и старый "добрый" метод, который ещё у Краснова был. Только там всё рендерилось безо всяких MRT - в два прохода, сначала для проверки (разными цветами), потом собственно вывод.
Да, возможно, с MRT будет несколько быстрее, поскольку рисуется всё 1 раз, хотя и не верится, что вывод на вторую таргет - совсем уж "бесплатно" (особенно для владельцев карт без шейдеров - цена будет в $$$ :)). А при 2-проходном выводе можно на первом проходе рисовать упрощённую геометрию.
Но в любом случае рендер таргет придётся лочить, чтобы проверить значение пикселя. Со всеми вытекающими.


 
Bryke   (2004-12-09 15:27) [17]

Sapersky,
Все отлично работает, координаты находятся.
Блин, я не ожидал такого эффекта.
В общем спасибо.


 
cyborg ©   (2004-12-09 18:22) [18]


> Но в любом случае рендер таргет придётся лочить, чтобы проверить
> значение пикселя. Со всеми вытекающими.

Не обязательно же весь экран лочить, можно одну конкретную точку ;)


 
MsShtaer   (2004-12-09 22:32) [19]

>Не обязательно же весь экран лочить, можно одну конкретную точку ;)
Согласен.
И вот что вам скажу. Рендер таргет приводит к замедлению процента на 3. Насчёт подробнее. У фирмы ATI есть бесплатная софтина RenderMonkey(У NVIDIA - Cg) эта софтина создаёт .fx файлы их можно подключать к делфи с помощью ID3DEffect9 (у GL незнаю, но как-то можно). Ещё подробнее не могу, т.к. только описание Обезьянки занимает 290 страниц.


 
Sapersky   (2004-12-10 13:43) [20]

Не обязательно же весь экран лочить, можно одну конкретную точку ;)

Э-э... ну да :)
Совсем меня запугали мелкософт и прочие авторитетные товарищи со своим "руками не трогать" (не блокировать видеопамять) и "против течения не плыть" (не читать из видеопамяти). Так что рефлекс срабатывает - "Lock = ПЛОХО", независимо от обстоятельств :)
На самом деле, должны быть ещё некие накладные расходы на саму блокировку. Вряд ли большие, впрочем - в DX7, насколько помню, время обработки было практически пропорционально объёму обработанных данных (при этом даже указываемый LockRect особой роли не играл). В DX8-9 надо бы протестировать...
Но всё равно не нравится мне этот метод :) Или два раза рисовать, или шейдеры нужны. Опять же, геометрические методы универсальнее - raycast-функциями можно проверять на попадание не только мышь, но и другие объекты, которые можно представить лучом.



Страницы: 1 вся ветка

Форум: "Игры";
Текущий архив: 2005.03.13;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.047 c
14-1109096969
Breakmaster
2005-02-22 21:29
2005.03.13
Хостинг для форума


3-1107984829
Нонейм
2005-02-10 00:33
2005.03.13
Разрядность numeric


1-1109516816
Igor_thief
2005-02-27 18:06
2005.03.13
Выделение ячейки в ValueListEditor


1-1109425932
Checist [root]
2005-02-26 16:52
2005.03.13
Создание новой формы


4-1106922134
JaDS
2005-01-28 17:22
2005.03.13
деректива message





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский