Extending Quake Limits - Part 3: Alias Models
Moderator: InsideQC Admins
18 posts
• Page 2 of 2 • 1, 2
some experiments i done seems to work quite ok.
this was modified from old pqer source for and easy way to implement vertex arrays.
and the header
atm i use it for the parts of realm that was not yet drawn with arrays gl_draw.c etc.
heres an example of use.
this was modified from old pqer source for and easy way to implement vertex arrays.
- Code: Select all
// fenix@io.com: vertex arrays
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#include "varrays.h"
#define R_MIN_VERTEX_COUNT 128
vavertex_t* global_vertex_array;
unsigned* global_indice_array;
texcoord_t* global_lightmap_texcoords;
int global_vertex_array_size;
int global_indice_array_size;
int mode_table[] =
{
/* R_POINTS */ GL_POINTS,
/* R_LINES */ GL_LINES,
/* R_LINE_STRIP */ GL_LINE_STRIP,
/* R_LINE_LOOP */ GL_LINE_LOOP,
/* R_TRIANGLES */ GL_TRIANGLES,
/* R_TRIANGLE_STRIP */ GL_TRIANGLE_STRIP,
/* R_TRIANGLE_FAN */ GL_TRIANGLE_FAN,
/* R_QUADS */ GL_QUADS,
/* R_QUAD_STRIP */ GL_QUAD_STRIP,
/* R_POLYGON */ GL_POLYGON
};
vavertex_t* current_vertex_array;
unsigned current_vertex_fields;
texcoord_t* current_lightmap_texcoords;
/* R_InitVertexArrays
****************************************************************************/
void R_InitVertexArrays(void)
{
int pnum = COM_CheckParm("-varraysize");
if (pnum != 0)
{
global_vertex_array_size = atoi(com_argv[pnum + 1]);
if (global_vertex_array_size < R_MIN_VERTEX_COUNT)
{
global_vertex_array_size = R_MIN_VERTEX_COUNT;
}
}
else
{
global_vertex_array_size = R_MIN_VERTEX_COUNT;
}
global_indice_array_size = global_vertex_array_size;
global_vertex_array = Heap_ZAlloc(sizeof(vavertex_t) * global_vertex_array_size);
global_indice_array = Heap_ZAlloc(sizeof(vavertex_t) * global_indice_array_size);
global_lightmap_texcoords = Heap_ZAlloc(sizeof(texcoord_t) * global_vertex_array_size);
}
/* R_VertexArray
****************************************************************************/
void R_VertexArray(vavertex_t* varray, texcoord_t* texcoords, unsigned fields)
{
current_lightmap_texcoords = texcoords;
current_vertex_array = varray;
current_vertex_fields = 0;
if (fields & R_VERTEX3)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(vavertex_t), &varray->x);
current_vertex_fields |= R_VERTEX3;
}
else if (fields & R_VERTEX2)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(vavertex_t), &varray->x);
current_vertex_fields |= R_VERTEX2;
}
else
{
glDisableClientState(GL_VERTEX_ARRAY);
}
if (fields & R_COLOR4)
{
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vavertex_t), &varray->r);
current_vertex_fields |= R_COLOR4;
}
else if (fields & R_COLOR3)
{
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(vavertex_t), &varray->r);
current_vertex_fields |= R_COLOR3;
}
else
{
glDisableClientState(GL_COLOR_ARRAY);
}
if (fields & R_TEXCOORD2)
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(vavertex_t), &varray->s);
current_vertex_fields |= R_TEXCOORD2;
}
else
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
/* R_DrawArray
****************************************************************************/
void R_DrawArray(R_MODE mode, int first, size_t count)
{
glDrawArrays(mode_table[mode], first, count);
}
/* R_DrawElements
****************************************************************************/
void R_DrawElements(R_MODE mode, size_t count, unsigned* indices)
{
glDrawElements(mode_table[mode], count, GL_UNSIGNED_INT, indices);
}
/* R_DrawRangeElements
****************************************************************************/
void R_DrawRangeElements(R_MODE mode, unsigned start, unsigned end, size_t count, unsigned* indices)
{
glDrawRangeElements(mode_table[mode], start, end, count, GL_UNSIGNED_INT, indices);
}
and the header
- Code: Select all
// fenix@io.com: vertex arrays
#ifndef GL_RVA_INCLUDED
#define GL_RVA_INCLUDED
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
typedef struct vavertex_s
{
float x, y, z; // vertex
float s, t; // texcoord
signed char i, j, k; // normal
unsigned char n; // normal index
unsigned char r, g, b, a; // color
} vavertex_t;
typedef struct texcoord_s
{
float s, t;
} texcoord_t;
typedef enum
{
R_COLOR3 = 1,
R_COLOR4 = 2,
R_TEXCOORD2 = 4,
R_VERTEX2 = 8,
R_VERTEX3 = 16
} R_VAFIELD;
typedef enum
{
R_POINTS,
R_LINES,
R_LINE_STRIP,
R_LINE_LOOP,
R_TRIANGLES,
R_TRIANGLE_STRIP,
R_TRIANGLE_FAN,
R_QUADS,
R_QUAD_STRIP,
R_POLYGON
} R_MODE;
extern vavertex_t* global_vertex_array;
extern unsigned* global_indice_array;
extern int global_vertex_array_size;
extern int global_indice_array_size;
extern texcoord_t* global_lightmap_texcoords;
extern texcoord_t* current_lightmap_texcoords;
void R_InitVertexArrays(void);
void R_VertexArray(vavertex_t* varray, texcoord_t* texcoords, unsigned fields);
void R_DrawArray(R_MODE mode, int first, size_t count);
void R_DrawElements(R_MODE mode, size_t count, unsigned* indices);
void R_DrawRangeElements(R_MODE, unsigned start, unsigned end, size_t count, unsigned* indices);
#endif
atm i use it for the parts of realm that was not yet drawn with arrays gl_draw.c etc.
heres an example of use.
- Code: Select all
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation)
{
int v, u, c;
unsigned trans[64*64], *dest;
byte *src;
int p;
vavertex_t *varray;
GL_Bind (translate_texture);
c = pic->width * pic->height;
dest = trans;
for (v=0 ; v<64 ; v++, dest += 64)
{
src = &menuplyr_pixels[ ((v*pic->height)>>6) *pic->width];
for (u=0 ; u<64 ; u++)
{
p = src[(u*pic->width)>>6];
if (p == 255)
dest[u] = p;
else
dest[u] = d_8to24table[translation[p]];
}
}
glTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glColor3f (1,1,1);
R_VertexArray(global_vertex_array, R_VERTEX2|R_TEXCOORD2);
varray = global_vertex_array;
varray->s = 0;
varray->t = 0;
varray->x = x;
varray->y = y;
varray++;
varray->s = 1;
varray->t = 0;
varray->x = x + pic->width;
varray->y = y;
varray++;
varray->s = 1;
varray->t = 1;
varray->x = x + pic->width;
varray->y = y + pic->height;
varray++;
varray->s = 0;
varray->t = 1;
varray->x = x;
varray->y = y + pic->height;
R_DrawArray(R_QUADS, 0, 4);
}
-

