HLFX.Ru Forum
профиль •  правила •  регистрация •  календарь •  народ •  FAQ •  поиск •  новое •  сутки •  главная •  выход  
HLFX.Ru Forum HLFX.Ru Forum > Теория и практика > Half-Life SDK > R_MarkLeaves
Из quake 1
Страницы (2): [1] 2 »   Предыдущая тема   Следующая тема
Автор
Тема Новая тема    Ответить
n00b
Житель форума

Дата регистрации: Nov 2010
Проживает: (void)
Сообщений: 128

Рейтинг



Half-Life R_MarkLeaves

В исходниках quake 1 есть функция:

C++ Source Code:
1
void R_MarkLeaves (void)
2
{
3
  byte	*vis;
4
  mnode_t	*node;
5
  int		i;
6
 
7
  if (r_oldviewleaf == r_viewleaf)
8
    return;
9
 
10
  r_visframecount++;
11
  r_oldviewleaf = r_viewleaf;
12
 
13
  vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
14
 
15
  for (i=0 ; i<cl.worldmodel->numleafs ; i++)
16
  {
17
    if (vis[i>>3] & (1<<(i&7)))
18
    {
19
      node = (mnode_t *)&cl.worldmodel->leafs[i+1];
20
      do
21
      {
22
        if (node->visframe == r_visframecount)
23
          break;
24
        node->visframe = r_visframecount;
25
        node = node->parent;
26
      } while (node);
27
    }
28
  }
29
}


Эта функция определяет какие части карты видны и их надо нарисовать? Или я что-то путаю ??
Подскажите пожалуйста

Сообщить модератору | IP: Записан
Сообщение: 74532

Старое сообщение 18-03-2011 11:53
- За что?
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 35062
Нанёс повреждений: 514 ед.
Возраст: 39

Рейтинг



Награды
 
[1 награда]


Цитата:
n00b писал:
Эта функция определяет какие части карты видны и их надо нарисовать?

Да.

__________________

Сообщить модератору | IP: Записан
Сообщение: 74533

Старое сообщение 18-03-2011 12:14
-
n00b
Житель форума

Дата регистрации: Nov 2010
Проживает: (void)
Сообщений: 128

Рейтинг



Цитата:
XaeroX писал:
Да.


А можете обьяснить - каким образом? а именно:
До цикла мне всё понятно, а что делает это условие ?
C++ Source Code:
if (vis[i>>3] & (1<<(i&7)))


Дальше непонятно почему node приравнивается листу:
C++ Source Code:
node = (mnode_t *)&cl.worldmodel->leafs[i+1];


И что за кадры ( visframe ) там используются и для чего они нужны.
Надеюсь на вашу помошь.

Сообщить модератору | IP: Записан
Сообщение: 74534

Старое сообщение 18-03-2011 13:08
- За что?
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 35062
Нанёс повреждений: 514 ед.
Возраст: 39

Рейтинг



Награды
 
[1 награда]


Гугли статьи, читай комментарии в исходниках.
Я сомневаюсь, что кто-то тут всё бросит и начнёт читать лекцию об устройстве BSP в 3д-играх. Хотя кто знает?

__________________

Сообщить модератору | IP: Записан
Сообщение: 74535

Старое сообщение 18-03-2011 13:16
-
n00b
Житель форума

Дата регистрации: Nov 2010
Проживает: (void)
Сообщений: 128

Рейтинг



Ну блин, я бы не отказался)
Пойду сам разберусь.
Оно мне в принципе и не надо, но для общего развития пригодилось бы.
Тогда вопрос:
Движок то старый, разчитан на медленные видяхи, есть ли смысл проверять невидимые участки карты - сама проверка не займет ли больше времени чем рисование ??

Сообщить модератору | IP: Записан
Сообщение: 74536

Старое сообщение 18-03-2011 13:23
- За что?
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 35062
Нанёс повреждений: 514 ед.
Возраст: 39

Рейтинг



Награды
 
[1 награда]


Цитата:
n00b писал:
сама проверка не займет ли больше времени чем рисование ??

