Panda3D
wander.cxx
1 ////////////////////////////////////////////////////////////////////////
2 // Filename : wander.cxx
3 // Created by : Deepak, John, Navin
4 // Date : 24 Oct 09
5 ////////////////////////////////////////////////////////////////////
6 //
7 // PANDA 3D SOFTWARE
8 // Copyright (c) Carnegie Mellon University. All rights reserved.
9 //
10 // All use of this software is subject to the terms of the revised BSD
11 // license. You should have received a copy of this license along
12 // with this source code in a file named "LICENSE."
13 //
14 ////////////////////////////////////////////////////////////////////
15 
16 #include "wander.h"
17 
18 /////////////////////////////////////////////////////////////////////////////////
19 //
20 // Function : rand_float
21 // Description : This function creates a random float point number
22 
23 /////////////////////////////////////////////////////////////////////////////////
24 
25 double rand_float() {
26  const static double rand_max = 0x7fff;
27  return ((rand()) / (rand_max + 1.0));
28 }
29 
30 /////////////////////////////////////////////////////////////////////////////////
31 //
32 // Function : random_clamped
33 // Description : This function returns a random floating point number in the range
34 // -1 to 1.
35 
36 /////////////////////////////////////////////////////////////////////////////////
37 
38 double random_clamped() {
39  return (rand_float() - rand_float());
40 }
41 
42 Wander::Wander(AICharacter *ai_ch, double wander_radius,int flag, double aoe, float wander_weight) {
43  _ai_char = ai_ch;
44  _wander_radius = wander_radius ;
45  _wander_weight = wander_weight;
46  double theta = rand_float() * 2 * 3.14159;
47  double si = rand_float() * 3.14159;
48  _flag = flag;
49  // Area around which the character should wander
50  _area_of_effect = aoe;
51  _init_pos = _ai_char->get_node_path().get_pos(_ai_char->get_char_render());
52  // _flag is used by Wander to wander in a given axis
53  // Value 0 - XY axes wander
54  // Value 1 - YZ axes wander
55  // Value 2 - XZ axes wander
56  // Value 3 - XYZ axes wander
57  // default is XY axes
58  switch(_flag) {
59  case 0: {
60  _wander_target = LVecBase3(_wander_radius * cos(theta), _wander_radius * sin(theta),0);
61  break;
62  }
63  case 1: {
64  _wander_target = LVecBase3(0, _wander_radius * cos(theta), _wander_radius * sin(theta));
65  break;
66  }
67  case 2: {
68  _wander_target = LVecBase3(_wander_radius * cos(theta), 0, _wander_radius * sin(theta));
69  break;
70  }
71  case 3: {
72  _wander_target = LVecBase3(_wander_radius * sin(theta) * cos(si), _wander_radius * sin(theta) * sin(si), _wander_radius * cos(theta));
73  break;
74  }
75  default: {
76  _wander_target = LVecBase3(_wander_radius * cos(theta), _wander_radius * sin(theta),0);
77  break;
78  }
79  }
80 }
81 
82 Wander::~Wander() {
83 }
84 
85 /////////////////////////////////////////////////////////////////////////////////
86 //
87 // Function : do_wander
88 // Description : This function performs the wander and returns the wander force which is used
89 // in the calculate_prioritized function.
90 // This function is not to be used by the user.
91 
92 /////////////////////////////////////////////////////////////////////////////////
93 
95  LVecBase3 present_pos = _ai_char->get_node_path().get_pos(_ai_char->get_char_render());
96  // Create the random slices to enable random movement of wander for x,y,z respectively
97  double time_slice_1 = random_clamped() * 1.5;
98  double time_slice_2 = random_clamped() * 1.5;
99  double time_slice_3 = random_clamped() * 1.5;
100  switch(_flag) {
101  case 0: {
102  _wander_target += LVecBase3(time_slice_1, time_slice_2, 0);
103  break;
104  }
105  case 1: {
106  _wander_target += LVecBase3(0, time_slice_1, time_slice_2);
107  break;
108  }
109  case 2: {
110  _wander_target += LVecBase3(time_slice_1, 0, time_slice_2);
111  break;
112  }
113  case 3: {
114  _wander_target += LVecBase3(time_slice_1, time_slice_2, time_slice_3);
115  break;
116  }
117 
118  default: {
119  _wander_target = LVecBase3(time_slice_1, time_slice_2, 0);
120  }
121  }
122  _wander_target.normalize();
123  _wander_target *= _wander_radius;
124  LVecBase3 target = _ai_char->get_char_render().get_relative_vector(_ai_char->get_node_path(), LVector3::forward());
125  target.normalize();
126  // Project wander target onto global space
127  target = _wander_target + target;
128  LVecBase3 desired_target = present_pos + target;
129  LVecBase3 desired_force = desired_target - _ai_char->get_node_path().get_pos() ;
130  desired_force.normalize();
131  desired_force *= _ai_char->_movt_force;
132  double distance = (present_pos - _init_pos).length();
133  if(_area_of_effect > 0 && distance > _area_of_effect) {
134  LVecBase3 direction = present_pos - _init_pos;
135  direction.normalize();
136  desired_force = - direction * _ai_char->_movt_force;
137  LVecBase3 dirn = _ai_char->_steering->_steering_force;
138  dirn.normalize();
139  _ai_char->_steering->_steering_force = LVecBase3(0.0, 0.0, 0.0);
140  }
141  return desired_force;
142 }
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
LVector3 get_relative_vector(const NodePath &other, const LVecBase3 &vec) const
Given that the indicated vector is in the coordinate system of the other node, returns the same vecto...
Definition: nodePath.cxx:2212
static LVector3f forward(CoordinateSystem cs=CS_default)
Returns the forward vector for the given coordinate system.
Definition: lvector3.h:579
LPoint3 get_pos() const
Retrieves the translation component of the transform.
Definition: nodePath.cxx:1178
LVecBase3 do_wander()
This function performs the wander and returns the wander force which is used in the calculate_priorit...
Definition: wander.cxx:94
bool normalize()
Normalizes the vector in place.
Definition: lvecBase3.h:783