/** * CommanderDJ - Parse a list of sounds. When using this function for a table entry, * required_string and optional_string aren't needed, as this function deals with * that as its tag parameter, just make sure that the destination sound index(es) can * handle -1 if things don't work out. * * @param destination Vector where sound indexes are to be stored * @param tag Tag * @param object_name Name of object being parsed * @param flags See the parse_sound_flags enum * */ void parse_sound_list(const char* tag, SCP_vector<int>& destination, const char* object_name, parse_sound_flags flags) { if(optional_string(tag)) { int check=0; //if we're using the old format, parse the first entry separately if(!(flags & PARSE_SOUND_SCP_SOUND_LIST)) { stuff_int(&check); } //now read the rest of the entries on the line for(size_t i=0; !check_for_eoln(); i++) { char buf[MAX_FILENAME_LEN]; stuff_string_white(buf, MAX_FILENAME_LEN); //we do this conditionally to avoid adding needless entries when reparsing if(destination.size() <= i) { destination.push_back(-1); } parse_sound_core(tag, &destination.at(i), object_name, buf, flags); } //if we're using the old format, double check the size) if(!(flags & PARSE_SOUND_SCP_SOUND_LIST) && (destination.size() != (unsigned)check)) { mprintf(("%s in '%s' has " SIZE_T_ARG " entries. This does not match entered size of %i.", tag, object_name, destination.size(), check)); } } }
/** * Compiles a new shader, and creates an opengl_shader_t that will be put into the GL_shader vector * if compilation is successful. * * @param sdr Identifier defined with the program we wish to compile * @param flags Combination of SDR_* flags * @param replacement_idx The index of the shader this replaces. If -1, the newly compiled shader will be appended to the GL_shader vector * or inserted at the first available empty slot */ int opengl_compile_shader(shader_type sdr, uint flags) { GR_DEBUG_SCOPE("Creating new shader"); int sdr_index = -1; int empty_idx; opengl_shader_t new_shader; Assert(sdr < NUM_SHADER_TYPES); opengl_compile_shader_actual(sdr, flags, new_shader); opengl_shader_set_current(); // add it to our list of embedded shaders // see if we have empty shader slots empty_idx = -1; for (int i = 0; i < (int)GL_shader.size(); ++i) { if (GL_shader[i].shader == NUM_SHADER_TYPES) { empty_idx = i; break; } } // then insert it at an empty slot or at the end if ( empty_idx >= 0 ) { GL_shader[empty_idx] = std::move(new_shader); sdr_index = empty_idx; } else { sdr_index = (int)GL_shader.size(); GL_shader.push_back(std::move(new_shader)); } return sdr_index; }
int gamesnd_get_by_iface_name(const char* name) { Assert( Snds_iface.size() <= INT_MAX ); Assert( Snds_iface.size() == Snds_iface_handle.size() ); int index = gamesnd_lookup_name(name, Snds_iface); if (index < 0) { int i = 0; for(SCP_vector<game_snd>::iterator snd = Snds_iface.begin(); snd != Snds_iface.end(); ++snd) { char *p = strrchr( snd->filename, '.' ); if(p == NULL) { if(!stricmp(snd->filename, name)) { index = i; break; } } else if(!strnicmp(snd->filename, name, p-snd->filename)) { index = i; break; } i++; } } return index; }
void outwnd_print(const char *id, const char *tmp) { uint i; if ( (id == NULL) || (tmp == NULL) ) return; if ( !outwnd_inited ) { fputs("outwnd not initialized yet... \n", stdout); fputs(tmp, stdout); fflush(stdout); return; } if (Outwnd_no_filter_file == 1) { Outwnd_no_filter_file = 2; outwnd_print( "general", "==========================================================================\n" ); outwnd_print( "general", "DEBUG SPEW: No debug_filter.cfg found, so only general, error, and warning\n" ); outwnd_print( "general", "categories can be shown and no debug_filter.cfg info will be saved.\n" ); outwnd_print( "general", "==========================================================================\n" ); } for (i = 0; i < OutwndFilter.size(); i++) { if ( !stricmp(id, OutwndFilter[i].name) ) break; } // id found that isn't in the filter list yet if ( i == OutwndFilter.size() ) { // Only create new filters if there was a filter file if (Outwnd_no_filter_file) return; Assert( strlen(id)+1 < NAME_LENGTH ); outwnd_filter_struct new_filter; strcpy_s(new_filter.name, id); new_filter.enabled = true; OutwndFilter.push_back( new_filter ); save_filter_info(); } if ( !OutwndFilter[i].enabled ) return; if (Log_debug_output_to_file) { if (Log_fp != NULL) { fputs(tmp, Log_fp); fflush(Log_fp); } } else { fputs(tmp, stdout); fflush(stdout); } }
int gamesnd_get_by_iface_tbl_index(int index) { Assert( Snds_iface.size() == Snds_iface_handle.size() ); char temp[11]; sprintf(temp, "%i", index); return gamesnd_lookup_name(temp, Snds_iface); }
void obj_find_overlap_colliders(SCP_vector<int> *overlap_list_out, SCP_vector<int> *list, int axis, bool collide) { size_t i, j; bool overlapped; bool first_not_added = true; SCP_vector<int> overlappers; float min; float max; float overlap_min; float overlap_max; overlappers.clear(); for ( i = 0; i < (*list).size(); ++i ) { overlapped = false; min = obj_get_collider_endpoint((*list)[i], axis, true); max = obj_get_collider_endpoint((*list)[i], axis, false); for ( j = 0; j < overlappers.size(); ) { overlap_min = obj_get_collider_endpoint(overlappers[j], axis, true); overlap_max = obj_get_collider_endpoint(overlappers[j], axis, false); if ( min <= overlap_max ) { overlapped = true; if ( overlappers.size() == 1 && first_not_added ) { first_not_added = false; overlap_list_out->push_back(overlappers[j]); } if ( collide ) { obj_collide_pair(&Objects[(*list)[i]], &Objects[overlappers[j]]); } } else { overlappers[j] = overlappers.back(); overlappers.pop_back(); continue; } ++j; } if ( overlappers.size() == 0 ) { first_not_added = true; } if ( overlapped ) { overlap_list_out->push_back((*list)[i]); } overlappers.push_back((*list)[i]); } overlapped = true; }
size_t opengl_get_shader_idx(shader_type shader_t, unsigned int flags) { for (size_t idx = 0; idx < GL_shader.size(); idx++) { if (GL_shader[idx].shader == shader_t && GL_shader[idx].flags == flags) { return idx; } } return GL_shader.size(); }
static void cache_program_binary(GLuint program, const SCP_string& hash) { if (!do_shader_caching()) { return; } GR_DEBUG_SCOPE("Saving shader binary"); GLint size; glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &size); if (size <= 0) { // No binary available (I'm looking at you Mesa...) return; } SCP_vector<uint8_t> binary; binary.resize((size_t) size); GLenum binary_fmt; GLsizei length; glGetProgramBinary(program, (GLsizei) binary.size(), &length, &binary_fmt, binary.data()); if (length == 0) { return; } auto base_filename = SCP_string("ogl_shader-") + hash; auto metadata_name = base_filename + ".json"; auto binary_name = base_filename + ".bin"; auto metadata_fp = cfopen(metadata_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!metadata_fp) { mprintf(("Could not open shader cache metadata file!\n")); return; } auto metadata = json_pack("{sI}", "format", (json_int_t)binary_fmt); if (json_dump_callback(metadata, json_write_callback, metadata_fp, 0) != 0) { mprintf(("Failed to write shader cache metadata file!\n")); cfclose(metadata_fp); return; } cfclose(metadata_fp); json_decref(metadata); auto binary_fp = cfopen(binary_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE, false, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT); if (!binary_fp) { mprintf(("Could not open shader cache binary file!\n")); return; } cfwrite(binary.data(), 1, (int) binary.size(), binary_fp); cfclose(binary_fp); }
/** * Call to load a shockwave, or add it and then load it */ int shockwave_load(char *s_name, bool shock_3D) { size_t i; int s_index = -1; shockwave_info *si = NULL; Assert( s_name ); // make sure that this is, or should be, valid if ( !VALID_FNAME(s_name) ) return -1; for (i = 0; i < Shockwave_info.size(); i++) { if ( !stricmp(Shockwave_info[i].filename, s_name) ) { s_index = i; break; } } if (s_index < 0) { shockwave_info si_tmp; strcpy_s(si_tmp.filename, s_name); Shockwave_info.push_back( si_tmp ); s_index = (int)(Shockwave_info.size() - 1); } Assert( s_index >= 0 ); si = &Shockwave_info[s_index]; // make sure to only try loading the shockwave once if ( (si->bitmap_id >= 0) || (si->model_id >= 0) ) return s_index; if (shock_3D) { si->model_id = model_load( si->filename, 0, NULL ); if ( si->model_id < 0 ) { Shockwave_info.pop_back(); return -1; } } else { si->bitmap_id = bm_load_animation( si->filename, &si->num_frames, &si->fps, NULL, 1 ); if ( si->bitmap_id < 0 ) { Shockwave_info.pop_back(); return -1; } } return s_index; }
// Try to find a match between filename and the names inside // of Hud_shield_filenames. This will provide us with an // association of ship class to shield icon information. void hud_shield_assign_info(ship_info *sip, char *filename) { ubyte i; for ( i = 0; i < (ubyte)Hud_shield_filenames.size(); i++ ) { if ( !stricmp(filename, Hud_shield_filenames.at(i).c_str()) ) { sip->shield_icon_index = i; return; } } //No HUD icon found. Add one! sip->shield_icon_index = (unsigned char) Hud_shield_filenames.size(); Hud_shield_filenames.push_back((SCP_string)filename); }
void cutscenes_screen_play() { char name[MAX_FILENAME_LEN]; // *full_name int which_cutscene; Assert( (Selected_line >= 0) && (Selected_line < (int)Cutscene_list.size()) ); which_cutscene = Cutscene_list[Selected_line]; strcpy_s(name, Cutscenes[which_cutscene].filename ); // full_name = cf_add_ext(name, NOX(".mve")); main_hall_stop_music(); main_hall_stop_ambient(); int rval = movie_play(name); main_hall_start_music(); if ( !rval ) { char str[256]; if (Cmdline_nomovies) strcpy_s(str, XSTR("Movies are currently disabled.", 1574)); else sprintf(str, XSTR("Unable to play movie %s.", 204), Cutscenes[which_cutscene].name); popup(0, 1, POPUP_OK, str ); } }
static bool printNextDebugMessage() { if (!hasPendingDebugMessage()) { return false; } GLint msgLen = 0; glGetIntegerv(GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB, &msgLen); SCP_vector<GLchar> msg; msg.resize(msgLen + 1); // Includes null character, needs to be removed later GLenum source; GLenum type; GLenum severity; GLuint id; GLsizei length; GLuint numFound = glGetDebugMessageLogARB(1, static_cast<GLsizei>(msg.size()), &source, &type, &id, &severity, &length, &msg[0]); if (numFound < 1) { return false; } debug_callback(source, type, id, severity, length, msg.data(), nullptr); return true; }
ubyte lcl_get_font_index(int font_num) { Assertion((font_num >= 0) && (font_num < LCL_MAX_FONTS), "Passed an invalid font index"); Assertion((Lcl_current_lang >= 0) && (Lcl_current_lang < (int)Lcl_languages.size()), "Current language is not valid, can't get font indexes"); return Lcl_languages[Lcl_current_lang].special_char_indexes[font_num]; }
/** * Builds the output text. */ void profile_dump_output() { if (Cmdline_frame_profile) { end_profile_time = timer_get_microseconds(); if (Cmdline_profile_write_file) { profiling_file << end_profile_time << ";" << (end_profile_time - start_profile_time) << std::endl; } profile_output.clear(); profile_output += " Avg : Min : Max : # : Profile Name\n"; profile_output += "----------------------------------------\n"; for(int i = 0; i < (int)samples.size(); i++) { uint64_t sample_time; float percent_time, avg_time, min_time, max_time; uint64_t avg_micro_seconds, min_micro_seconds, max_micro_seconds; Assert(samples[i].open_profiles == 0); sample_time = samples[i].accumulator - samples[i].children_sample_time; if (end_profile_time == start_profile_time) { percent_time = 0.0f; } else { percent_time = (i2fl(sample_time) / i2fl(end_profile_time - start_profile_time)) *100.0f; } avg_micro_seconds = min_micro_seconds = max_micro_seconds = sample_time; avg_time = min_time = max_time = percent_time; // add new measurement into the history and get avg, min, and max store_profile_in_history(samples[i].name, percent_time, sample_time); get_profile_from_history(samples[i].name, &avg_time, &min_time, &max_time, &avg_micro_seconds, &min_micro_seconds, &max_micro_seconds); // format the data char avg[64], min[64], max[64], num[64]; sprintf(avg, "%3.1f%% (%3.1fms)", avg_time, i2fl(avg_micro_seconds)*0.001f); sprintf(min, "%3.1f%% (%3.1fms)", min_time, i2fl(min_micro_seconds)*0.001f); sprintf(max, "%3.1f%% (%3.1fms)", max_time, i2fl(max_micro_seconds)*0.001f); sprintf(num, "%3d", samples[i].profile_instances); SCP_string indented_name(samples[i].name); for(uint indent = 0; indent < samples[i].num_parents; indent++) { indented_name = ">" + indented_name; } char line[256]; sprintf(line, "%5s : %5s : %5s : %3s : ", avg, min, max, num); profile_output += line + indented_name + "\n"; } samples.clear(); start_profile_time = timer_get_microseconds(); } }
camid cam_get_camera(uint idx) { if(idx >= Cameras.size()) return camid(); return camid(idx, Cameras[idx]->get_signature()); }
camid cam_create(char *n_name, vec3d *n_pos, matrix *n_ori, object *n_object, int n_object_host_submodel) { camera *cam = NULL; camid cid; //Get signature int sig = cam_get_next_sig(); //Get name char buf[NAME_LENGTH] = {'\0'}; if(n_name == NULL) sprintf(buf, "Camera %d", cid.getSignature()); else strncpy(buf, n_name, NAME_LENGTH-1); //Find a free slot cam = new camera(buf, sig); cid = camid(Cameras.size(), sig); Cameras.push_back(cam); //Set attributes if(n_pos != NULL) cam->set_position(n_pos); if(n_ori != NULL) cam->set_rotation(n_ori); if(n_object != NULL) cam->set_object_host(n_object, n_object_host_submodel); return cid; }
void opengl_bind_buffer_object(int handle) { GR_DEBUG_SCOPE("Bind buffer handle"); Assert(handle >= 0); Assert((size_t)handle < GL_buffer_objects.size()); opengl_buffer_object &buffer_obj = GL_buffer_objects[handle]; switch ( buffer_obj.type ) { case GL_ARRAY_BUFFER: GL_state.Array.BindArrayBuffer(buffer_obj.buffer_id); break; case GL_ELEMENT_ARRAY_BUFFER: GL_state.Array.BindElementBuffer(buffer_obj.buffer_id); break; case GL_TEXTURE_BUFFER: GL_state.Array.BindTextureBuffer(buffer_obj.buffer_id); break; case GL_UNIFORM_BUFFER: GL_state.Array.BindUniformBuffer(buffer_obj.buffer_id); break; default: Int3(); return; break; } }
void snd_spew_info() { size_t idx; char txt[512] = ""; CFILE *out = cfopen("sounds.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA); if(out == NULL){ return; } cfwrite_string("Sounds loaded :\n", out); // spew info for all sounds for (idx = 0; idx < Sounds.size(); idx++) { if(!(Sounds[idx].flags & SND_F_USED)){ continue; } sprintf(txt, "%s (%ds)\n", Sounds[idx].filename, Sounds[idx].info.duration); cfwrite_string(txt, out); } // close the outfile if(out != NULL){ cfclose(out); out = NULL; } }
bool opengl_post_init_shaders() { int idx; int flags = 0; // figure out which flags we need for the main post process shader for (idx = 0; idx < (int)Post_effects.size(); idx++) { if (Post_effects[idx].always_on) { flags |= (1 << idx); } } if ( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_MAIN, flags) < 0 ) { // only the main shader is actually required for post-processing return false; } if ( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_BRIGHTPASS, 0) < 0 || gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_BLUR, SDR_FLAG_BLUR_HORIZONTAL) < 0 || gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_BLUR, SDR_FLAG_BLUR_VERTICAL) < 0 || gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_BLOOM_COMP, 0) < 0) { // disable bloom if we don't have those shaders available Cmdline_bloom_intensity = 0; } if ( gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA, 0) < 0 || gr_opengl_maybe_create_shader(SDR_TYPE_POST_PROCESS_FXAA_PREPASS, 0) < 0 ) { Cmdline_fxaa = false; fxaa_unavailable = true; mprintf(("Error while compiling FXAA shaders. FXAA will be unavailable.\n")); } return true; }
// called at beginning of level to page in all ship icons // used in this level void hud_ship_icon_page_in(ship_info *sip) { hud_frames *sgp; if ( sip->shield_icon_index == 255 ) { return; } // load in shield frames if not already loaded Assert(sip->shield_icon_index < (ubyte)Hud_shield_filenames.size()); sgp = &Shield_gauges.at(sip->shield_icon_index); if ( sgp->first_frame == -1 ) { sgp->first_frame = bm_load_animation(Hud_shield_filenames.at(sip->shield_icon_index).c_str(), &sgp->num_frames); if ( sgp->first_frame == -1 ) { Warning(LOCATION, "Could not load in the HUD shield ani: %s\n", Hud_shield_filenames.at(sip->shield_icon_index).c_str()); return; } } int i; for (i=0; i<sgp->num_frames; i++ ) { bm_page_in_aabitmap(sgp->first_frame+i, 1); } }
void waypoint_add_list(const char *name, SCP_vector<vec3d> &vec_list) { Assert(name != NULL); if (find_matching_waypoint_list(name) != NULL) { Warning(LOCATION, "Waypoint list '%s' already exists in this mission! Not adding the new list...", name); return; } waypoint_list new_list(name); Waypoint_lists.push_back(new_list); waypoint_list *wp_list = &Waypoint_lists.back(); wp_list->get_waypoints().reserve(vec_list.size()); SCP_vector<vec3d>::iterator ii; for (ii = vec_list.begin(); ii != vec_list.end(); ++ii) { waypoint new_waypoint(&(*ii), wp_list); wp_list->get_waypoints().push_back(new_waypoint); } // so that masking in the other function works // though if you actually hit this Assert, you have other problems Assert(wp_list->get_waypoints().size() <= 0xffff); }
void obj_sort_and_collide() { if (Cmdline_dis_collisions) return; if ( !(Game_detail_flags & DETAIL_FLAG_COLLISION) ) return; SCP_vector<int> sort_list_y; SCP_vector<int> sort_list_z; sort_list_y.clear(); { TRACE_SCOPE(tracing::SortColliders); obj_quicksort_colliders(&Collision_sort_list, 0, (int)(Collision_sort_list.size() - 1), 0); } obj_find_overlap_colliders(&sort_list_y, &Collision_sort_list, 0, false); sort_list_z.clear(); { TRACE_SCOPE(tracing::SortColliders); obj_quicksort_colliders(&sort_list_y, 0, (int)(sort_list_y.size() - 1), 1); } obj_find_overlap_colliders(&sort_list_z, &sort_list_y, 1, false); sort_list_y.clear(); { TRACE_SCOPE(tracing::SortColliders); obj_quicksort_colliders(&sort_list_z, 0, (int)(sort_list_z.size() - 1), 2); } obj_find_overlap_colliders(&sort_list_y, &sort_list_z, 2, true); }
/** * Go through GL_shader and call glDeleteObject() for all created shaders, then clear GL_shader */ void opengl_shader_shutdown() { size_t i; if ( !is_minimum_GLSL_version() ) { return; } for (i = 0; i < GL_shader.size(); i++) { if (GL_shader[i].program_id) { vglDeleteObjectARB(GL_shader[i].program_id); GL_shader[i].program_id = 0; } GL_shader[i].uniforms.clear(); GL_shader[i].attributes.clear(); GL_shader[i].uniform_blocks.clear(); } GL_shader.clear(); if (GLshader_info_log != NULL) { vm_free(GLshader_info_log); GLshader_info_log = NULL; } }
/** * Call at the close of each level (mission) */ void shockwave_level_close() { if ( !Shockwave_inited ) return; shockwave_delete_all(); size_t i; // unload default shockwave, and erase all others for (i = 0; i < Shockwave_info.size(); i++) { if ( !i ) { if (Shockwave_info[i].bitmap_id >= 0) bm_unload( Shockwave_info[i].bitmap_id ); else if (Shockwave_info[i].model_id >= 0) model_page_out_textures( Shockwave_info[i].model_id ); continue; } if (Shockwave_info[i].bitmap_id >= 0) bm_release( Shockwave_info[i].bitmap_id ); if (Shockwave_info[i].model_id >= 0) model_unload( Shockwave_info[i].model_id ); Shockwave_info.erase( Shockwave_info.begin() + i ); } Shockwave_inited = 0; }
void opengl_shader_set_current(int handle) { Assert(handle >= 0); Assert(handle < (int)GL_shader.size()); opengl_shader_set_current(&GL_shader[handle]); }
void opengl_destroy_all_buffers() { for ( uint i = 0; i < GL_buffer_objects.size(); i++ ) { gr_opengl_delete_buffer(i); } GL_vertex_buffers_in_use = 0; }
void get_post_process_effect_names(SCP_vector<SCP_string> &names) { size_t idx; for (idx = 0; idx < Post_effects.size(); idx++) { names.push_back(Post_effects[idx].name); } }
void opengl_post_init_uniforms(int flags) { for (int idx = 0; idx < (int)Post_effects.size(); idx++) { if (flags & (1 << idx)) { Current_shader->program->Uniforms.initUniform(Post_effects[idx].uniform_name.c_str()); } } }
size_t opengl_get_shader_idx(shader_type shader_t, unsigned int flags) { auto found = GL_shader_map.find(shader_descriptor_t(shader_t, flags)); if (found != GL_shader_map.end()) { return found->second; } return GL_shader.size(); }
void opengl_post_init_uniforms(int flags) { for (int idx = 0; idx < (int)Post_effects.size(); idx++) { if (flags & (1 << idx)) { opengl_shader_init_uniform(Post_effects[idx].uniform_name.c_str()); } } }