Смотря какая проверка и смотря что рисовать. Если рендер уровня кваки - то по-моему разницы никакой, в любом случае будет фпс, упёртый в потолок. Если же куча всяких "тяжёлых" эффектов... Ну тут надо учесть, что большинство нубских говнодвижков вроде моей волатилы являются CPU-bound на уровне драйвера, и нагрузка на CPU очень большая. Помогает многопоточный SMP-рендерер - расчеты видимости делает один процессор, а в это время второй процессор засылает данные в драйвер.

__________________

Сообщить модератору | IP: Записан
Сообщение: 74537

Старое сообщение 18-03-2011 13:28
-
 Дядя Миша
racing for fish

Дата регистрации: Oct 2005
Проживает: Кубань
Сообщений: 33064
Нанёс повреждений: 392 ед.

Рейтинг



Цитата:
n00b писал:
До цикла мне всё понятно, а что делает это условие ?
C++ Source Code:
if (vis[i>>3] & (1<<(i&7)))

виз в целях экономии места хранится побитно. каждый бит определяет видимость того или иного визблока из другого визблока. Соответственно еденичка - виден, ноль - нет. мега-условие, это собственно доступ к нужному биту.
Цитата:
n00b писал:
Дальше непонятно почему node приравнивается листу:
C++ Source Code:
node = (mnode_t *)&cl.worldmodel->leafs[i+1];

это сделано для удобства. В первой и второй кваке, ноды и листья линкуются в общую цепь и имеют сходные структуры примерно до середины. Там есть комментарии, что вот эта часть расшарена между ноадами и лифами. а эта - уникальна для лифов или нодов.
Таким образом мы бегаем по лифам, пока не наткнемся на ноду или наоборот. А чтобы заведомо отличить лиф от ноды, мы делаем либо plane == NULL (так сделано в даркплейсе), либо contents == 0 (как в оригинальной кваке).
Цитата:
n00b писал:
И что за кадры ( visframe ) там используются и для чего они нужны.

это чтобы не бегать по лифам каждый кадр, а только при смене визблока.
А визблок меняется, ориентировочно каждые 100 юнитов (точно не помню). Таким образом мы сохраняем указатель на старый лиф в r_oldviewleaf и проверяем его с новым лифом (который получается из vieworigin игрока) если лифы совпадают (т.е. игрок находится по прежнему в том же самом лифе), то визфрейм не инкрементится и остается старым. Если же лиф сменился, мы просто помечаем видимые ноды новым значением (а все остальные ноды остаются либо вообще не помеченные, либо помеченные устаревшим значением visframecount) и далее есть проверка на визфрейм, где мы просто отсекаем невидимые ноды и листья.
Цитата:
XaeroX писал:
Я сомневаюсь, что кто-то тут всё бросит и начнёт читать лекцию об устройстве BSP в 3д-играх

Йолки-палки! На форуме появился человек, которому действительно интересное в чём-то разобраться, а не украсть рендер паранои, а ты его отпугиваешь.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'

Сообщить модератору | IP: Записан
Сообщение: 74539

Старое сообщение 18-03-2011 14:00
-
 XaeroX
Crystice Softworks

Дата регистрации: Oct 2005
Проживает: Торонто
Сообщений: 35062
Нанёс повреждений: 514 ед.
Возраст: 39

Рейтинг



Награды
 
[1 награда]


Цитата:
Дядя Миша писал:
Таким образом мы бегаем по лифам, пока не наткнемся на ноду или наоборот

Наоборот. Ноды - узлы бсп-дерева, лифы - конечные точки.

__________________

Сообщить модератору | IP: Записан
Сообщение: 74540

Старое сообщение 18-03-2011 14:07
-
n00b
Житель форума

Дата регистрации: Nov 2010
Проживает: (void)
Сообщений: 128

Рейтинг



Огромное спасибо!
Побежал мучить свою программу

Сообщить модератору | IP: Записан
Сообщение: 74541

Старое сообщение 18-03-2011 14:16
- За что?
 Дядя Миша
racing for fish

