106 return ( ax == bx ? a < b : ax < bx );
113 return ( ay == by ? a < b : ay < by );
167 PRINT_WARN(
"Stg::Init() must be called before a World is created." );
210 bool found_gui =
false;
213 found_gui |= (*world_it)->IsGUI();
217 PRINT_WARN(
"When using the GUI only a single world can be simulated." );
237 if( (*world_it)->Update() == false )
248 World* world( thread_info->first );
249 const int thread_instance( thread_info->second );
309 PRINT_ERR(
"block has no model for a parent" );
311 mod->LoadBlock( wf, entity );
322 PRINT_ERR(
"block has no ranger model for a parent" );
338 std::map< std::string, creator_t>::iterator it =
344 PRINT_ERR1(
"Model type %s not found in model typetable", typestr.c_str() );
347 creator = it->second;
353 mod = (*creator)(
this, parent, typestr );
357 PRINT_ERR1(
"Unknown model type %s in world file.",
372 entity, parent_entity );
382 mod->
Load(wf, entity );
393 printf(
" [Loading %s]", worldfile_path.c_str() );
397 wf->
Load( worldfile_path );
427 PRINT_WARN(
"threads set to <1. Forcing to 1" );
440 typedef void* (*func_ptr) (
void*);
449 new std::pair<World*,int>(
this, t+1 ) );
452 if( worker_threads > 1 )
453 printf(
"[threads %u]", worker_threads );
461 if( strcmp( typestr,
"window" ) == 0 )
465 else if( strcmp( typestr,
"block" ) == 0 )
467 else if( strcmp( typestr,
"sensor" ) == 0 )
477 (*it)->blockgroup.CalcSize();
482 (*it)->InitControllers();
503 token =
"[unloaded]";
513 const uint32_t usec_per_hour(3600000000U);
514 const uint32_t usec_per_minute(60000000U);
515 const uint32_t usec_per_second(1000000U);
516 const uint32_t usec_per_msec(1000U);
518 const uint32_t hours(
sim_time / usec_per_hour);
519 const uint32_t minutes((
sim_time % usec_per_hour) / usec_per_minute);
520 const uint32_t seconds((
sim_time % usec_per_minute) / usec_per_second);
521 const uint32_t msec((
sim_time % usec_per_second) / usec_per_msec);
528 snprintf( buf, 255,
"%uh", hours );
532 snprintf( buf, 255,
" %um %02us %03umsec", minutes, seconds, msec);
542 cb_list.push_back( std::pair<world_callback_t,void*>(cb, user) );
549 std::pair<world_callback_t,void*> p( cb, user );
571 for(
size_t t(0); t<threads; ++t )
583 q.front()->CallUpdateCallbacks();
594 if( ((*it).first )(
this, (*it).second ) )
601 std::priority_queue<Event>& queue(
event_queues[queue_num] );
611 Event ev( queue.top() );
619 ev.
cb( ev.mod, ev.arg);
621 while( !queue.empty() );
690 (*it)->UpdateCharge();
709 PRINT_DEBUG1(
"looking up model name %s in models_by_name", name.c_str() );
711 std::map<std::string,Model*>::const_iterator it(
models_by_name.find( name ) );
715 PRINT_WARN1(
"lookup of model name %s: no matching name", name.c_str() );
724 float* drawpts(
new float[4] );
749 const uint32_t sample_count,
753 Pose raypose( gpose );
754 const double starta( fov/2.0 - raypose.
a );
756 for( uint32_t
s(0);
s < sample_count; ++
s )
758 raypose.
a = (
s * fov / (double)(sample_count-1)) - starta;
759 samples[
s] =
Raytrace( raypose, range, func, model, arg, ztest );
771 return Raytrace(
Ray( mod, gpose, range, func, arg, ztest ));
788 const double startx( globx );
789 const double starty( globy );
793 const double sina(sin(angle));
794 const double cosa(cos(angle));
795 const double tana(sina/cosa);
799 const double dx(
ppm * r.
range * cosa);
800 const double dy(
ppm * r.
range * sina);
804 const int32_t sx(
sgn(dx));
805 const int32_t sy(
sgn(dy));
806 const int32_t ax(abs(dx));
807 const int32_t ay(abs(dy));
808 const int32_t bx(2*ax);
809 const int32_t by(2*ay);
815 const double xjumpy( sx * REGIONWIDTH * tana );
816 const double yjumpx( sy * REGIONWIDTH / tana );
817 const double yjumpy( sy * REGIONWIDTH );
820 const double xjumpdist( fabs(xjumpx)+fabs(xjumpy) );
821 const double yjumpdist( fabs(yjumpx)+fabs(yjumpy) );
823 const unsigned int layer( (
updates+1) % 2 );
826 double xcrossx(0), xcrossy(0);
827 double ycrossx(0), ycrossy(0);
828 double distX(0), distY(0);
829 bool calculatecrossings(
true );
842 if( reg && reg->count )
848 calculatecrossings =
true;
854 Cell* c( ®->cells[ cx + cy * REGIONWIDTH ] );
861 while( (cx>=0) && (cx<REGIONWIDTH) &&
862 (cy>=0) && (cy<REGIONWIDTH) &&
884 sample.
range = fabs((globx-startx) / cosa) /
ppm;
886 sample.
range = fabs((globy-starty) / sina) /
ppm;
918 if( calculatecrossings )
920 calculatecrossings =
false;
924 const int32_t ix( globx );
925 const int32_t iy( globy );
926 double regionx( ix/REGIONWIDTH*REGIONWIDTH );
927 double regiony( iy/REGIONWIDTH*REGIONWIDTH );
928 if( (globx < 0) && (ix % REGIONWIDTH) ) regionx -=
REGIONWIDTH;
929 if( (globy < 0) && (iy % REGIONWIDTH) ) regiony -=
REGIONWIDTH;
932 const double xdx( sx < 0 ?
933 regionx - globx - 1.0 :
934 regionx + REGIONWIDTH - globx );
935 const double xdy( xdx*tana );
937 const double ydy( sy < 0 ?
938 regiony - globy - 1.0 :
939 regiony + REGIONWIDTH - globy );
940 const double ydx( ydy/tana );
951 distX = fabs(xdx)+fabs(xdy);
952 distY = fabs(ydx)+fabs(ydy);
1023 const size_t pt_count( pts.size() );
1025 for(
size_t i(0); i<pt_count; ++i )
1032 const int32_t dx( end.
x - start.
x );
1033 const int32_t dy( end.
y - start.
y );
1034 const int32_t sx(
sgn(dx));
1035 const int32_t sy(
sgn(dy));
1036 const int32_t ax(abs(dx));
1037 const int32_t ay(abs(dy));
1038 const int32_t bx(2*ax);
1039 const int32_t by(2*ay);
1044 int32_t globx(start.
x);
1045 int32_t globy(start.
y);
1051 ->GetRegion(
GETREG(globx),
1117 std::map<point_int_t,SuperRegion*>::iterator it(
superregions.find(org) );
1175 return( time > other.
time );
static bool quit_all
quit all worlds ASAP
std::set< Model * > models
SuperRegion * CreateSuperRegion(point_int_t origin)
pthread_cond_t threads_done_cond
signalled by last worker thread to unblock main thread
Bounds y
volume extent along y axis, initially zero
int32_t GETSREG(const int32_t x)
int GetEntityParent(int entity)
uint64_t updates
the number of simulated time steps executed so far
std::map< int, Model * > models_by_wfentity
bool graphics
true iff we have a GUI
double max
largest value in range, initially zero
void LoadBlock(Worldfile *wf, int entity)
The Stage library uses its own namespace.
const char * GetEntityType(int entity)
std::list< std::pair< world_callback_t, void * > > cb_list
List of callback functions and arguments.
static std::vector< std::string > args
unsigned int show_clock_interval
updates between clock outputs
const int32_t SRBITS(RBITS+SBITS)
std::list< float * > ray_list
List of rays traced for debug visualization.
bool operator()(const Model *a, const Model *b) const
void RegisterOption(Option *opt)
Register an Option for pickup by the GUI.
int32_t GETREG(const int32_t x)
void LoadModel(Worldfile *wf, int entity)
void RemovePowerPack(PowerPack *pp)
std::set< Option * > option_table
GUI options (toggles) registered by models.
const std::string ReadString(int entity, const char *name, const std::string &value)
SuperRegion * AddSuperRegion(const point_int_t &coord)
pthread_cond_t threads_start_cond
signalled to unblock worker threads
static std::set< World * > world_set
all the worlds that exist
std::set< Model *, ltx > models_with_fiducials_byx
void LoadSensor(Worldfile *wf, int entity)
void EraseAll(T thing, C &cont)
double min
smallest value in range, initially zero
std::map< std::string, Model * > models_by_name
bool operator<(const Event &other) const
#define PRINT_DEBUG2(m, a, b)
double ppm
the resolution of the world model in pixels per meter
void AddBlock(Block *b, unsigned int index)
SuperRegion * GetSuperRegionCreate(const point_int_t &org)
void DestroySuperRegion(SuperRegion *sr)
usec_t time
time that event occurs
void Load(Worldfile *wf, int wf_entity)
unsigned int worker_threads
the number of worker threads to use
const point_int_t & GetOrigin() const
void ForEachDescendant(model_callback_t func, void *arg)
void AddUpdateCallback(world_callback_t cb, void *user)
meters_t z
location in 3 axes
Model *(* creator_t)(World *, Model *, const std::string &type)
static void * update_thread_entry(std::pair< World *, int > *info)
int total_subs
the total number of subscriptions to all models
void RecordRay(double x1, double y1, double x2, double y2)
bool Save(const std::string &filename)
usec_t sim_time
the current sim time in this world in microseconds
virtual void AddModel(Model *mod)
virtual bool Update(void)
static int _reload_cb(Model *mod, void *dummy)
Pose GetGlobalPose() const
unsigned int threads_working
the number of worker threads not yet finished
void LoadSensor(Worldfile *wf, int entity)
static unsigned int next_id
initially zero, used to allocate unique sequential world ids
std::map< point_int_t, SuperRegion * > superregions
pthread_mutex_t sync_mutex
protect the worker thread management stuff
meters_t range
range to beam hit in meters
bool dirty
iff true, a gui redraw would be required
bounds3d_t extent
Describes the 3D volume of the world.
RaytraceResult Raytrace(const Ray &ray)
Color color
the color struck by this beam
static int _save_cb(Model *mod, void *dummy)
Region * GetRegion(int32_t x, int32_t y)
virtual void SetToken(const std::string &str)
Worldfile * wf
If set, points to the worldfile used to create this world.
bool(* ray_test_func_t)(Model *candidate, Model *finder, const void *arg)
Bounds x
volume extent along x axis, intially zero
bool operator()(const Model *a, const Model *b) const
std::vector< Model * > children
bool paused
if true, the simulation is stopped
std::vector< std::priority_queue< Event > > event_queues
virtual void SetToken(const std::string &str)
virtual void RemoveModel(Model *mod)
bool show_clock
iff true, print the sim time on stdout
#define PRINT_DEBUG1(m, a)
Bounds z
volume extent along z axis, initially zero
const int32_t REGIONWIDTH(1<< RBITS)
Cell * GetCell(int32_t x, int32_t y)
double ReadFloat(int entity, const char *name, double value)
static std::map< std::string, creator_t > name_map
void SetGuiMove(bool val)
bool quit
quit this world ASAP
Model * GetModel(const std::string &name) const
std::set< Model * > active_energy
std::set< Model *, lty > models_with_fiducials_byy
std::list< PowerPack * > powerpack_list
List of all the powerpacks attached to models in the world.
void ConsumeQueue(unsigned int queue_num)
std::vector< std::queue< Model * > > pending_update_callbacks
std::vector< Block * > blocks[2]
std::vector< Model * > models_with_fiducials
int ReadInt(int entity, const char *name, int value)
std::set< ModelPosition * > active_velocity
SuperRegion * GetSuperRegion(const point_int_t &org)
radians_t a
rotation about the z axis.
int32_t GETCELL(const int32_t x)
int(* world_callback_t)(World *world, void *user)
Model * CreateModel(Model *parent, const std::string &typestr)
void CallUpdateCallbacks()
Call all calbacks in cb_list, removing any that return true;.
virtual bool Save(const char *filename)
void AddModelName(Model *mod, const std::string &name)
bool Load(const std::string &filename)
unsigned int GetEventQueue(Model *mod) const
static std::string ctrlargs
World(const std::string &name="MyWorld", double ppm=DEFAULT_PPM)
Model * mod
the model struck by this beam
#define PRINT_WARN1(m, a)
Model * mod
model to which this block belongs
virtual std::string ClockString(void) const
int RemoveUpdateCallback(world_callback_t cb, void *user)
void MapPoly(const std::vector< point_int_t > &poly, Block *block, unsigned int layer)
const char * Token() const
virtual void Load(const std::string &worldfile_path)
void AddPowerPack(PowerPack *pp)