/** * @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]; if (vertind >= MAX_GL_ARRAY_LENGTH * 3) Com_Error(ERR_DROP, "R_LoadBspVertexArrays: Exceeded MAX_GL_ARRAY_LENGTH %i", vertind); /* 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; } } 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); } }
/* * R_LoadBspVertexArrays */ static void R_LoadBspVertexArrays(void) { int i, j; int vert_index, texcoord_index, tangent_index, color_index; float soff, toff, s, t; float *point, *normal, *sdir, *tdir; vec4_t tangent; vec3_t bitangent; r_bsp_surface_t *surf; r_bsp_edge_t *edge; r_bsp_vertex_t *vert; R_AllocVertexArrays(r_load_model); // allocate the arrays vert_index = texcoord_index = tangent_index = 0; surf = r_load_model->surfaces; for (i = 0; i < r_load_model->num_surfaces; i++, surf++) { surf->index = vert_index / 3; for (j = 0; j < surf->num_edges; j++) { const int index = r_load_model->surface_edges[surf->first_edge + j]; // vertex if (index > 0) { // negative indices to differentiate which end of the edge edge = &r_load_model->edges[index]; vert = &r_load_model->vertexes[edge->v[0]]; } else { edge = &r_load_model->edges[-index]; vert = &r_load_model->vertexes[edge->v[1]]; } point = vert->position; memcpy(&r_load_model->verts[vert_index], point, sizeof(vec3_t)); // texture directional vectors and offsets sdir = surf->texinfo->vecs[0]; soff = surf->texinfo->vecs[0][3]; tdir = surf->texinfo->vecs[1]; toff = surf->texinfo->vecs[1][3]; // texture coordinates s = DotProduct(point, sdir) + soff; s /= surf->texinfo->image->width; t = DotProduct(point, tdir) + toff; t /= surf->texinfo->image->height; r_load_model->texcoords[texcoord_index + 0] = s; r_load_model->texcoords[texcoord_index + 1] = t; if (surf->flags & R_SURF_LIGHTMAP) { // lightmap coordinates s = DotProduct(point, sdir) + soff; s -= surf->st_mins[0]; s += surf->light_s * r_load_model->lightmap_scale; s += r_load_model->lightmap_scale / 2.0; s /= r_lightmaps.size * r_load_model->lightmap_scale; t = DotProduct(point, tdir) + toff; t -= surf->st_mins[1]; t += surf->light_t * r_load_model->lightmap_scale; t += r_load_model->lightmap_scale / 2.0; t /= r_lightmaps.size * r_load_model->lightmap_scale; } r_load_model->lmtexcoords[texcoord_index + 0] = s; r_load_model->lmtexcoords[texcoord_index + 1] = t; // normal vector if ((surf->texinfo->flags & SURF_PHONG) && !VectorCompare( vert->normal, vec3_origin)) // phong shaded normal = vert->normal; else // per-plane normal = surf->normal; memcpy(&r_load_model->normals[vert_index], normal, sizeof(vec3_t)); // tangent vector TangentVectors(normal, sdir, tdir, tangent, bitangent); memcpy(&r_load_model->tangents[tangent_index], tangent, sizeof(vec4_t)); // accumulate colors R_AddBspVertexColor(vert, surf); vert_index += 3; texcoord_index += 2; tangent_index += 4; } } color_index = 0; surf = r_load_model->surfaces; // now iterate over the verts again, assembling the accumulated colors for (i = 0; i < r_load_model->num_surfaces; i++, surf++) { for (j = 0; j < surf->num_edges; j++) { const int index = r_load_model->surface_edges[surf->first_edge + j]; // vertex if (index > 0) { // negative indices to differentiate which end of the edge edge = &r_load_model->edges[index]; vert = &r_load_model->vertexes[edge->v[0]]; } else { edge = &r_load_model->edges[-index]; vert = &r_load_model->vertexes[edge->v[1]]; } memcpy(&r_load_model->colors[color_index], vert->color, sizeof(vec4_t)); color_index += 4; } } }
void PolygonGroup::BuildTangentsBinormals(uint32 flagsToAdd) { if (!(vertexFormat & EVF_TANGENT)) { // Dirty hack. Copy pointers of this polygon group // PolygonGroup * oldGroup = this; // AllocateData(oldGroup->GetVertexFormat() | flagsToAdd, oldGroup->GetVertexCount(), oldGroup->GetIndexCount()); // CopyFrom(oldGroup); // SafeRelease(oldGroup); } for (int v = 0; v < vertexCount; ++v) { //Vector3 * tan0 = (Vector3 *)((uint8 *)normalArray + v * vertexStride); Vector3 * tan1 = (Vector3 *)((uint8 *)tangentArray + v * vertexStride); Vector3 * tan2 = (Vector3 *)((uint8 *)binormalArray + v * vertexStride); //*tan0 = Vector3(0.0f, 0.0f, 0.0f); tan1->x = 0; tan1->y = 0; tan1->z = 0; tan2->x = 0; tan2->y = 0; tan2->z = 0; } for (int t = 0; t < triangleCount; ++t) { int32 i1 = indexArray[t * 3]; int32 i2 = indexArray[t * 3 + 1]; int32 i3 = indexArray[t * 3 + 2]; Vector3 v1 = *(Vector3 *)((uint8 *)vertexArray + i1 * vertexStride); Vector3 v2 = *(Vector3 *)((uint8 *)vertexArray + i2 * vertexStride); Vector3 v3 = *(Vector3 *)((uint8 *)vertexArray + i3 * vertexStride); // use first texture coordinate Vector2 w1 = *(Vector2 *)((uint8 *)textureCoordArray[0] + i1 * vertexStride); Vector2 w2 = *(Vector2 *)((uint8 *)textureCoordArray[0] + i2 * vertexStride); Vector2 w3 = *(Vector2 *)((uint8 *)textureCoordArray[0] + i3 * vertexStride); //float32 x1 = v2.x - v1.x; //float32 x2 = v3.x - v1.x; //float32 y1 = v2.y - v1.y; //float32 y2 = v3.y - v1.y; //float32 z1 = v2.z - v1.z; //float32 z2 = v3.z - v1.z; //float32 s1 = w2.x - w1.x; //float32 s2 = w3.x - w1.x; //float32 t1 = w2.y - w1.y; //float32 t2 = w3.y - w1.y; //float r = 1.0F / (s1 * t2 - s2 * t1); //Vector3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, // (t2 * z1 - t1 * z2) * r); //Vector3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, // (s1 * z2 - s2 * z1) * r); Vector3 sdir, tdir, norm; TangentVectors(v1, v2, v3, w1, w2, w3, sdir, tdir, norm); //Vector3 * nor1 = (Vector3 *)((uint8 *)normalArray + i1 * vertexStride); //Vector3 * nor2 = (Vector3 *)((uint8 *)normalArray + i2 * vertexStride); //Vector3 * nor3 = (Vector3 *)((uint8 *)normalArray + i3 * vertexStride); Vector3 * tan1 = (Vector3 *)((uint8 *)tangentArray + i1 * vertexStride); Vector3 * tan2 = (Vector3 *)((uint8 *)tangentArray + i2 * vertexStride); Vector3 * tan3 = (Vector3 *)((uint8 *)tangentArray + i3 * vertexStride); Vector3 * tan21 = (Vector3 *)((uint8 *)binormalArray + i1 * vertexStride); Vector3 * tan22 = (Vector3 *)((uint8 *)binormalArray + i2 * vertexStride); Vector3 * tan23 = (Vector3 *)((uint8 *)binormalArray + i3 * vertexStride); //*nor1 += norm; //*nor2 += norm; //*nor3 += norm; *tan1 += sdir; *tan2 += sdir; *tan3 += sdir; *tan21 += tdir; *tan22 += tdir; *tan23 += tdir; } for (int v = 0; v < vertexCount; ++v) { Vector3 * nres = (Vector3 *)((uint8 *)normalArray + v * vertexStride); Vector3 * tres = (Vector3 *)((uint8 *)tangentArray + v * vertexStride); Vector3 * bres = (Vector3 *)((uint8 *)binormalArray + v * vertexStride); *bres = -*bres; nres->Normalize(); tres->Normalize(); bres->Normalize(); //Vector3 n = *nres; //Vector3 t = *tres; //Vector3 t2 = *bres; //*tres = (t - DotProduct(n, t) * n); // ////tres->x = -tres->x; ////tres->y = -tres->y; ////tres->z = -tres->z; ////nres->x = -nres->x; ////nres->y = -nres->y; ////nres->z = -nres->z; //tres->Normalize(); // //float32 handedness = (DotProduct(CrossProduct(n, t), t2) < 0.0f) ? (-1.0f) : (1.0f); //if (vertexFormat & EVF_BINORMAL) //{ // *bres = CrossProduct(*tres, *nres); // bres->Normalize(); //} ////*bres = -*bres; //*tres = -*tres; /* BORODA: Removed unused variable Vector3 nrecomp = CrossProduct(*tres, *bres); */ // int xt = 0; // use this method (get from .. http://www.c4engine.com/code/tangent.html); //const Vector3D& n = normal[a]; //const Vector3D& t = tan1[a]; //// Gram-Schmidt orthogonalize // tangent[a] = (t - n * Dot(n, t)).Normalize(); // // // Calculate handedness // tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F; } }
/** * @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 vertOfs, texCoordOfs, tangOfs; 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, indexCount; vertOfs = texCoordOfs = tangOfs = 0; vertexCount = indexCount = 0; for (i = 0, surf = mod->bsp.surfaces; i < mod->bsp.numsurfaces; i++, surf++) { const int numedges = surf->numedges; vertexCount += numedges; if (numedges > 2) /* no triangles for degenerate polys */ indexCount += (numedges - 2) * 3; } surf = mod->bsp.surfaces; /* allocate the vertex arrays */ mod->bsp.texcoords = Mem_PoolAllocTypeN(GLfloat, vertexCount * 2, vid_modelPool); mod->bsp.lmtexcoords = Mem_PoolAllocTypeN(GLfloat, vertexCount * 2, vid_modelPool); mod->bsp.verts = Mem_PoolAllocTypeN(GLfloat, vertexCount * 3, vid_modelPool); mod->bsp.normals = Mem_PoolAllocTypeN(GLfloat, vertexCount * 3, vid_modelPool); mod->bsp.tangents = Mem_PoolAllocTypeN(GLfloat, vertexCount * 4, vid_modelPool); mod->bsp.indexes = Mem_PoolAllocTypeN(GLint, indexCount, vid_modelPool); /* Will be filled at the end of map loading, after building surface lists */ for (i = 0; i < mod->bsp.numsurfaces; i++, surf++) { surf->index = vertOfs / 3; surf->firstTriangle = -1; /* Mark as "no triangles generated yet" */ 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[vertOfs]; /* 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[texCoordOfs + 0] = s; mod->bsp.texcoords[texCoordOfs + 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[texCoordOfs + 0] = s; mod->bsp.lmtexcoords[texCoordOfs + 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[vertOfs], normal, sizeof(vec3_t)); /* tangent vector */ TangentVectors(normal, sdir, tdir, tangent, binormal); memcpy(&mod->bsp.tangents[tangOfs], tangent, sizeof(vec4_t)); vertOfs += 3; texCoordOfs += 2; tangOfs += 4; } } R_ReallocateStateArrays(vertOfs / 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, vertOfs * 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, texCoordOfs * 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, texCoordOfs * 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, vertOfs * 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, tangOfs * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW); qglBindBuffer(GL_ARRAY_BUFFER, 0); } }
/** * @brief * @sa FinalLightFace */ void BuildFacelights (unsigned int facenum) { dBspSurface_t* face; dBspPlane_t* plane; dBspTexinfo_t* tex; float* center; float* sdir, *tdir; vec3_t normal, binormal; vec4_t tangent; lightinfo_t li; float scale; int i, j, numsamples; facelight_t* fl; int* headhints; const int grid_type = config.soft ? 1 : 0; if (facenum >= MAX_MAP_FACES) { Com_Printf("MAX_MAP_FACES hit\n"); return; } face = &curTile->faces[facenum]; plane = &curTile->planes[face->planenum]; tex = &curTile->texinfo[face->texinfo]; if (tex->surfaceFlags & SURF_WARP) return; /* non-lit texture */ sdir = tex->vecs[0]; tdir = tex->vecs[1]; /* lighting -extra antialiasing */ if (config.extrasamples) numsamples = config.soft ? SOFT_SAMPLES : MAX_SAMPLES; else numsamples = 1; OBJZERO(li); scale = 1.0 / numsamples; /* each sample contributes this much */ li.face = face; li.facedist = plane->dist; VectorCopy(plane->normal, li.facenormal); /* negate the normal and dist */ if (face->side) { VectorNegate(li.facenormal, li.facenormal); li.facedist = -li.facedist; } /* get the origin offset for rotating bmodels */ VectorCopy(face_offset[facenum], li.modelorg); /* calculate lightmap texture mins and maxs */ CalcLightinfoExtents(&li); /* and the lightmap texture vectors */ CalcLightinfoVectors(&li); /* now generate all of the sample points */ CalcPoints(&li, 0, 0); fl = &facelight[config.compile_for_day][facenum]; fl->numsamples = li.numsurfpt; fl->samples = Mem_AllocTypeN(vec3_t, fl->numsamples); fl->directions = Mem_AllocTypeN(vec3_t, fl->numsamples); center = face_extents[facenum].center; /* center of the face */ /* Also setup the hints. Each hint is specific to each light source, including sunlight. */ headhints = Mem_AllocTypeN(int, (numlights[config.compile_for_day] + 1)); /* calculate light for each sample */ for (i = 0; i < fl->numsamples; i++) { float* const sample = fl->samples[i]; /* accumulate lighting here */ float* const direction = fl->directions[i]; /* accumulate direction here */ if (tex->surfaceFlags & SURF_PHONG) /* interpolated normal */ SampleNormal(&li, li.surfpt[i], normal); else /* or just plane normal */ VectorCopy(li.facenormal, normal); for (j = 0; j < numsamples; j++) { /* with antialiasing */ vec3_t pos; /* add offset for supersampling */ VectorMA(li.surfpt[i], sampleofs[grid_type][j][0] * li.step, li.textoworld[0], pos); VectorMA(pos, sampleofs[grid_type][j][1] * li.step, li.textoworld[1], pos); NudgeSamplePosition(pos, normal, center, pos); GatherSampleLight(pos, normal, sample, direction, scale, headhints); } if (VectorNotEmpty(direction)) { vec3_t dir; /* normalize it */ VectorNormalize(direction); /* finalize the lighting direction for the sample */ TangentVectors(normal, sdir, tdir, tangent, binormal); dir[0] = DotProduct(direction, tangent); dir[1] = DotProduct(direction, binormal); dir[2] = DotProduct(direction, normal); VectorCopy(dir, direction); } } /* Free the hints. */ Mem_Free(headhints); for (i = 0; i < fl->numsamples; i++) { /* pad them */ float* const direction = fl->directions[i]; if (VectorEmpty(direction)) VectorSet(direction, 0.0, 0.0, 1.0); } /* free the sample positions for the face */ Mem_Free(li.surfpt); }
/* * @brief Writes vertex data for the given surface to the load model's arrays. * * @param count The current vertex count for the load model. */ static void R_LoadBspVertexArrays_Surface(r_model_t *mod, r_bsp_surface_t *surf, GLuint *count) { uint16_t i; surf->index = *count; for (i = 0; i < surf->num_edges; i++) { const int32_t index = mod->bsp->surface_edges[surf->first_edge + i]; const r_bsp_edge_t *edge; r_bsp_vertex_t *vert; // vertex if (index > 0) { // negative indices to differentiate which end of the edge edge = &mod->bsp->edges[index]; vert = &mod->bsp->vertexes[edge->v[0]]; } else { edge = &mod->bsp->edges[-index]; vert = &mod->bsp->vertexes[edge->v[1]]; } memcpy(&mod->verts[(*count) * 3], vert->position, sizeof(vec3_t)); // texture directional vectors and offsets const vec_t *sdir = surf->texinfo->vecs[0]; const vec_t soff = surf->texinfo->vecs[0][3]; const vec_t *tdir = surf->texinfo->vecs[1]; const vec_t toff = surf->texinfo->vecs[1][3]; // texture coordinates vec_t s = DotProduct(vert->position, sdir) + soff; s /= surf->texinfo->material->diffuse->width; vec_t t = DotProduct(vert->position, tdir) + toff; t /= surf->texinfo->material->diffuse->height; mod->texcoords[(*count) * 2 + 0] = s; mod->texcoords[(*count) * 2 + 1] = t; // lightmap texture coordinates if (surf->flags & R_SURF_LIGHTMAP) { s = DotProduct(vert->position, sdir) + soff; s -= surf->st_mins[0]; s += surf->light_s * mod->bsp->lightmaps->scale; s += mod->bsp->lightmaps->scale / 2.0; s /= surf->lightmap->width * mod->bsp->lightmaps->scale; t = DotProduct(vert->position, tdir) + toff; t -= surf->st_mins[1]; t += surf->light_t * mod->bsp->lightmaps->scale; t += mod->bsp->lightmaps->scale / 2.0; t /= surf->lightmap->height * mod->bsp->lightmaps->scale; } mod->lightmap_texcoords[(*count) * 2 + 0] = s; mod->lightmap_texcoords[(*count) * 2 + 1] = t; // normal vector, which is per-vertex for SURF_PHONG const vec_t *normal; if ((surf->texinfo->flags & SURF_PHONG) && !VectorCompare(vert->normal, vec3_origin)) normal = vert->normal; else normal = surf->normal; memcpy(&mod->normals[(*count) * 3], normal, sizeof(vec3_t)); // tangent vectors vec4_t tangent; vec3_t bitangent; TangentVectors(normal, sdir, tdir, tangent, bitangent); memcpy(&mod->tangents[(*count) * 4], tangent, sizeof(vec4_t)); (*count)++; } }