Дата регистрации: Oct 2005
Проживает: Кубань
Сообщений: 33064
Нанёс повреждений: 392 ед.

Рейтинг



Цитата:
XaeroX писал:
Наоборот. Ноды - узлы бсп-дерева, лифы - конечные точки.

та я вот не помню. Где-то у меня был код, который перебирал именно лифы в поисках ноды. Ну да пофиг.

Добавлено 18-03-2011 в 17:51:

А хотя нет, вру. Это я у лифа сурфейсы перебирал, что-то в голову запало.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'

Сообщить модератору | IP: Записан
Сообщение: 74544

Старое сообщение 18-03-2011 14:51
-
n00b
Житель форума

Дата регистрации: Nov 2010
Проживает: (void)
Сообщений: 128

Рейтинг



Я тут решил разбить все плоскости карты на треугольники.
Треугольники делаю по рёбрам фейса, точки плоскости беру методом из quake 1: ( рисует фейсы по крайней мере правильно )

C++ Source Code:
1
numverts = 0;
2
for (i=0 ; i<fa->numedges ; i++)
3
{
4
  lindex = loadmodel->surfedges[fa->firstedge + i];
5
 
6
  if (lindex > 0)
7
    vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position;
8
  else
9
    vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position;
10
  VectorCopy (vec, verts[numverts]);
11
  numverts++;
12
}

И разбиваю на треугольники с точками:
точка1, точкаN, точкаN + 1;

Разбивание происходит, но не всегда верно. Вот например пятиугольник, разбивается совсем не на 3 триугольника как надо бы. По рисунку видно, что линии соединяются с точками других плоскостей, получается что даже на 1 прямой фейса может быть несколько ребер и их надо склеивать, или всё же неверен алгоритм разбивания ?

[ Вложение ]
razb.jpg

Сообщить модератору | IP: Записан
Сообщение: 74572

Старое сообщение 19-03-2011 15:58
- За что?
 Дядя Миша
racing for fish

Дата регистрации: Oct 2005
Проживает: Кубань
Сообщений: 33064
Нанёс повреждений: 392 ед.

Рейтинг



Цитата:
n00b писал:
Я тут решил разбить все плоскости карты на треугольники.

ну MarkLeaves тут совершенно не нужен. То есть вообще.
Кроме того, для разбиения на треугольники крайне желательно генерить индексы для вертексов. Потому что по сути, сами вертексы трогать не следует.
Ну вот простенький код для разбиения полигона на треугольники.
Простенький - потому что не учитывает такие интересные вещи, как например subdivided surface - т.е. воду, лаву и прочие жидкости.
C++ Source Code:
1
/*
2
=================
3
Mod_BuildPolygon
4
=================
5
*/
6
static void Mod_BuildPolygon( msurface_t *surf, int numVerts, const float *verts )
7
{
8
  float		s, t;
9
  uint		index, bufSize;
10
  mtexinfo_t	*texinfo = surf->texinfo;
11
  int		i, numElems;
12
  byte		*buffer;
13
  vec3_t		normal;
14
  mesh_t		*mesh;
15
 
16
  // allocate mesh
17
  numElems = (numVerts - 2) * 3;
18
 
19
  // mesh + ( align vertex, align normal, (st + lmst) + elem * numElems) * numVerts;
20
  bufSize = sizeof( mesh_t ) + numVerts * ( sizeof( vec4_t ) + sizeof( vec4_t ) + sizeof( vec4_t )) + numElems * sizeof( elem_t );
21
 
22
  buffer = Mod_Malloc( loadmodel, bufSize );
23
 
24
  mesh = (mesh_t *)buffer;
25
  buffer += sizeof( mesh_t );
26
  mesh->numVerts = numVerts;
27
  mesh->numElems = numElems;
28
 
29
  // setup pointers
30
  mesh->vertexArray = (vec4_t *)buffer;
31
  buffer += numVerts * sizeof( vec4_t );
32
  mesh->normalsArray = (vec4_t *)buffer;
33
  buffer += numVerts * sizeof( vec4_t );
34
  mesh->stCoordArray = (vec2_t *)buffer;
35
  buffer += numVerts * sizeof( vec2_t );
36
  mesh->lmCoordArray = (vec2_t *)buffer;
37
  buffer += numVerts * sizeof( vec2_t );
38
  mesh->elems = (elem_t *)buffer;
39
  buffer += numElems * sizeof( elem_t );
40
 
41
  mesh->next = surf->mesh;
42
  surf->mesh = mesh;
43
 
44
  // create indices
45
  for( i = 0, index = 2; i < mesh->numElems; i += 3, index++ )
46
  {
47
    mesh->elems[i+0] = 0;
48
    mesh->elems[i+1] = index - 1;
49
    mesh->elems[i+2] = index;
50
  }
51
 
52
  // setup normal
53
  if( surf->flags & SURF_PLANEBACK )
54
    VectorNegate( surf->plane->normal, normal );
55
  else VectorCopy( surf->plane->normal, normal );
56
 
57
  VectorNormalize( normal );
58
 
59
  // create vertices
60
  mesh->numVerts = numVerts;
61
 
62
  for( i = 0; i < numVerts; i++, verts += 3 )
63
  {
64
    // vertex
65
    VectorCopy( verts, mesh->vertexArray[ i ] );
66
    VectorCopy( normal, mesh->normalsArray[ i ] );
67
 
68
    mesh->vertexArray[ i ][3] = 1.0f;
69
    mesh->normalsArray[ i ][3] = 1.0f;
70
 
71
    // texture coordinates
72
    s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3];
73
    if( texinfo->width != -1 ) s /= texinfo->width;
74
    else s /= surf->shader->stages[0].textures[0]->width;
75
 
76
    t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3];
