HLFX.Ru Forum Страницы (2): [1] 2 »
Показать все 23 сообщений этой темы на одной странице

HLFX.Ru Forum (https://hlfx.ru/forum/index.php)
- Half-Life SDK (https://hlfx.ru/forum/forumdisplay.php?forumid=8)
-- R_MarkLeaves (https://hlfx.ru/forum/showthread.php?threadid=2701)


Отправлено n00b 18-03-2011 в 11:53:

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
}


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


Отправлено XaeroX 18-03-2011 в 12:14:

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

Да.

__________________

xaerox on Vivino


Отправлено n00b 18-03-2011 в 13:08:

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


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


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


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


Отправлено XaeroX 18-03-2011 в 13:16:

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

__________________

xaerox on Vivino


Отправлено n00b 18-03-2011 в 13:23:

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


Отправлено XaeroX 18-03-2011 в 13:28:

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

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

__________________

xaerox on Vivino


Отправлено Дядя Миша 18-03-2011 в 14:00:

Цитата:
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'


Отправлено XaeroX 18-03-2011 в 14:07:

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

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

__________________

xaerox on Vivino


Отправлено n00b 18-03-2011 в 14:16:

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


Отправлено Дядя Миша 18-03-2011 в 14:51:

Цитата:
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'


Отправлено n00b 19-03-2011 в 15:58:

Я тут решил разбить все плоскости карты на треугольники.
Треугольники делаю по рёбрам фейса, точки плоскости беру методом из 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 прямой фейса может быть несколько ребер и их надо склеивать, или всё же неверен алгоритм разбивания ?


Отправлено Дядя Миша 19-03-2011 в 17:12:

Цитата:
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'


Отправлено n00b 20-03-2011 в 08:22:

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

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

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

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


Отправлено Дядя Миша 20-03-2011 в 10:46:

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'


Отправлено n00b 20-03-2011 в 10:52:

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


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

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


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


Временная зона GMT. Текущее время 22:23. Страницы (2): [1] 2 »
Показать все 23 сообщений этой темы на одной странице

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