- R_Mesh_Start();
-}
-
-void R_Mesh_AddTransparent(void)
-{
- int i, j, k, *index;
- float viewdistcompare, centerscaler, dist1, dist2, dist3, center, maxdist;
- buf_vertex_t *vert1, *vert2, *vert3;
- buf_transtri_t *tri;
- buf_mesh_t *mesh, *transmesh;
-
- if (!currenttransmesh)
- return;
-
- // convert index data to transtris for sorting
- for (j = 0;j < currenttransmesh;j++)
- {
- mesh = buf_transmesh + j;
- k = mesh->firsttriangle;
- index = &buf_transtri[k].index[0];
- for (i = 0;i < mesh->triangles;i++)
- {
- tri = &buf_sorttranstri[k++];
- tri->mesh = mesh;
- tri->index[0] = *index++;
- tri->index[1] = *index++;
- tri->index[2] = *index++;
- }
- }
-
- // map farclip to 0-4095 list range
- centerscaler = (TRANSDEPTHRES / r_farclip) * (1.0f / 3.0f);
- viewdistcompare = viewdist + 4.0f;
-
- memset(buf_sorttranstri_list, 0, TRANSDEPTHRES * sizeof(buf_transtri_t *));
-
- k = 0;
- for (j = 0;j < currenttranstriangle;j++)
- {
- tri = &buf_sorttranstri[j];
- i = tri->mesh->firstvert;
-
- vert1 = &buf_transvertex[tri->index[0] + i];
- vert2 = &buf_transvertex[tri->index[1] + i];
- vert3 = &buf_transvertex[tri->index[2] + i];
-
- dist1 = DotProduct(vert1->v, vpn);
- dist2 = DotProduct(vert2->v, vpn);
- dist3 = DotProduct(vert3->v, vpn);
-
- maxdist = max(dist1, max(dist2, dist3));
- if (maxdist < viewdistcompare)
- continue;
-
- center = (dist1 + dist2 + dist3) * centerscaler - viewdist;
-#if SLOWMATH
- i = (int) center;
- i = bound(0, i, (TRANSDEPTHRES - 1));
-#else
- if (center < 0.0f)
- center = 0.0f;
- center += 8388608.0f;
- i = *((int *)¢er) & 0x7FFFFF;
- i = min(i, (TRANSDEPTHRES - 1));
-#endif
- tri->next = buf_sorttranstri_list[i];
- buf_sorttranstri_list[i] = tri;
- k++;
- }
-
- for (i = 0;i < currenttransmesh;i++)
- buf_transmesh[i].transchain = NULL;
- transmesh = NULL;
- for (j = 0;j < TRANSDEPTHRES;j++)
- {
- if ((tri = buf_sorttranstri_list[j]))
- {
- for (;tri;tri = tri->next)
- {
- if (!tri->mesh->transchain)
- {
- tri->mesh->chain = transmesh;
- transmesh = tri->mesh;
- }
- tri->meshsortchain = tri->mesh->transchain;
- tri->mesh->transchain = tri;
- }
- }
- }
-
- for (;transmesh;transmesh = transmesh->chain)
- {
- if (currentmesh >= max_meshs || currenttriangle + transmesh->triangles > max_batch || currenttriangle + transmesh->triangles > 1024 || currentvertex + transmesh->verts > max_verts)
- R_Mesh_Render();
-
- mesh = &buf_mesh[currentmesh++];
- *mesh = *transmesh; // copy mesh properties
-
- mesh->firstvert = currentvertex;
- memcpy(&buf_vertex[currentvertex], &buf_transvertex[transmesh->firstvert], transmesh->verts * sizeof(buf_vertex_t));
- memcpy(&buf_fcolor[currentvertex], &buf_transfcolor[transmesh->firstvert], transmesh->verts * sizeof(buf_fcolor_t));
- for (i = 0;i < backendunits && transmesh->textures[i];i++)
- memcpy(&buf_texcoord[i][currentvertex], &buf_transtexcoord[i][transmesh->firstvert], transmesh->verts * sizeof(buf_texcoord_t));
- currentvertex += mesh->verts;
-
- mesh->firsttriangle = currenttriangle;
- for (tri = transmesh->transchain;tri;tri = tri->meshsortchain)
- {
- buf_tri[currenttriangle].index[0] = tri->index[0];
- buf_tri[currenttriangle].index[1] = tri->index[1];
- buf_tri[currenttriangle].index[2] = tri->index[2];
- currenttriangle++;
- }
- mesh->triangles = currenttriangle - mesh->firsttriangle;
- }
-
- currenttransmesh = 0;
- currenttranstriangle = 0;
- currenttransvertex = 0;
-}
-
-void R_Mesh_Draw(const rmeshinfo_t *m)
-{
- // these are static because gcc runs out of virtual registers otherwise
- static int i, j, overbright, *index;
- static float *in, scaler;
- static float cr, cg, cb, ca;
- static buf_mesh_t *mesh;
- static buf_vertex_t *vert;
- static buf_fcolor_t *fcolor;
- static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
-
- if (!backendactive)
- Sys_Error("R_Mesh_Draw: called when backend is not active\n");
-
- if (m->index == NULL
- || !m->numtriangles
- || m->vertex == NULL
- || !m->numverts)
- Host_Error("R_Mesh_Draw: no triangles or verts\n");
-
- // ignore meaningless alpha meshs
- if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
- {
- if (m->color)
- {
- for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
- if (*in >= 0.01f)
- break;
- if (i == m->numverts)
- return;
- }
- else if (m->ca < 0.01f)
- return;
- }
-
- if (!backendactive)
- Sys_Error("R_Mesh_Draw: called when backend is not active\n");
-
-#ifdef DEBUGGL
- for (i = 0;i < m->numtriangles * 3;i++)
- if ((unsigned int) m->index[i] >= (unsigned int) m->numverts)
- Host_Error("R_Mesh_Draw: invalid index (%i of %i verts)\n", m->index, m->numverts);
-#endif
-
- // LordHavoc: removed this error condition because with floatcolors 0,
- // the 3DFX driver works with very large meshs
- // FIXME: we can work around this by falling back on non-array renderer if buffers are too big
- //if (m->numtriangles > 1024 || m->numverts > 3072)
- //{
- // Con_Printf("R_Mesh_Draw: mesh too big for 3DFX drivers, rejected\n");
- // return;
- //}
-
- if (m->numtriangles > max_meshs || m->numverts > max_verts)
- {
- Con_Printf("R_Mesh_Draw: mesh too big for current gl_mesh_maxtriangles setting, increasing limits\n");
- if (m->numtriangles > overflowedmeshtris)
- overflowedmeshtris = m->numtriangles;
- if (((m->numverts + 2) / 3) > overflowedmeshtris)
- overflowedmeshtris = (m->numverts + 2) / 3;
- return;
- }
-
- if (m->transparent)
- {
- if (currenttransmesh >= max_transmeshs || (currenttranstriangle + m->numtriangles) > max_transmeshs || (currenttransvertex + m->numverts) > max_transverts)
- {
- if (!transranout)
- {
- Con_Printf("R_Mesh_Draw: ran out of room for transparent meshs\n");
- transranout = true;
- }
- return;
- }
-
- c_transmeshs++;
- c_transtris += m->numtriangles;
- vert = &buf_transvertex[currenttransvertex];
- fcolor = &buf_transfcolor[currenttransvertex];
- for (i = 0;i < backendunits;i++)
- texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
-
- // transmesh is only for storage of transparent meshs until they
- // are inserted into the main mesh array
- mesh = &buf_transmesh[currenttransmesh++];
- mesh->firsttriangle = currenttranstriangle;
- mesh->firstvert = currenttransvertex;
- index = &buf_transtri[currenttranstriangle].index[0];
-
- currenttranstriangle += m->numtriangles;
- currenttransvertex += m->numverts;
- }
- else
- {
- if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
- R_Mesh_Render();
-
- c_meshs++;
- c_meshtris += m->numtriangles;
- vert = &buf_vertex[currentvertex];
- fcolor = &buf_fcolor[currentvertex];
- for (i = 0;i < backendunits;i++)
- texcoord[i] = &buf_texcoord[i][currentvertex];
-
- // opaque meshs are rendered directly
- mesh = &buf_mesh[currentmesh++];
- mesh->firsttriangle = currenttriangle;
- mesh->firstvert = currentvertex;
- index = &buf_tri[currenttriangle].index[0];
-
- currenttriangle += m->numtriangles;
- currentvertex += m->numverts;
- }
-
- // code shared for transparent and opaque meshs
- memcpy(index, m->index, sizeof(int[3]) * m->numtriangles);
- mesh->blendfunc1 = m->blendfunc1;
- mesh->blendfunc2 = m->blendfunc2;
- mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
- mesh->depthtest = !m->depthdisable;
- mesh->triangles = m->numtriangles;
- mesh->verts = m->numverts;
-
- overbright = false;
- scaler = 1;
- if (m->blendfunc2 == GL_SRC_COLOR)
- {
- if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
- scaler *= 0.5f;
- }
- else
- {
- if (m->tex[0])
- {
- overbright = gl_combine.integer;
- if (overbright)
- scaler *= 0.25f;
- }
- scaler *= overbrightscale;
- }
-
-
- j = -1;
- for (i = 0;i < backendunits;i++)
- {
- if ((mesh->textures[i] = m->tex[i]))
- j = i;
- mesh->texturergbscale[i] = m->texrgbscale[i];
- if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
- mesh->texturergbscale[i] = 1;
- }
- if (overbright && j >= 0)
- mesh->texturergbscale[j] = 4;
-
- if (m->vertexstep != sizeof(buf_vertex_t))
- {
- for (i = 0, in = m->vertex;i < m->numverts;i++, (int)in += m->vertexstep)
- {
- vert[i].v[0] = in[0];
- vert[i].v[1] = in[1];
- vert[i].v[2] = in[2];
- }
- }
- else
- memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
-
- if (m->color)
- {
- for (i = 0, in = m->color;i < m->numverts;i++, (int)in += m->colorstep)
- {
- fcolor[i].c[0] = in[0] * scaler;
- fcolor[i].c[1] = in[1] * scaler;
- fcolor[i].c[2] = in[2] * scaler;
- fcolor[i].c[3] = in[3];
- }
- }
- else
- {
- cr = m->cr * scaler;
- cg = m->cg * scaler;
- cb = m->cb * scaler;
- ca = m->ca;
- for (i = 0;i < m->numverts;i++)
- {
- fcolor[i].c[0] = cr;
- fcolor[i].c[1] = cg;
- fcolor[i].c[2] = cb;
- fcolor[i].c[3] = ca;
- }
- }
-
- for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
- {
- if (j >= backendunits)
- Sys_Error("R_Mesh_Draw: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
- if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
- {
- for (i = 0, in = m->texcoords[j];i < m->numverts;i++, (int)in += m->texcoordstep[j])
- {
- texcoord[j][i].t[0] = in[0];
- texcoord[j][i].t[1] = in[1];
- }
- }
- else
- memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
- }
-
- if (currenttriangle >= max_batch)
- R_Mesh_Render();
-}
-
-void R_Mesh_Draw_NativeOnly(const rmeshinfo_t *m)
-{
- // these are static because gcc runs out of virtual registers otherwise
- static int i, j, overbright, *index;
- static float *in, scaler;
- static buf_mesh_t *mesh;
- static buf_vertex_t *vert;
- static buf_fcolor_t *fcolor;
- static buf_texcoord_t *texcoord[MAX_TEXTUREUNITS];
-
- if (!backendactive)
- Sys_Error("R_Mesh_Draw: called when backend is not active\n");
-
- if (m->index == NULL
- || !m->numtriangles
- || m->vertex == NULL
- || !m->numverts)
- Host_Error("R_Mesh_Draw: no triangles or verts\n");
-
- // ignore meaningless alpha meshs
- if (!m->depthwrite && m->blendfunc1 == GL_SRC_ALPHA && (m->blendfunc2 == GL_ONE || m->blendfunc2 == GL_ONE_MINUS_SRC_ALPHA))
- {
- if (m->color)
- {
- for (i = 0, in = m->color + 3;i < m->numverts;i++, (int)in += m->colorstep)
- if (*in >= 0.01f)
- break;
- if (i == m->numverts)
- return;
- }
- else if (m->ca < 0.01f)
- return;
- }
-
- // LordHavoc: removed this error condition because with floatcolors 0,
- // the 3DFX driver works with very large meshs
- // FIXME: we can work around this by falling back on non-array renderer if buffers are too big
- //if (m->numtriangles > 1024 || m->numverts > 3072)
- //{
- // Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for 3DFX drivers, rejected\n");
- // return;
- //}
-
- if (m->numtriangles > max_meshs || m->numverts > max_verts)
- {
- Con_Printf("R_Mesh_Draw_NativeOnly: mesh too big for current gl_mesh_maxtriangles setting, increasing limits\n");
- if (m->numtriangles > overflowedmeshtris)
- overflowedmeshtris = m->numtriangles;
- if (((m->numverts + 2) / 3) > overflowedmeshtris)
- overflowedmeshtris = (m->numverts + 2) / 3;
- return;
- }
-
- if (m->transparent)
- {
- if (currenttransmesh >= max_transmeshs || (currenttranstriangle + m->numtriangles) > max_transmeshs || (currenttransvertex + m->numverts) > max_transverts)
- {
- if (!transranout)
- {
- Con_Printf("R_Mesh_Draw_NativeOnly: ran out of room for transparent meshs\n");
- transranout = true;
- }
- return;
- }
-
- c_transmeshs++;
- c_transtris += m->numtriangles;
- vert = &buf_transvertex[currenttransvertex];
- fcolor = &buf_transfcolor[currenttransvertex];
- for (i = 0;i < backendunits;i++)
- texcoord[i] = &buf_transtexcoord[i][currenttransvertex];
-
- // transmesh is only for storage of transparent meshs until they
- // are inserted into the main mesh array
- mesh = &buf_transmesh[currenttransmesh++];
- mesh->firsttriangle = currenttranstriangle;
- mesh->firstvert = currenttransvertex;
- index = &buf_transtri[currenttranstriangle].index[0];
- currenttranstriangle += m->numtriangles;
- currenttransvertex += m->numverts;
- }
- else
- {
- if (currentmesh >= max_meshs || (currenttriangle + m->numtriangles) > max_batch || (currentvertex + m->numverts) > max_verts)
- R_Mesh_Render();
-
- c_meshs++;
- c_meshtris += m->numtriangles;
- vert = &buf_vertex[currentvertex];
- fcolor = &buf_fcolor[currentvertex];
- for (i = 0;i < backendunits;i++)
- texcoord[i] = &buf_texcoord[i][currentvertex];
-
- // opaque meshs are rendered directly
- mesh = &buf_mesh[currentmesh++];
- mesh->firsttriangle = currenttriangle;
- mesh->firstvert = currentvertex;
- index = &buf_tri[currenttriangle].index[0];
- currenttriangle += m->numtriangles;
- currentvertex += m->numverts;
- }
-
- // code shared for transparent and opaque meshs
- memcpy(index, m->index, sizeof(int[3]) * m->numtriangles);
- mesh->blendfunc1 = m->blendfunc1;
- mesh->blendfunc2 = m->blendfunc2;
- mesh->depthmask = (m->blendfunc2 == GL_ZERO || m->depthwrite);
- mesh->depthtest = !m->depthdisable;
- mesh->triangles = m->numtriangles;
- mesh->verts = m->numverts;
-
- overbright = false;
- scaler = 1;
- if (m->blendfunc2 == GL_SRC_COLOR)
- {
- if (m->blendfunc1 == GL_DST_COLOR) // 2x modulate with framebuffer
- scaler *= 0.5f;
- }
- else
- {
- if (m->tex[0])
- {
- overbright = gl_combine.integer;
- if (overbright)
- scaler *= 0.25f;
- }
- scaler *= overbrightscale;
- }
-
- j = -1;
- for (i = 0;i < backendunits;i++)
- {
- if ((mesh->textures[i] = m->tex[i]))
- j = i;
- mesh->texturergbscale[i] = m->texrgbscale[i];
- if (mesh->texturergbscale[i] != 1 && mesh->texturergbscale[i] != 2 && mesh->texturergbscale[i] != 4)
- mesh->texturergbscale[i] = 1;
- }
- if (overbright && j >= 0)
- mesh->texturergbscale[j] = 4;
-
- if (m->vertexstep != sizeof(buf_vertex_t))
- Host_Error("R_Mesh_Draw_NativeOnly: unsupported vertexstep\n");
- if (m->colorstep != sizeof(buf_fcolor_t))
- Host_Error("R_Mesh_Draw_NativeOnly: unsupported colorstep\n");
- if (m->color == NULL)
- Host_Error("R_Mesh_Draw_NativeOnly: must provide color array\n");
- for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
- {
- if (j >= backendunits)
- Sys_Error("R_Mesh_Draw_NativeOnly: texture %i supplied when there are only %i texture units\n", j + 1, backendunits);
- if (m->texcoordstep[j] != sizeof(buf_texcoord_t))
- Host_Error("R_Mesh_Draw_NativeOnly: unsupported texcoordstep\n");
- }
-
- memcpy(vert, m->vertex, m->numverts * sizeof(buf_vertex_t));
- for (j = 0;j < MAX_TEXTUREUNITS && m->tex[j];j++)
- memcpy(&texcoord[j][0].t[0], m->texcoords[j], m->numverts * sizeof(buf_texcoord_t));
-
- memcpy(fcolor, m->color, m->numverts * sizeof(buf_fcolor_t));
-
- // do this as a second step because memcpy preloaded the cache, which we can't easily do
- if (scaler != 1)
- {
- for (i = 0;i < m->numverts;i++)
- {
- fcolor[i].c[0] *= scaler;
- fcolor[i].c[1] *= scaler;
- fcolor[i].c[2] *= scaler;
- }
- }
-
- if (currenttriangle >= max_batch)
- R_Mesh_Render();