15 #include "pandaFramework.h"
17 #include "pandaNode.h"
18 #include "transformState.h"
19 #include "clockObject.h"
20 #include "string_utils.h"
22 #include "panda_getopt.h"
23 #include "preprocess_argv.h"
25 #define RANDFRAC (rand()/(PN_stdfloat)(RAND_MAX))
37 PN_stdfloat xcenter,ycenter;
38 PN_stdfloat xoffset,yoffset;
39 PN_stdfloat ang1,ang1_vel;
40 PN_stdfloat ang2,ang2_vel;
45 PN_stdfloat xstart,ystart;
46 PN_stdfloat xend,yend;
47 PN_stdfloat xdel,ydel,timedel;
48 double starttime,endtime;
57 typedef enum {None,Rotation,LinearMotion} GriddedMotionType;
59 #define GRIDCELLSIZE 5.0
62 #define MIN_WANDERAREA_DIMENSION 120.0f
64 static PN_stdfloat grid_pos_offset;
65 static PN_stdfloat wander_area_pos_offset;
67 static GriddedMotionType gridmotiontype = None;
72 move_gridded_stuff(GriddedMotionType gridmotiontype,
78 for(
int i = 0; i < size; i++) {
79 double time_delta = (now-InfoArr[i].starttime);
80 #define DO_FP_MODULUS(VAL,MAXVAL) \
81 {if(VAL > MAXVAL) {int idivresult = (int)(VAL / (PN_stdfloat)MAXVAL); VAL=VAL-idivresult*MAXVAL;} else \
82 if(VAL < -MAXVAL) {int idivresult = (int)(VAL / (PN_stdfloat)MAXVAL); VAL=VAL+idivresult*MAXVAL;}}
86 if(gridmotiontype==Rotation) {
88 InfoArr[i].ang1=time_delta*InfoArr[i].ang1_vel;
89 DO_FP_MODULUS(InfoArr[i].ang1,360.0);
90 InfoArr[i].ang2=time_delta*InfoArr[i].ang2_vel;
91 DO_FP_MODULUS(InfoArr[i].ang2,360.0);
97 LVector3 translate_vec(InfoArr[i].xcenter+new_center._v.v._0,
98 InfoArr[i].ycenter+new_center._v.v._1,
101 const LVector3 rotation_axis(0.0, 0.0, 1.0);
105 xfm_mat = tmat1 * tmat2;
108 PN_stdfloat xpos,ypos;
110 if(now>InfoArr[i].endtime) {
111 InfoArr[i].starttime = now;
113 xpos = InfoArr[i].xstart = InfoArr[i].xend;
114 ypos = InfoArr[i].ystart = InfoArr[i].yend;
116 InfoArr[i].xend = RANDFRAC*fabs(2.0*wander_area_pos_offset) + wander_area_pos_offset;
117 InfoArr[i].yend = RANDFRAC*fabs(2.0*wander_area_pos_offset) + wander_area_pos_offset;
119 PN_stdfloat xdel = InfoArr[i].xdel = InfoArr[i].xend-InfoArr[i].xstart;
120 PN_stdfloat ydel = InfoArr[i].ydel = InfoArr[i].yend-InfoArr[i].ystart;
122 InfoArr[i].endtime = now + csqrt(xdel*xdel+ydel*ydel)/InfoArr[i].vel;
123 InfoArr[i].timedel = InfoArr[i].endtime - InfoArr[i].starttime;
125 const LVector3 rotate_axis(0.0, 0.0, 1.0);
127 PN_stdfloat ang = rad_2_deg(atan2(-xdel,ydel));
131 PN_stdfloat timefrac= time_delta/InfoArr[i].timedel;
133 xpos = InfoArr[i].xdel*timefrac+InfoArr[i].xstart;
134 ypos = InfoArr[i].ydel*timefrac+InfoArr[i].ystart;
137 LVector3 translate_vec(xpos, ypos, 0.0);
140 xfm_mat = InfoArr[i].rotmat * tmat2;
142 InfoArr[i].node->
set_transform(TransformState::make_mat(xfm_mat));
147 get_command_line_opts(
int &argc,
char **&argv) {
151 const char *options =
"rm";
152 int flag = getopt(argc, argv, options);
153 while (flag != EOF) {
156 gridmotiontype = Rotation;
160 gridmotiontype = LinearMotion;
164 nout <<
"Invalid parameter.\n";
168 flag = getopt(argc, argv, options);
171 argv += (optind - 1);
172 argc -= (optind - 1);
178 get_command_line_filenames(
int argc,
char *argv[],
181 for (
int i = 1; i < argc && argv[i] != (
char *)NULL; i++) {
182 const string &arg = argv[i];
183 size_t comma = arg.find(
',');
184 if (comma == string::npos) {
192 string name = arg.substr(0, comma);
193 string count_str = arg.substr(comma + 1);
195 if (!string_to_int(count_str, count)) {
196 nout <<
"Ignoring invalid number: " << count_str <<
"\n";
198 }
else if (count <= 0) {
199 nout <<
"Ignoring inappropriate number: " << count <<
"\n";
206 gridded_filenames.push_back(gf);
226 GriddedFilenames::iterator fi;
227 for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
229 PT(
PandaNode) node = loader.load_sync(gf._filename, options);
232 grid_count += gf._count;
237 info_arr.reserve(grid_count);
243 while(gridwidth*gridwidth < grid_count) {
247 grid_pos_offset = -gridwidth*GRIDCELLSIZE/2.0;
248 wander_area_pos_offset = -max((PN_stdfloat)fabs(grid_pos_offset), MIN_WANDERAREA_DIMENSION/2.0f);
253 PN_stdfloat xpos = grid_pos_offset;
254 PN_stdfloat ypos = grid_pos_offset;
256 srand( (
unsigned)time( NULL ) );
267 for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
269 if (!gf._model.
is_empty() && gf._count > passnum) {
275 PT(
PandaNode) node = loader.load_sync(gf._filename, options);
285 info.node = model.
node();
289 if(gridmotiontype==Rotation) {
291 #define MIN_REVOLUTION_ANGVEL 30
292 #define MAX_REVOLUTION_ANGVEL 60
294 #define MIN_ROTATION_ANGVEL 30
295 #define MAX_ROTATION_ANGVEL 600
297 #define MAX_RADIUS 4.0*GRIDCELLSIZE
298 #define MIN_RADIUS 0.1*GRIDCELLSIZE
300 info.starttime = now;
304 info.ang1=RANDFRAC * 360.0;
305 info.ang1_vel=((MAX_REVOLUTION_ANGVEL-MIN_REVOLUTION_ANGVEL) * RANDFRAC) + MIN_REVOLUTION_ANGVEL;
307 info.ang2=RANDFRAC * 360.0;
308 info.ang2_vel=((MAX_ROTATION_ANGVEL-MIN_ROTATION_ANGVEL) * RANDFRAC) + MIN_ROTATION_ANGVEL;
310 info.radius = (RANDFRAC * (MAX_RADIUS-MIN_RADIUS)) + MIN_RADIUS;
313 info.ang1_vel=-info.ang1_vel;
317 info.ang2_vel=-info.ang2_vel;
324 const LVector3 rotate_axis(0.0, 0.0, 1.0);
326 LVector3 translate_vec(xpos+new_center._v.v._0,
327 ypos+new_center._v.v._1,
332 xfm_mat = tmat1 * tmat2;
333 }
else if(gridmotiontype==LinearMotion) {
336 #define MAX_VEL (fabs(wander_area_pos_offset))
338 info.vel=((MAX_VEL-MIN_VEL) * RANDFRAC) + MIN_VEL;
343 info.xend = RANDFRAC*fabs(2.0*wander_area_pos_offset) + wander_area_pos_offset;
344 info.yend = RANDFRAC*fabs(2.0*wander_area_pos_offset) + wander_area_pos_offset;
346 info.starttime = now;
348 PN_stdfloat xdel = info.xdel = info.xend-info.xstart;
349 PN_stdfloat ydel = info.ydel = info.yend-info.ystart;
351 info.endtime = csqrt(xdel*xdel+ydel*ydel)/info.vel;
353 info.timedel = info.endtime - info.starttime;
355 const LVector3 rotate_axis(0.0, 0.0, 1.0);
356 PN_stdfloat ang = rad_2_deg(atan2(-xdel,ydel));
360 LVector3 translate_vec(xpos, ypos, 0.0);
363 xfm_mat = info.rotmat * tmat2;
365 LVector3 translate_vec(xpos, ypos, 0.0);
371 info_arr.push_back(info);
373 if((model_count % gridwidth) == 0) {
374 xpos= -gridwidth*GRIDCELLSIZE/2.0;
383 }
while (loaded_any);
387 main(
int argc,
char **argv) {
391 preprocess_argv(argc, argv);
396 if (!get_command_line_opts(argc, argv)) {
404 get_command_line_filenames(argc, argv, static_filenames, gridded_filenames);
416 load_gridded_models(window, gridded_filenames, info_arr);
425 while (framework.
do_frame(current_thread)) {
426 if (!info_arr.empty() && gridmotiontype) {
427 move_gridded_stuff(gridmotiontype, &info_arr[0], info_arr.size());
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
A basic node of the scene graph or data graph.
void stagger_animations()
Walks through all the animations that were bound by loop_animations() and staggers their play rate sl...
void loop_animations(int hierarchy_match_flags=PartGroup::HMF_ok_part_extra|PartGroup::HMF_ok_anim_extra)
Looks for characters and their matching animation files in the scene graph; binds and loops any match...
NodePath copy_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Functions like instance_to(), except a deep copy is made of the referenced node and all of its descen...
void enable_default_keys()
Sets callbacks on the event handler to handle all of the normal viewer keys, like t to toggle texture...
static LMatrix4f translate_mat(const LVecBase3f &trans)
Returns a matrix that applies the indicated translation.
NodePath & get_models()
Returns the root of the scene graph normally reserved for parenting models and such.
NodePath get_render()
Returns the root of the 3-d scene graph.
Specifies parameters that may be passed to the loader.
This encapsulates the data that is normally associated with a single window, or with a single display...
A convenient class for loading models from disk, in bam or egg format (or any of a number of other fo...
PandaNode * node() const
Returns the referenced node of the path.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
NodePath instance_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread()) const
Adds the referenced node of the NodePath as a child of the referenced node of the indicated other Nod...
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
This is our own Panda specialization on the default STL vector.
void reparent_to(const NodePath &other, int sort=0, Thread *current_thread=Thread::get_current_thread())
Removes the referenced node of the NodePath from its current parent and attaches it to the referenced...
PandaFramework * get_panda_framework() const
Returns a pointer to the associated PandaFramework object.
The name of a file, such as a texture file or an Egg file.
This is a 4-by-4 transform matrix.
double get_frame_time(Thread *current_thread=Thread::get_current_thread()) const
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
void center_trackball(const NodePath &object)
Centers the trackball on the indicated object, and scales the trackball motion suitably.
void enable_keyboard()
Creates a ButtonThrower to listen to button presses and throw them as events.
WindowFramework * open_window()
Opens a window on the default graphics pipe.
void open_framework(int &argc, char **&argv)
Should be called once at the beginning of the application to initialize Panda (and the framework) for...
This is a two-component vector offset.
static LMatrix4f rotate_mat_normaxis(float angle, const LVecBase3f &axis, CoordinateSystem cs=CS_default)
Returns a matrix that rotates by the given angle in degrees counterclockwise about the indicated vect...
A thread; that is, a lightweight process.
bool load_models(const NodePath &parent, int argc, char *argv[], int first_arg=1)
Loads up all the model files listed in the indicated argument list.
static LMatrix3f rotate_mat(float angle)
Returns a matrix that rotates by the given angle in degrees counterclockwise.
void set_window_title(const string &title)
Specifies the title that is set for all subsequently created windows.
bool is_empty() const
Returns true if the NodePath contains no nodes.
This class serves to provide a high-level framework for basic applications that use Panda in simple w...
void setup_trackball()
Sets up the mouse to trackball around the camera.
void report_frame_rate(ostream &out) const
Reports the currently measured average frame rate to the indicated ostream.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
void set_transform(const TransformState *transform, Thread *current_thread=Thread::get_current_thread())
Sets the transform that will be applied to this node and below.
void set_rotate_mat_normaxis(float angle, const LVecBase3f &axis, CoordinateSystem cs=CS_default)
Fills mat with a matrix that rotates by the given angle in degrees counterclockwise about the indicat...
virtual bool do_frame(Thread *current_thread)
Renders one frame and performs all associated processing.
static Filename from_os_specific(const string &os_specific, Type type=T_general)
This named constructor returns a Panda-style filename (that is, using forward slashes, and no drive letter) based on the supplied filename string that describes a filename in the local system conventions (for instance, on Windows, it may use backslashes or begin with a drive letter and a colon).