/* * @brief Register event listener for models. */ static void R_RegisterModel(r_media_t *self) { r_model_t *mod = (r_model_t *) self; if (mod->type == MOD_BSP) { uint16_t i; const r_bsp_texinfo_t *t = mod->bsp->texinfo; for (i = 0; i < mod->bsp->num_texinfo; i++, t++) { R_RegisterDependency(self, (r_media_t *) t->material); } const r_bsp_surface_t *s = mod->bsp->surfaces; for (i = 0; i < mod->bsp->num_surfaces; i++, s++) { R_RegisterDependency(self, (r_media_t *) s->lightmap); R_RegisterDependency(self, (r_media_t *) s->deluxemap); } // keep a reference to the world model r_model_state.world = mod; } else if (IS_MESH_MODEL(mod)) { R_RegisterDependency(self, (r_media_t *) mod->mesh->material); } }
/** * @brief Performs a frustum-cull of all entities. This is performed in a separate * thread while the renderer draws the world. Mesh entities which pass a frustum * cull will also have their lighting information updated. */ void R_CullEntities(void) { r_entity_t *e = r_view.entities; for (uint16_t i = 0; i < r_view.num_entities; i++, e++) { r_entities_t *ents = &r_sorted_entities.null_entities; if (IS_BSP_INLINE_MODEL(e->model)) { if (R_CullBspInlineModel(e)) { continue; } ents = &r_sorted_entities.bsp_inline_entities; } else if (IS_MESH_MODEL(e->model)) { if (R_CullMeshModel(e)) { continue; } R_UpdateMeshModelLighting(e); ents = &r_sorted_entities.mesh_entities; } R_ENTITY_TO_ENTITIES(ents, e); // append to the appropriate draw list R_SetMatrixForEntity(e); // set the transform matrix } // sort the mesh entities list by model to allow object instancing r_entities_t *mesh = &r_sorted_entities.mesh_entities; qsort(mesh, mesh->count, sizeof(r_entity_t *), R_CullEntities_compare); }
/** * @brief Applies any configuration and tag alignment, populating the model-view * matrix for the entity in the process. */ void R_SetMatrixForEntity(r_entity_t *e) { if (e->parent) { vec3_t forward; if (!IS_MESH_MODEL(e->model)) { Com_Warn("Invalid model for linked entity\n"); return; } const r_entity_t *p = e->parent; while (p->parent) { p = p->parent; } AngleVectors(p->angles, forward, NULL, NULL); VectorClear(e->origin); VectorClear(e->angles); Matrix4x4_CreateFromEntity(&e->matrix, e->origin, e->angles, e->scale); R_ApplyMeshModelTag(e); R_ApplyMeshModelConfig(e); Matrix4x4_Invert_Simple(&e->inverse_matrix, &e->matrix); Matrix4x4_Transform(&e->matrix, vec3_origin, e->origin); Matrix4x4_Transform(&e->matrix, vec3_forward, forward); VectorAngles(forward, e->angles); return; } Matrix4x4_CreateFromEntity(&e->matrix, e->origin, e->angles, e->scale); if (IS_MESH_MODEL(e->model)) { R_ApplyMeshModelConfig(e); } Matrix4x4_Invert_Simple(&e->inverse_matrix, &e->matrix); }
/* * @brief Allocates and populates static VBO's for the specified r_model_t. */ static void R_LoadVertexBuffers(r_model_t *mod) { if (!qglGenBuffers) return; if (IS_MESH_MODEL(mod) && mod->mesh->num_frames > 1) // animated models don't use VBO return; const GLsizei v = mod->num_verts * 3 * sizeof(GLfloat); const GLsizei st = mod->num_verts * 2 * sizeof(GLfloat); const GLsizei t = mod->num_verts * 4 * sizeof(GLfloat); // load the vertex buffer objects qglGenBuffers(1, &mod->vertex_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->vertex_buffer); qglBufferData(GL_ARRAY_BUFFER, v, mod->verts, GL_STATIC_DRAW); qglGenBuffers(1, &mod->texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, st, mod->texcoords, GL_STATIC_DRAW); qglGenBuffers(1, &mod->normal_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->normal_buffer); qglBufferData(GL_ARRAY_BUFFER, v, mod->normals, GL_STATIC_DRAW); qglGenBuffers(1, &mod->tangent_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->tangent_buffer); qglBufferData(GL_ARRAY_BUFFER, t, mod->tangents, GL_STATIC_DRAW); if (mod->lightmap_texcoords) { qglGenBuffers(1, &mod->lightmap_texcoord_buffer); qglBindBuffer(GL_ARRAY_BUFFER, mod->lightmap_texcoord_buffer); qglBufferData(GL_ARRAY_BUFFER, st, mod->lightmap_texcoords, GL_STATIC_DRAW); } qglBindBuffer(GL_ARRAY_BUFFER, 0); R_GetError(mod->media.name); }
/** * @brief Draws bounding boxes for all non-linked entities in `ents`. */ static void R_DrawEntityBounds(const r_entities_t *ents, const vec4_t color) { if (!r_draw_entity_bounds->value) { return; } if (ents->count == 0) { return; } R_BindDiffuseTexture(r_image_state.null->texnum); R_EnableColorArray(true); R_BindAttributeInterleaveBuffer(&r_model_state.bound_vertice_buffer, R_ARRAY_MASK_ALL); R_BindAttributeBuffer(R_ARRAY_ELEMENTS, &r_model_state.bound_element_buffer); u8vec4_t bc; ColorDecompose(color, bc); for (int32_t i = 0; i < 8; ++i) { Vector4Set(r_model_state.bound_vertices[i].color, bc[0], bc[1], bc[2], bc[3]); } static matrix4x4_t mat, modelview; R_GetMatrix(R_MATRIX_MODELVIEW, &modelview); for (size_t i = 0; i < ents->count; i++) { const r_entity_t *e = ents->entities[i]; if (e->parent || (e->effects & EF_WEAPON) || !IS_MESH_MODEL(e->model)) { continue; } VectorSet(r_model_state.bound_vertices[0].position, e->mins[0], e->mins[1], e->mins[2]); VectorSet(r_model_state.bound_vertices[1].position, e->maxs[0], e->mins[1], e->mins[2]); VectorSet(r_model_state.bound_vertices[2].position, e->maxs[0], e->maxs[1], e->mins[2]); VectorSet(r_model_state.bound_vertices[3].position, e->mins[0], e->maxs[1], e->mins[2]); VectorSet(r_model_state.bound_vertices[4].position, e->mins[0], e->mins[1], e->maxs[2]); VectorSet(r_model_state.bound_vertices[5].position, e->maxs[0], e->mins[1], e->maxs[2]); VectorSet(r_model_state.bound_vertices[6].position, e->maxs[0], e->maxs[1], e->maxs[2]); VectorSet(r_model_state.bound_vertices[7].position, e->mins[0], e->maxs[1], e->maxs[2]); R_UploadToBuffer(&r_model_state.bound_vertice_buffer, sizeof(r_bound_interleave_vertex_t) * 8, r_model_state.bound_vertices); // draw box const vec_t *origin; if (e->effects & EF_BOB) { origin = e->termination; } else { origin = e->origin; } Matrix4x4_CreateFromEntity(&mat, origin, vec3_origin, e->scale); Matrix4x4_Concat(&mat, &modelview, &mat); R_SetMatrix(R_MATRIX_MODELVIEW, &mat); R_DrawArrays(GL_LINES, 0, (GLint) r_model_state.bound_element_count - 6); // draw origin Matrix4x4_CreateFromEntity(&mat, origin, e->angles, e->scale); Matrix4x4_Concat(&mat, &modelview, &mat); R_SetMatrix(R_MATRIX_MODELVIEW, &mat); R_DrawArrays(GL_LINES, (GLint) r_model_state.bound_element_count - 6, 6); } R_SetMatrix(R_MATRIX_MODELVIEW, &modelview); R_UnbindAttributeBuffer(R_ARRAY_ELEMENTS); R_EnableColorArray(false); R_Color(NULL); }