int main(int argc, const char **argv) { if(argc == 1) { const char *params[] = {"-p", "win32", "../../../Raw/Level/level.dae", "./"}; parseArgs(4, params); } else parseArgs(argc, argv); printf("Outputting in %s format\n", g_Endianness == LittleEndian ? "LittleEndian" : "BigEndian"); aiSetImportPropertyInteger( AI_CONFIG_PP_RVC_FLAGS, aiComponent_TANGENTS_AND_BITANGENTS | aiComponent_COLORS ); // Remove degenerates; if we don't do this, tangents & bitangents // can't be calculated for meshes with degenerate tris aiSetImportPropertyInteger( AI_CONFIG_PP_FD_REMOVE, true ); const aiScene* scene = aiImportFile( filename.c_str(), aiProcessPreset_TargetRealtime_MaxQuality | aiProcess_GenNormals | aiProcess_RemoveComponent ); if(!scene) printf("Failed to load %s\n", filename.c_str()); else { makeDirectories(); cJSON *root = cJSON_CreateObject(); cJSON *list = cJSON_CreateArray(); cJSON_AddItemToObject(root, "scene", list); aiMatrix4x4 identity; printf("Loaded %s\n", filename.c_str()); processSceneRecursive(scene, list, identity, scene->mRootNode); printf("Done\n"); outputFinalStep(); writeJsonToFile(root, outdir + "/scene.scene"); } aiReleaseImport(scene); getchar(); return 0; }
void outputJsonTextureFile(const std::string &filename, const std::string &output) { cJSON *root = cJSON_CreateObject(); cJSON *texture = cJSON_CreateObject(); cJSON *source = cJSON_CreateString((filename + ".btx").c_str()); cJSON_AddItemToObject(root, "texture", texture); cJSON_AddItemToObject(texture, "source", source); writeJsonToFile(root, output + ".texture"); }
void outputJsonMaterialFile(const std::string &texturefilename, const std::string &filename) { cJSON *root = cJSON_CreateObject(); cJSON *material = cJSON_CreateObject(); cJSON *textures = cJSON_CreateArray(); cJSON *diffuse = cJSON_CreateString((texturefilename + ".texture").c_str()); cJSON_AddItemToArray(textures, diffuse); cJSON_AddItemToObject(root, "material", material); cJSON_AddItemToObject(material, "textures", textures); cJSON_AddStringToObject(material, "vshader", (outdir + "/Shaders/simple.vp").c_str()); cJSON_AddStringToObject(material, "fshader", (outdir + "/Shaders/simple.fp").c_str()); cJSON *state = cJSON_CreateObject(); cJSON_AddItemToObject(material, "state", state); cJSON_AddFalseToObject(state, "enable-alpha-test"); cJSON_AddStringToObject(state, "compare-alpha-test", "less-equal"); cJSON_AddNumberToObject(state, "threshold-alpha-test", 127); writeJsonToFile(root, filename + ".material"); }
std::string outputJsonEntityFile(const std::string &name, const aiMatrix4x4 &matrix, const std::string &mesh, const std::string &material, const std::string &occlusionName) { float deg; aiVector3D s, p, a; aiQuaternion r; matrix.Decompose(s, r, p); convertToAxisAngle(r, a, deg); cJSON *root = cJSON_CreateObject(); cJSON *entity = cJSON_CreateObject(); cJSON_AddItemToObject(root, "entity", entity); cJSON_AddStringToObject(entity, "name", name.c_str()); cJSON *transform = cJSON_CreateObject(); cJSON_AddItemToObject(entity, "transform", transform); cJSON *position = cJSON_CreateArray(); cJSON_AddNumberToArray(position, p.x); cJSON_AddNumberToArray(position, p.y); cJSON_AddNumberToArray(position, p.z); cJSON_AddItemToObject(transform, "position", position); cJSON *orientation = cJSON_CreateArray(); cJSON *axis = cJSON_CreateArray(); cJSON_AddNumberToArray(axis, a.x); cJSON_AddNumberToArray(axis, a.y); cJSON_AddNumberToArray(axis, a.z); cJSON_AddNumberToArray(orientation, deg); cJSON_AddItemToArray(orientation, axis); cJSON_AddItemToObject(transform, "orientation", orientation); cJSON *scale = cJSON_CreateArray(); cJSON_AddNumberToArray(scale, s.x); cJSON_AddNumberToArray(scale, s.y); cJSON_AddNumberToArray(scale, s.z); cJSON_AddItemToObject(transform, "scale", scale); cJSON *components = cJSON_CreateObject(); cJSON_AddItemToObject(entity, "components", components); cJSON *renderable = cJSON_CreateObject(); cJSON_AddItemToObject(components, "renderable", renderable); cJSON_AddStringToObject(renderable, "mesh", mesh.c_str()); cJSON_AddStringToObject(renderable, "material", (material + ".material").c_str()); cJSON *physics = cJSON_CreateObject(); cJSON_AddItemToObject(components, "physics", physics); cJSON_AddStringToObject(physics, "type", "static"); if(!occlusionName.empty()) { cJSON *occlusion = cJSON_CreateObject(); cJSON_AddItemToObject(components, "occlusion", occlusion); cJSON_AddStringToObject(occlusion, "source", occlusionName.c_str()); } std::string filename = outdir + "/Entities/" + name + ".entity"; writeJsonToFile(root, filename); return filename; }
// //========================================================================= // int main(int argc, char **argv) { int j; // Set sane defaults modesInitConfig(); // signal handlers: signal(SIGINT, sigintHandler); signal(SIGTERM, sigtermHandler); // Parse the command line options for (j = 1; j < argc; j++) { int more = j+1 < argc; // There are more arguments if (!strcmp(argv[j],"--device-index") && more) { Modes.dev_name = strdup(argv[++j]); } else if (!strcmp(argv[j],"--gain") && more) { Modes.gain = (int) (atof(argv[++j])*10); // Gain is in tens of DBs } else if (!strcmp(argv[j],"--enable-agc")) { Modes.enable_agc++; } else if (!strcmp(argv[j],"--freq") && more) { Modes.freq = (int) strtoll(argv[++j],NULL,10); } else if (!strcmp(argv[j],"--ifile") && more) { Modes.filename = strdup(argv[++j]); } else if (!strcmp(argv[j],"--iformat") && more) { ++j; if (!strcasecmp(argv[j], "uc8")) { Modes.input_format = INPUT_UC8; } else if (!strcasecmp(argv[j], "sc16")) { Modes.input_format = INPUT_SC16; } else if (!strcasecmp(argv[j], "sc16q11")) { Modes.input_format = INPUT_SC16Q11; } else { fprintf(stderr, "Input format '%s' not understood (supported values: UC8, SC16, SC16Q11)\n", argv[j]); exit(1); } } else if (!strcmp(argv[j],"--dcfilter")) { Modes.dc_filter = 1; } else if (!strcmp(argv[j],"--measure-noise")) { Modes.measure_noise = 1; } else if (!strcmp(argv[j],"--fix")) { Modes.nfix_crc = 1; } else if (!strcmp(argv[j],"--no-fix")) { Modes.nfix_crc = 0; } else if (!strcmp(argv[j],"--no-crc-check")) { Modes.check_crc = 0; } else if (!strcmp(argv[j],"--phase-enhance")) { Modes.phase_enhance = 1; } else if (!strcmp(argv[j],"--raw")) { Modes.raw = 1; } else if (!strcmp(argv[j],"--net")) { Modes.net = 1; } else if (!strcmp(argv[j],"--modeac")) { Modes.mode_ac = 1; } else if (!strcmp(argv[j],"--net-beast")) { Modes.beast = 1; } else if (!strcmp(argv[j],"--net-only")) { Modes.net = 1; Modes.net_only = 1; } else if (!strcmp(argv[j],"--net-heartbeat") && more) { Modes.net_heartbeat_interval = (uint64_t)(1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--net-ro-size") && more) { Modes.net_output_flush_size = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-ro-rate") && more) { Modes.net_output_flush_interval = 1000 * atoi(argv[++j]) / 15; // backwards compatibility } else if (!strcmp(argv[j],"--net-ro-interval") && more) { Modes.net_output_flush_interval = (uint64_t)(1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--net-ro-port") && more) { if (Modes.beast) // Required for legacy backward compatibility {Modes.net_output_beast_port = atoi(argv[++j]);;} else {Modes.net_output_raw_port = atoi(argv[++j]);} } else if (!strcmp(argv[j],"--net-ri-port") && more) { Modes.net_input_raw_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bo-port") && more) { Modes.net_output_beast_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bi-port") && more) { Modes.net_input_beast_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bind-address") && more) { Modes.net_bind_address = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-http-port") && more) { Modes.net_http_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-fatsv-port") && more) { Modes.net_fatsv_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-sbs-port") && more) { Modes.net_output_sbs_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-buffer") && more) { Modes.net_sndbuf_size = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-verbatim")) { Modes.net_verbatim = 1; } else if (!strcmp(argv[j],"--forward-mlat")) { Modes.forward_mlat = 1; } else if (!strcmp(argv[j],"--onlyaddr")) { Modes.onlyaddr = 1; } else if (!strcmp(argv[j],"--metric")) { Modes.metric = 1; } else if (!strcmp(argv[j],"--aggressive")) { Modes.nfix_crc = MODES_MAX_BITERRORS; } else if (!strcmp(argv[j],"--interactive")) { Modes.interactive = Modes.throttle = 1; } else if (!strcmp(argv[j],"--throttle")) { Modes.throttle = 1; } else if (!strcmp(argv[j],"--interactive-rows") && more) { Modes.interactive_rows = atoi(argv[++j]); } else if (!strcmp(argv[j],"--interactive-ttl") && more) { Modes.interactive_display_ttl = (uint64_t)(1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--lat") && more) { Modes.fUserLat = atof(argv[++j]); } else if (!strcmp(argv[j],"--lon") && more) { Modes.fUserLon = atof(argv[++j]); } else if (!strcmp(argv[j],"--max-range") && more) { Modes.maxRange = atof(argv[++j]) * 1852.0; // convert to metres } else if (!strcmp(argv[j],"--debug") && more) { char *f = argv[++j]; while(*f) { switch(*f) { case 'D': Modes.debug |= MODES_DEBUG_DEMOD; break; case 'd': Modes.debug |= MODES_DEBUG_DEMODERR; break; case 'C': Modes.debug |= MODES_DEBUG_GOODCRC; break; case 'c': Modes.debug |= MODES_DEBUG_BADCRC; break; case 'p': Modes.debug |= MODES_DEBUG_NOPREAMBLE; break; case 'n': Modes.debug |= MODES_DEBUG_NET; break; case 'j': Modes.debug |= MODES_DEBUG_JS; break; default: fprintf(stderr, "Unknown debugging flag: %c\n", *f); exit(1); break; } f++; } } else if (!strcmp(argv[j],"--stats")) { if (!Modes.stats) Modes.stats = (uint64_t)1 << 60; // "never" } else if (!strcmp(argv[j],"--stats-range")) { Modes.stats_range_histo = 1; } else if (!strcmp(argv[j],"--stats-every") && more) { Modes.stats = (uint64_t) (1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--snip") && more) { snipMode(atoi(argv[++j])); exit(0); } else if (!strcmp(argv[j],"--help")) { showHelp(); exit(0); } else if (!strcmp(argv[j],"--ppm") && more) { Modes.ppm_error = atoi(argv[++j]); } else if (!strcmp(argv[j],"--quiet")) { Modes.quiet = 1; } else if (!strcmp(argv[j],"--show-only") && more) { Modes.show_only = (uint32_t) strtoul(argv[++j], NULL, 16); } else if (!strcmp(argv[j],"--mlat")) { Modes.mlat = 1; } else if (!strcmp(argv[j],"--interactive-rtl1090")) { Modes.interactive = 1; Modes.interactive_rtl1090 = 1; } else if (!strcmp(argv[j],"--oversample")) { Modes.oversample = 1; #ifndef _WIN32 } else if (!strcmp(argv[j], "--write-json") && more) { Modes.json_dir = strdup(argv[++j]); } else if (!strcmp(argv[j], "--write-json-every") && more) { Modes.json_interval = (uint64_t)(1000 * atof(argv[++j])); if (Modes.json_interval < 100) // 0.1s Modes.json_interval = 100; } else if (!strcmp(argv[j], "--json-location-accuracy") && more) { Modes.json_location_accuracy = atoi(argv[++j]); #endif } else { fprintf(stderr, "Unknown or not enough arguments for option '%s'.\n\n", argv[j]); showHelp(); exit(1); } } #ifndef _WIN32 // Setup for SIGWINCH for handling lines if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} #endif if (Modes.mode_ac && Modes.oversample) { fprintf(stderr, "Warning: --modeac is currently ignored when --oversample is used;\n" " no ModeA/C messages will be decoded.\n"); } // Initialization log_with_timestamp("%s %s starting up.", MODES_DUMP1090_VARIANT, MODES_DUMP1090_VERSION); modesInit(); if (Modes.net_only) { fprintf(stderr,"Net-only mode, no RTL device or file open.\n"); } else if (Modes.filename == NULL) { if (modesInitRTLSDR() < 0) { exit(1); } } else { if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') { Modes.fd = STDIN_FILENO; } else if ((Modes.fd = open(Modes.filename, #ifdef _WIN32 (O_RDONLY | O_BINARY) #else (O_RDONLY) #endif )) == -1) { perror("Opening data file"); exit(1); } } if (Modes.net) modesInitNet(); // init stats: Modes.stats_current.start = Modes.stats_current.end = Modes.stats_alltime.start = Modes.stats_alltime.end = Modes.stats_periodic.start = Modes.stats_periodic.end = Modes.stats_5min.start = Modes.stats_5min.end = Modes.stats_15min.start = Modes.stats_15min.end = mstime(); for (j = 0; j < 15; ++j) Modes.stats_1min[j].start = Modes.stats_1min[j].end = Modes.stats_current.start; // write initial json files so they're not missing writeJsonToFile("receiver.json", generateReceiverJson); writeJsonToFile("stats.json", generateStatsJson); writeJsonToFile("aircraft.json", generateAircraftJson); // If the user specifies --net-only, just run in order to serve network // clients without reading data from the RTL device if (Modes.net_only) { while (!Modes.exit) { struct timespec start_time; start_cpu_timing(&start_time); backgroundTasks(); end_cpu_timing(&start_time, &Modes.stats_current.background_cpu); usleep(100000); } } else { // Create the thread that will read the data from the device. pthread_mutex_lock(&Modes.data_mutex); pthread_create(&Modes.reader_thread, NULL, readerThreadEntryPoint, NULL); while (Modes.exit == 0) { struct timespec start_time; if (Modes.first_free_buffer == Modes.first_filled_buffer) { /* wait for more data. * we should be getting data every 50-60ms. wait for max 100ms before we give up and do some background work. * this is fairly aggressive as all our network I/O runs out of the background work! */ struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_nsec += 100000000; normalize_timespec(&ts); pthread_cond_timedwait(&Modes.data_cond, &Modes.data_mutex, &ts); // This unlocks Modes.data_mutex, and waits for Modes.data_cond } // Modes.data_mutex is locked, and possibly we have data. // copy out reader CPU time and reset it add_timespecs(&Modes.reader_cpu_accumulator, &Modes.stats_current.reader_cpu, &Modes.stats_current.reader_cpu); Modes.reader_cpu_accumulator.tv_sec = 0; Modes.reader_cpu_accumulator.tv_nsec = 0; if (Modes.first_free_buffer != Modes.first_filled_buffer) { // FIFO is not empty, process one buffer. struct mag_buf *buf; start_cpu_timing(&start_time); buf = &Modes.mag_buffers[Modes.first_filled_buffer]; // Process data after releasing the lock, so that the capturing // thread can read data while we perform computationally expensive // stuff at the same time. pthread_mutex_unlock(&Modes.data_mutex); if (Modes.oversample) { demodulate2400(buf); } else { demodulate2000(buf); } Modes.stats_current.samples_processed += buf->length; Modes.stats_current.samples_dropped += buf->dropped; end_cpu_timing(&start_time, &Modes.stats_current.demod_cpu); // Mark the buffer we just processed as completed. pthread_mutex_lock(&Modes.data_mutex); Modes.first_filled_buffer = (Modes.first_filled_buffer + 1) % MODES_MAG_BUFFERS; pthread_cond_signal(&Modes.data_cond); pthread_mutex_unlock(&Modes.data_mutex); } else { // Nothing to process this time around. pthread_mutex_unlock(&Modes.data_mutex); } start_cpu_timing(&start_time); backgroundTasks(); end_cpu_timing(&start_time, &Modes.stats_current.background_cpu); pthread_mutex_lock(&Modes.data_mutex); } pthread_mutex_unlock(&Modes.data_mutex); pthread_join(Modes.reader_thread,NULL); // Wait on reader thread exit pthread_cond_destroy(&Modes.data_cond); // Thread cleanup - only after the reader thread is dead! pthread_mutex_destroy(&Modes.data_mutex); } // If --stats were given, print statistics if (Modes.stats) { display_total_stats(); } cleanup_converter(Modes.converter_state); log_with_timestamp("Normal exit."); pthread_exit(0); #ifdef _WIN32 return (0); #endif }
// //========================================================================= // // This function is called a few times every second by main in order to // perform tasks we need to do continuously, like accepting new clients // from the net, refreshing the screen in interactive mode, and so forth // void backgroundTasks(void) { static uint64_t next_stats_display; static uint64_t next_stats_update; static uint64_t next_json, next_history; uint64_t now = mstime(); icaoFilterExpire(); trackPeriodicUpdate(); if (Modes.net) { modesNetPeriodicWork(); } // Refresh screen when in interactive mode if (Modes.interactive) { interactiveShowData(); } // always update end time so it is current when requests arrive Modes.stats_current.end = now; if (now >= next_stats_update) { int i; if (next_stats_update == 0) { next_stats_update = now + 60000; } else { Modes.stats_latest_1min = (Modes.stats_latest_1min + 1) % 15; Modes.stats_1min[Modes.stats_latest_1min] = Modes.stats_current; add_stats(&Modes.stats_current, &Modes.stats_alltime, &Modes.stats_alltime); add_stats(&Modes.stats_current, &Modes.stats_periodic, &Modes.stats_periodic); reset_stats(&Modes.stats_5min); for (i = 0; i < 5; ++i) add_stats(&Modes.stats_1min[(Modes.stats_latest_1min - i + 15) % 15], &Modes.stats_5min, &Modes.stats_5min); reset_stats(&Modes.stats_15min); for (i = 0; i < 15; ++i) add_stats(&Modes.stats_1min[i], &Modes.stats_15min, &Modes.stats_15min); reset_stats(&Modes.stats_current); Modes.stats_current.start = Modes.stats_current.end = now; if (Modes.json_dir) writeJsonToFile("stats.json", generateStatsJson); next_stats_update += 60000; } } if (Modes.stats && now >= next_stats_display) { if (next_stats_display == 0) { next_stats_display = now + Modes.stats; } else { add_stats(&Modes.stats_periodic, &Modes.stats_current, &Modes.stats_periodic); display_stats(&Modes.stats_periodic); reset_stats(&Modes.stats_periodic); next_stats_display += Modes.stats; } } if (Modes.json_dir && now >= next_json) { writeJsonToFile("aircraft.json", generateAircraftJson); next_json = now + Modes.json_interval; } if ((Modes.json_dir || Modes.net_http_port) && now >= next_history) { int rewrite_receiver_json = (Modes.json_aircraft_history[HISTORY_SIZE-1].content == NULL); free(Modes.json_aircraft_history[Modes.json_aircraft_history_next].content); // might be NULL, that's OK. Modes.json_aircraft_history[Modes.json_aircraft_history_next].content = generateAircraftJson("/data/aircraft.json", &Modes.json_aircraft_history[Modes.json_aircraft_history_next].clen); if (Modes.json_dir) { char filebuf[PATH_MAX]; snprintf(filebuf, PATH_MAX, "history_%d.json", Modes.json_aircraft_history_next); writeJsonToFile(filebuf, generateHistoryJson); } Modes.json_aircraft_history_next = (Modes.json_aircraft_history_next+1) % HISTORY_SIZE; if (rewrite_receiver_json) writeJsonToFile("receiver.json", generateReceiverJson); // number of history entries changed next_history = now + HISTORY_INTERVAL; } }