revelator - Posts: 2567
- Joined: Thu Jan 24, 2008 12:04 pm
- Location: inside tha debugger
The software renderer has limits hard-coded into the x86 ASM code. I've tried to extend the limit of vertexes in it once, but since I know pretty much nothing about x86 ASM I've got a lot of weird errors.
-

mankrip - Posts: 915
- Joined: Fri Jul 04, 2008 3:02 am
Re: Extending Quake Limits - Part 3: Alias Models
Vertex cache optimization (read all about it) for the glDrawElements version of the above code:
Plonk this at the end of your new GL_MakeAliasModelDisplayLists.
You'll need to remove some C++isms (like the "int i" in the for loops) as well as pass pheader as an additional param to the original function (I called it "hdr" here).
This also needs to include "d3dx9.h" and link to "d3dx9.lib" but it works perfectly in OpenGL too; I just put it into RMQ and got very measurable performance improvements in cases where MDL drawing was the primary bottleneck in the scene.
- Code: Select all
// optimize the model
{
int hunkmark = Hunk_LowMark ();
int numtris = hdr->numindexes / 3;
unsigned short *newindexes = (unsigned short *) Hunk_Alloc (hdr->numindexes * sizeof (unsigned short));
DWORD *optresult = (DWORD *) Hunk_Alloc ((hdr->numverts > numtris ? hdr->numverts : numtris) * sizeof (DWORD));
aliasmesh_t *newvertexes = (aliasmesh_t *) Hunk_Alloc (hdr->numverts * sizeof (aliasmesh_t));
DWORD *remap = (DWORD *) Hunk_Alloc (hdr->numverts * sizeof (DWORD));
D3DXOptimizeFaces (indexes, numtris, hdr->numverts, FALSE, optresult);
for (int i = 0; i < numtris; i++)
{
int src = optresult[i] * 3;
int dst = i * 3;
newindexes[dst + 0] = indexes[src + 0];
newindexes[dst + 1] = indexes[src + 1];
newindexes[dst + 2] = indexes[src + 2];
}
D3DXOptimizeVertices (newindexes, numtris, hdr->numverts, FALSE, optresult);
for (int i = 0; i < hdr->numverts; i++)
{
memcpy (&newvertexes[i], &hunkmesh[optresult[i]], sizeof (aliasmesh_t));
remap[optresult[i]] = i;
}
// copy the optimized version back out
for (int i = 0; i < hdr->numindexes; i++)
indexes[i] = remap[newindexes[i]];
for (int i = 0; i < hdr->numverts; i++)
{
hunkmesh[i].vertindex = newvertexes[i].vertindex;
hunkmesh[i].st[0] = newvertexes[i].st[0];
hunkmesh[i].st[1] = newvertexes[i].st[1];
}
Hunk_FreeToLowMark (hunkmark);
}
Plonk this at the end of your new GL_MakeAliasModelDisplayLists.
You'll need to remove some C++isms (like the "int i" in the for loops) as well as pass pheader as an additional param to the original function (I called it "hdr" here).
This also needs to include "d3dx9.h" and link to "d3dx9.lib" but it works perfectly in OpenGL too; I just put it into RMQ and got very measurable performance improvements in cases where MDL drawing was the primary bottleneck in the scene.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
We knew the words, we knew the score, we knew what we were fighting for
-

mh - Posts: 2292
- Joined: Sat Jan 12, 2008 1:38 am
18 posts
• Page 2 of 2 • 1, 2
Return to Programming Tutorials
Who is online
Users browsing this forum: No registered users and 1 guest