/** * @brief Developer tool for viewing BSP vertex normals. Only Phong interpolated * surfaces show their normals when r_shownormals > 1. */ void R_DrawBspNormals (int tile) { int i, j, k; const mBspSurface_t* surf; const mBspModel_t* bsp; const vec4_t color = {1.0, 0.0, 0.0, 1.0}; if (!r_shownormals->integer) return; R_EnableTexture(&texunit_diffuse, false); R_ResetArrayState(); /* default arrays */ R_Color(color); k = 0; bsp = &r_mapTiles[tile]->bsp; surf = bsp->surfaces; for (i = 0; i < bsp->numsurfaces; i++, surf++) { if (surf->frame != r_locals.frame) continue; /* not visible */ if (surf->texinfo->flags & SURF_WARP) continue; /* don't care */ if (r_shownormals->integer > 1 && !(surf->texinfo->flags & SURF_PHONG)) continue; /* don't care */ /* avoid overflows, draw in batches */ if (k > r_state.array_size - 512) { glDrawArrays(GL_LINES, 0, k / 3); k = 0; refdef.batchCount++; } for (j = 0; j < surf->numedges; j++) { vec3_t end; const GLfloat* vertex = &bsp->verts[(surf->index + j) * 3]; const GLfloat* normal = &bsp->normals[(surf->index + j) * 3]; VectorMA(vertex, 12.0, normal, end); memcpy(&r_state.vertex_array_3d[k], vertex, sizeof(vec3_t)); memcpy(&r_state.vertex_array_3d[k + 3], end, sizeof(vec3_t)); k += sizeof(vec3_t) / sizeof(vec_t) * 2; R_ReallocateStateArrays(k); } } glDrawArrays(GL_LINES, 0, k / 3); refdef.batchCount++; R_EnableTexture(&texunit_diffuse, true); R_Color(nullptr); }
/** * @brief Render the specified stage for the surface. Resolve vertex attributes via * helper functions, outputting to the default vertex arrays. */ static void R_DrawSurfaceStage (mBspSurface_t *surf, materialStage_t *stage) { int i; R_ReallocateStateArrays(surf->numedges); R_ReallocateTexunitArray(&texunit_diffuse, surf->numedges); R_ReallocateTexunitArray(&texunit_lightmap, surf->numedges); for (i = 0; i < surf->numedges; i++) { const float *v = &r_mapTiles[surf->tile]->bsp.verts[surf->index * 3 + i * 3]; const float *st = &r_mapTiles[surf->tile]->bsp.texcoords[surf->index * 2 + i * 2]; R_StageVertex(surf, stage, v, &r_state.vertex_array_3d[i * 3]); R_StageTexCoord(stage, v, st, &texunit_diffuse.texcoord_array[i * 2]); if (texunit_lightmap.enabled) { st = &r_mapTiles[surf->tile]->bsp.lmtexcoords[surf->index * 2 + i * 2]; texunit_lightmap.texcoord_array[i * 2 + 0] = st[0]; texunit_lightmap.texcoord_array[i * 2 + 1] = st[1]; } if (r_state.color_array_enabled) R_StageColor(stage, v, &r_state.color_array[i * 4]); /* normals and tangents */ if (r_state.lighting_enabled) { const float *n = &r_mapTiles[surf->tile]->bsp.normals[surf->index * 3 + i * 3]; memcpy(&r_state.normal_array[i * 3], n, sizeof(vec3_t)); if (r_state.active_normalmap) { const float *t = &r_mapTiles[surf->tile]->bsp.tangents[surf->index * 4 + i * 4]; memcpy(&r_state.tangent_array[i * 4], t, sizeof(vec3_t)); } } } glDrawArrays(GL_TRIANGLE_FAN, 0, i); refdef.batchCount++; R_CheckError(); }
/** * @brief Puts the map data into buffers * @sa R_ModAddMapTile * @note Shift the verts after the texcoords for diffuse and lightmap are loaded * @sa R_ModShiftTile * @todo Don't use the buffers from r_state here - they might overflow * @todo Decrease MAX_GL_ARRAY_LENGTH to 32768 again when this is fixed */ static void R_LoadBspVertexArrays (model_t *mod) { int i, j; int vertind, coordind, tangind; float *vecShifted; float soff, toff, s, t; float *point, *sdir, *tdir; vec4_t tangent; vec3_t binormal; mBspSurface_t *surf; mBspVertex_t *vert; int vertexcount; vertind = coordind = tangind = vertexcount = 0; for (i = 0, surf = mod->bsp.surfaces; i < mod->bsp.numsurfaces; i++, surf++) for (j = 0; j < surf->numedges; j++) vertexcount++; surf = mod->bsp.surfaces; /* allocate the vertex arrays */ mod->bsp.texcoords = (GLfloat *)Mem_PoolAlloc(vertexcount * 2 * sizeof(GLfloat), vid_modelPool, 0); mod->bsp.lmtexcoords = (GLfloat *)Mem_PoolAlloc(vertexcount * 2 * sizeof(GLfloat), vid_modelPool, 0); mod->bsp.verts = (GLfloat *)Mem_PoolAlloc(vertexcount * 3 * sizeof(GLfloat), vid_modelPool, 0); mod->bsp.normals = (GLfloat *)Mem_PoolAlloc(vertexcount * 3 * sizeof(GLfloat), vid_modelPool, 0); mod->bsp.tangents = (GLfloat *)Mem_PoolAlloc(vertexcount * 4 * sizeof(GLfloat), vid_modelPool, 0); for (i = 0; i < mod->bsp.numsurfaces; i++, surf++) { surf->index = vertind / 3; for (j = 0; j < surf->numedges; j++) { const float *normal; const int index = mod->bsp.surfedges[surf->firstedge + j]; /* vertex */ if (index > 0) { /* negative indices to differentiate which end of the edge */ const mBspEdge_t *edge = &mod->bsp.edges[index]; vert = &mod->bsp.vertexes[edge->v[0]]; } else { const mBspEdge_t *edge = &mod->bsp.edges[-index]; vert = &mod->bsp.vertexes[edge->v[1]]; } point = vert->position; /* shift it for assembled maps */ vecShifted = &mod->bsp.verts[vertind]; /* origin (func_door, func_rotating) bmodels must not have shifted vertices, * they are translated by their entity origin value */ if (surf->isOriginBrushModel) VectorCopy(point, vecShifted); else VectorAdd(point, shift, vecShifted); /* texture directional vectors and offsets */ sdir = surf->texinfo->uv; soff = surf->texinfo->u_offset; tdir = surf->texinfo->vv; toff = surf->texinfo->v_offset; /* texture coordinates */ s = DotProduct(point, sdir) + soff; s /= surf->texinfo->image->width; t = DotProduct(point, tdir) + toff; t /= surf->texinfo->image->height; mod->bsp.texcoords[coordind + 0] = s; mod->bsp.texcoords[coordind + 1] = t; if (surf->flags & MSURF_LIGHTMAP) { /* lightmap coordinates */ s = DotProduct(point, sdir) + soff; s -= surf->stmins[0]; s += surf->light_s * surf->lightmap_scale; s += surf->lightmap_scale / 2.0; s /= r_lightmaps.size * surf->lightmap_scale; t = DotProduct(point, tdir) + toff; t -= surf->stmins[1]; t += surf->light_t * surf->lightmap_scale; t += surf->lightmap_scale / 2.0; t /= r_lightmaps.size * surf->lightmap_scale; } mod->bsp.lmtexcoords[coordind + 0] = s; mod->bsp.lmtexcoords[coordind + 1] = t; /* normal vectors */ if ((surf->texinfo->flags & SURF_PHONG) && VectorNotEmpty(vert->normal)) normal = vert->normal; /* phong shaded */ else normal = surf->normal; /* per plane */ memcpy(&mod->bsp.normals[vertind], normal, sizeof(vec3_t)); /* tangent vector */ TangentVectors(normal, sdir, tdir, tangent, binormal); memcpy(&mod->bsp.tangents[tangind], tangent, sizeof(vec4_t)); vertind += 3; coordind += 2; tangind += 4; } } R_ReallocateStateArrays(vertind / 3); if (qglBindBuffer) { /* and also the vertex buffer objects */ qglGenBuffers(1, &mod->bsp.vertex_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer); qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.normal_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer); qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW); qglGenBuffers(1, &mod->bsp.tangent_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer); qglBufferData(GL_ARRAY_BUFFER, tangind * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW); qglBindBuffer(GL_ARRAY_BUFFER, 0); } }