77
    if( texinfo->height != -1 ) t /= texinfo->height;
78
    else t /= surf->shader->stages[0].textures[0]->height;
79
 
80
    mesh->stCoordArray[ i ][0] = s;
81
    mesh->stCoordArray[ i ][1] = t;
82
 
83
    // lightmap texture coordinates
84
    s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3] - surf->textureMins[0];
85
    s += surf->lmS * LM_SAMPLE_SIZE;
86
    s += LM_SAMPLE_SIZE >> 1;
87
    s /= LIGHTMAP_TEXTURE_WIDTH * LM_SAMPLE_SIZE;
88
 
89
    t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3] - surf->textureMins[1];
90
    t += surf->lmT * LM_SAMPLE_SIZE;
91
    t += LM_SAMPLE_SIZE >> 1;
92
    t /= LIGHTMAP_TEXTURE_HEIGHT * LM_SAMPLE_SIZE;
93
 
94
    mesh->lmCoordArray[ i ][0] = s;
95
    mesh->lmCoordArray[ i ][1] = t;
96
  }
97
}

Этот же код в чуть более другой вариации можно встретить в различных проектах на тему Q2 и Q3: Quake2 Evolved, QFusion, EGL и прочих.
Конкретно этот код - взят из раннего ксаша (конец 2010 года).

Добавлено 19-03-2011 в 20:12:

Структурка mesh_t выглядит вот так, если интересно
C++ Source Code:
1
typedef struct mesh_s
2
{
3
  int		numVerts;
4
  int		numElems;
5
 
6
  vec4_t		*vertexArray;
7
  vec4_t		*normalsArray;
8
  vec2_t		*stCoordArray;
9
  vec2_t		*lmCoordArray;
10
  rgba_t		*colorsArray;
11
  elem_t		*elems;
12
 
13
  struct mesh_s	*next;		// temporary chain of subdivided surfaces
14
} mesh_t;

а elem_t - обычный unsigned int.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'

Сообщить модератору | IP: Записан
Сообщение: 74576

Старое сообщение 19-03-2011 17:12
-
n00b
Житель форума

Дата регистрации: Nov 2010
Проживает: (void)
Сообщений: 128

Рейтинг



Цитата:
Структурка mesh_t выглядит вот так, если интересно

Конечно интересно
Все сделал, работает не плохо.
Перевел всё на вершинные буфера - на карте de_dust2 3000+ fps за место 280 через glBegin\glEnd.

