/* * @brief Uploads the specified image to the OpenGL implementation. Images that * do not have a GL texture reserved (which is most diffuse textures) will have * one generated for them. This flexibility allows for explicitly managed * textures (such as lightmaps) to be here as well. */ void R_UploadImage(r_image_t *image, GLenum format, byte *data) { if (!image || !data) { Com_Error(ERR_DROP, "NULL image or data\n"); } if (!image->texnum) { glGenTextures(1, &(image->texnum)); } R_BindTexture(image->texnum); if (image->type & IT_MASK_MIPMAP) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_image_state.filter_min); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_image_state.filter_mag); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, r_image_state.anisotropy); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_image_state.filter_mag); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_image_state.filter_mag); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); } glTexImage2D(GL_TEXTURE_2D, 0, format, image->width, image->height, 0, format, GL_UNSIGNED_BYTE, data); R_RegisterMedia((r_media_t *) image); R_GetError(image->media.name); }
/* * @brief Resolves the specified media if it is already known. The returned * media is re-registered for convenience. * * @return r_media_t The media, or NULL. */ r_media_t *R_FindMedia(const char *name) { r_media_t *media; if ((media = g_hash_table_lookup(r_media_state.media, name))) { R_RegisterMedia(media); } return media; }
/* * @brief Establishes a dependency from the specified dependent to the given * dependency. Dependencies in use by registered media are never freed. */ void R_RegisterDependency(r_media_t *dependent, r_media_t *dependency) { if (dependent) { if (dependency) { if (!g_list_find(dependent->dependencies, dependency)) { Com_Debug("%s -> %s\n", dependent->name, dependency->name); dependent->dependencies = g_list_prepend(dependent->dependencies, dependency); R_RegisterMedia(dependency); } } else { // Com_Debug("Invalid dependency for %s\n", dependent->name); } } else { Com_Warn("Invalid dependent\n"); } }
/* * @brief Inserts the specified media into the shared table, re-registering all * of its dependencies as well. */ void R_RegisterMedia(r_media_t *media) { // check to see if we're already seeded if (media->seed != r_media_state.seed) { r_media_t *m; if ((m = g_hash_table_lookup(r_media_state.media, media->name))) { if (m != media) { // the old instance will eventually be freed Com_Debug("Replacing %s\n", media->name); R_FreeMedia_(NULL, m, m); g_hash_table_replace(r_media_state.media, media->name, media); } else { Com_Debug("Retaining %s\n", media->name); } } else { Com_Debug("Inserting %s\n", media->name); g_hash_table_insert(r_media_state.media, media->name, media); } r_media_state.keys = g_list_insert_sorted(r_media_state.keys, media->name, R_RegisterMedia_Compare); // re-seed the media to retain it media->seed = r_media_state.seed; } // call the implementation-specific register function if (media->Register) { media->Register(media); } // and finally re-register all dependencies GList *d = media->dependencies; while (d) { R_RegisterMedia((r_media_t *) d->data); d = d->next; } }
/* * @brief Loads the model by the specified name. */ r_model_t *R_LoadModel(const char *name) { r_model_t *mod; char key[MAX_QPATH]; size_t i; if (!name || !name[0]) { Com_Error(ERR_DROP, "R_LoadModel: NULL name\n"); } if (*name == '*') { g_snprintf(key, sizeof(key), "%s#%s", r_model_state.world->media.name, name + 1); } else { StripExtension(name, key); } if (!(mod = (r_model_t *) R_FindMedia(key))) { void *buf; const r_model_format_t *format = r_model_formats; for (i = 0; i < lengthof(r_model_formats); i++, format++) { StripExtension(name, key); strcat(key, format->extension); if (Fs_Load(key, &buf) != -1) break; } if (i == lengthof(r_model_formats)) { // not found if (strstr(name, "players/")) { Com_Debug("Failed to load player %s\n", name); } else { Com_Warn("Failed to load %s\n", name); } return NULL; } StripExtension(name, key); mod = (r_model_t *) R_AllocMedia(key, sizeof(r_model_t)); mod->media.Register = R_RegisterModel; mod->media.Free = R_FreeModel; mod->type = format->type; // load the materials first, so that we can resolve surfaces lists R_LoadMaterials(mod); // load it format->Load(mod, buf); // free the file Fs_Free(buf); // assemble vertex buffer objects from static arrays R_LoadVertexBuffers(mod); // calculate an approximate radius from the bounding box vec3_t tmp; VectorSubtract(mod->maxs, mod->mins, tmp); mod->radius = VectorLength(tmp) / 2.0; R_RegisterMedia((r_media_t *) mod); } return mod; }