Добавлено 20-03-2011 в 11:22:

И сразу вопрос по VBO:
Можно ли без опасений использовать вершинные буфера, или все-таки ещё есть видеоустройства, которые их не поддерживают? ( например ноутбуки )

Сообщить модератору | IP: Записан
Сообщение: 74588

Старое сообщение 20-03-2011 08:22
- За что?
 Дядя Миша
racing for fish

Дата регистрации: Oct 2005
Проживает: Кубань
Сообщений: 33064
Нанёс повреждений: 392 ед.

Рейтинг



LIGHTMAP_TEXTURE_WIDTH и LIGHTMAP_TEXTURE_HEIGHT равны размеру твоих лайтмап в движке. Обычно это 256 х 256, халфа использует 128х128. LM_SAMPLE_SIZE - 16 (захардкоденное значение разрешения лайтмапы для хл1\ку1\ку2). Менять нельзя ни в коем случае.

Цитата:
n00b писал:
Перевел всё на вершинные буфера - на карте de_dust2 3000+ fps за место 280 через glBegin\glEnd.

с такой маааленькой поправкой - без переключения текстур, без освещения, без студиомоделей и вообще без эдиктов.
А как только ты всё это нарисуешь, у тебя всё вернется обратно на круги своя.
Цитата:
n00b писал:
Можно ли без опасений использовать вершинные буфера, или все-таки ещё есть видеоустройства, которые их не поддерживают?

вертекс арраи везде поддерживаются. VBO не везде, к тому же оно может глючить на тех же ноутбуках. Кроме того на картах типа кушных вертекс арраи быстрее VBO.

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'

Сообщить модератору | IP: Записан
Сообщение: 74595

Старое сообщение 20-03-2011 10:46
-
n00b
Житель форума

Дата регистрации: Nov 2010
Проживает: (void)
Сообщений: 128

Рейтинг



Цитата:
с такой маааленькой поправкой - без переключения текстур, без освещения, без студиомоделей и вообще без эдиктов.
А как только ты всё это нарисуешь, у тебя всё вернется обратно на круги своя.


Ну это я просто для сравнения - 3000 и 280

Цитата:
вертекс арраи везде поддерживаются. VBO не везде, к тому же оно может глючить на тех же ноутбуках. Кроме того на картах типа кушных вертекс арраи быстрее VBO. [/B]


Ок, спасибо, сделаю без VBO.

Сообщить модератору | IP: Записан
Сообщение: 74597

Старое сообщение 20-03-2011 10:52
- За что?
Тема: (Опционально)
Ваш ответ:



Переводчик транслита


[проверить длину сообщения]
Опции: Автоматическое формирование ссылок: автоматически добавлять [url] и [/url] вокруг интернет адресов.
Уведомление по E-Mail: отправить вам уведомление, если кто-то ответил в тему (только для зарегистрированных пользователей).
Отключить смайлики в сообщении: не преобразовывать текстовые смайлики в картинки.
Показать подпись: добавить вашу подпись в конец сообщения (только зарегистрированные пользователи могут иметь подписи).

Временная зона GMT. Текущее время 22:21. Новая тема    Ответить
Страницы (2): [1] 2 »   Предыдущая тема   Следующая тема
HLFX.Ru Forum HLFX.Ru Forum > Теория и практика > Half-Life SDK > R_MarkLeaves
Из quake 1
Версия для печати | Отправить тему по E-Mail | Подписаться на эту тему

Быстрый переход:
Оцените эту тему:

Правила Форума:
Вы not можете создавать новые темы
Вы not можете отвечать в темы
Вы not можете прикреплять вложения
Вы not можете редактировать ваши сообщения
HTML Код ВЫКЛ
vB Код ВКЛ
Смайлики ВКЛ
[IMG] Код ВКЛ
 

< Обратная связь - HLFX.ru >

На основе vBulletin
Авторское право © 2000 - 2002, Jelsoft Enterprises Limited.
Дизайн и программирование: Crystice Softworks © 2005 - 2024