Panda3D
collisionParabola.cxx
1 // Filename: collisionParabola.cxx
2 // Created by: drose (11Oct07)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "collisionParabola.h"
16 #include "collisionEntry.h"
17 #include "datagram.h"
18 #include "datagramIterator.h"
19 #include "bamReader.h"
20 #include "bamWriter.h"
21 #include "geom.h"
22 #include "geomLinestrips.h"
23 #include "geomVertexWriter.h"
24 #include "boundingHexahedron.h"
25 #include "boundingSphere.h"
26 #include "look_at.h"
27 
28 PStatCollector CollisionParabola::_volume_pcollector(
29  "Collision Volumes:CollisionParabola");
30 PStatCollector CollisionParabola::_test_pcollector(
31  "Collision Tests:CollisionParabola");
32 TypeHandle CollisionParabola::_type_handle;
33 
34 ////////////////////////////////////////////////////////////////////
35 // Function: CollisionParabola::get_collision_origin
36 // Access: Public, Virtual
37 // Description: Returns the point in space deemed to be the "origin"
38 // of the solid for collision purposes. The closest
39 // intersection point to this origin point is considered
40 // to be the most significant.
41 ////////////////////////////////////////////////////////////////////
44  return _parabola.calc_point(_t1);
45 }
46 
47 ////////////////////////////////////////////////////////////////////
48 // Function: CollisionParabola::make_copy
49 // Access: Public, Virtual
50 // Description:
51 ////////////////////////////////////////////////////////////////////
52 CollisionSolid *CollisionParabola::
53 make_copy() {
54  return new CollisionParabola(*this);
55 }
56 
57 
58 ////////////////////////////////////////////////////////////////////
59 // Function: CollisionParabola::test_intersection
60 // Access: Public, Virtual
61 // Description:
62 ////////////////////////////////////////////////////////////////////
63 PT(CollisionEntry) CollisionParabola::
64 test_intersection(const CollisionEntry &entry) const {
65  return entry.get_into()->test_intersection_from_parabola(entry);
66 }
67 
68 ////////////////////////////////////////////////////////////////////
69 // Function: CollisionParabola::xform
70 // Access: Public, Virtual
71 // Description: Transforms the solid by the indicated matrix.
72 ////////////////////////////////////////////////////////////////////
73 void CollisionParabola::
74 xform(const LMatrix4 &mat) {
75  _parabola.xform(mat);
76 
77  mark_viz_stale();
78  mark_internal_bounds_stale();
79 }
80 
81 ////////////////////////////////////////////////////////////////////
82 // Function: CollisionParabola::get_volume_pcollector
83 // Access: Public, Virtual
84 // Description: Returns a PStatCollector that is used to count the
85 // number of bounding volume tests made against a solid
86 // of this type in a given frame.
87 ////////////////////////////////////////////////////////////////////
90  return _volume_pcollector;
91 }
92 
93 ////////////////////////////////////////////////////////////////////
94 // Function: CollisionParabola::get_test_pcollector
95 // Access: Public, Virtual
96 // Description: Returns a PStatCollector that is used to count the
97 // number of intersection tests made against a solid
98 // of this type in a given frame.
99 ////////////////////////////////////////////////////////////////////
102  return _test_pcollector;
103 }
104 
105 ////////////////////////////////////////////////////////////////////
106 // Function: CollisionParabola::output
107 // Access: Public, Virtual
108 // Description:
109 ////////////////////////////////////////////////////////////////////
110 void CollisionParabola::
111 output(ostream &out) const {
112  out << _parabola << ", t1 = " << _t1 << ", t2 = " << _t2;
113 }
114 
115 ////////////////////////////////////////////////////////////////////
116 // Function: CollisionParabola::compute_internal_bounds
117 // Access: Protected, Virtual
118 // Description:
119 ////////////////////////////////////////////////////////////////////
120 PT(BoundingVolume) CollisionParabola::
121 compute_internal_bounds() const {
122  LPoint3 p1 = _parabola.calc_point(get_t1());
123  LPoint3 p2 = _parabola.calc_point(get_t2());
124  LVector3 pdelta = p2 - p1;
125 
126  // If p1 and p2 are sufficiently close, just put a sphere around
127  // them.
128  PN_stdfloat d2 = pdelta.length_squared();
129  if (d2 < collision_parabola_bounds_threshold * collision_parabola_bounds_threshold) {
130  LPoint3 pmid = (p1 + p2) * 0.5f;
131  return new BoundingSphere(pmid, csqrt(d2) * 0.5f);
132  }
133 
134  // OK, the more general bounding volume. We use BoundingHexahedron
135  // to define a very thin box that roughly bounds the parabola's arc.
136  // We must use BoundingHexahedron instead of BoundingBox, because
137  // the box will not be axis-aligned, and might be inflated too large
138  // if we insist on using the axis-aligned BoundingBox.
139 
140  // We first define "parabola space" as a coordinate space such that
141  // the YZ plane of parabola space corresponds to the plane of the
142  // parabola.
143 
144  // We have to be explicit about the coordinate system--we
145  // specifically mean CS_zup_right here, to make the YZ plane.
146 
147  LMatrix4 from_parabola;
148  look_at(from_parabola, pdelta, -_parabola.get_a(), CS_zup_right);
149  from_parabola.set_row(3, p1);
150 
151  // The matrix that computes from world space to parabola space is
152  // the inverse of that which we just computed.
153  LMatrix4 to_parabola;
154  to_parabola.invert_from(from_parabola);
155 
156  // Now convert the parabola itself into parabola space.
157  LParabola psp = _parabola;
158  psp.xform(to_parabola);
159 
160  LPoint3 pp2 = psp.calc_point(get_t2());
161  PN_stdfloat max_y = pp2[1];
162 
163  // We compute a few points along the parabola to attempt to get the
164  // minmax.
165  PN_stdfloat min_z = 0.0f;
166  PN_stdfloat max_z = 0.0f;
167  int num_points = collision_parabola_bounds_sample;
168  for (int i = 0; i < num_points; ++i) {
169  double t = (double)(i + 1) / (double)(num_points + 1);
170  LPoint3 p = psp.calc_point(get_t1() + t * (get_t2() - get_t1()));
171  min_z = min(min_z, p[2]);
172  max_z = max(max_z, p[2]);
173  }
174 
175  // That gives us a simple bounding volume in parabola space.
176  PT(BoundingHexahedron) volume =
177  new BoundingHexahedron(LPoint3(-0.01, max_y, min_z), LPoint3(0.01, max_y, min_z),
178  LPoint3(0.01, max_y, max_z), LPoint3(-0.01, max_y, max_z),
179  LPoint3(-0.01, 0, min_z), LPoint3(0.01, 0, min_z),
180  LPoint3(0.01, 0, max_z), LPoint3(-0.01, 0, max_z));
181  // And convert that back into real space.
182  volume->xform(from_parabola);
183  return volume.p();
184 }
185 
186 ////////////////////////////////////////////////////////////////////
187 // Function: CollisionParabola::fill_viz_geom
188 // Access: Protected, Virtual
189 // Description: Fills the _viz_geom GeomNode up with Geoms suitable
190 // for rendering this solid.
191 ////////////////////////////////////////////////////////////////////
192 void CollisionParabola::
193 fill_viz_geom() {
194  if (collide_cat.is_debug()) {
195  collide_cat.debug()
196  << "Recomputing viz for " << *this << "\n";
197  }
198 
199  static const int num_points = 100;
200 
201  PT(GeomVertexData) vdata = new GeomVertexData
202  ("collision", GeomVertexFormat::get_v3cp(),
203  Geom::UH_static);
204  GeomVertexWriter vertex(vdata, InternalName::get_vertex());
205  GeomVertexWriter color(vdata, InternalName::get_color());
206 
207  for (int i = 0; i < num_points; i++) {
208  double t = ((double)i / (double)num_points);
209  vertex.add_data3(_parabola.calc_point(_t1 + t * (_t2 - _t1)));
210 
211  color.add_data4(LColor(1.0f, 1.0f, 1.0f, 0.0f) +
212  t * LColor(0.0f, 0.0f, 0.0f, 1.0f));
213  }
214 
215  PT(GeomLinestrips) line = new GeomLinestrips(Geom::UH_static);
216  line->add_next_vertices(num_points);
217  line->close_primitive();
218 
219  PT(Geom) geom = new Geom(vdata);
220  geom->add_primitive(line);
221 
222  _viz_geom->add_geom(geom, get_other_viz_state());
223  _bounds_viz_geom->add_geom(geom, get_other_bounds_viz_state());
224 }
225 
226 ////////////////////////////////////////////////////////////////////
227 // Function: CollisionParabola::register_with_read_factory
228 // Access: Public, Static
229 // Description: Factory method to generate a CollisionParabola object
230 ////////////////////////////////////////////////////////////////////
233  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
234 }
235 
236 ////////////////////////////////////////////////////////////////////
237 // Function: CollisionParabola::write_datagram
238 // Access: Public
239 // Description: Function to write the important information in
240 // the particular object to a Datagram
241 ////////////////////////////////////////////////////////////////////
244  CollisionSolid::write_datagram(manager, me);
245  _parabola.write_datagram(me);
246  me.add_stdfloat(_t1);
247  me.add_stdfloat(_t2);
248 }
249 
250 ////////////////////////////////////////////////////////////////////
251 // Function: CollisionParabola::make_from_bam
252 // Access: Protected
253 // Description: Factory method to generate a CollisionParabola object
254 ////////////////////////////////////////////////////////////////////
255 TypedWritable *CollisionParabola::
256 make_from_bam(const FactoryParams &params) {
258  DatagramIterator scan;
259  BamReader *manager;
260 
261  parse_params(params, scan, manager);
262  me->fillin(scan, manager);
263  return me;
264 }
265 
266 ////////////////////////////////////////////////////////////////////
267 // Function: CollisionParabola::fillin
268 // Access: Protected
269 // Description: Function that reads out of the datagram (or asks
270 // manager to read) all of the data that is needed to
271 // re-create this object and stores it in the appropiate
272 // place
273 ////////////////////////////////////////////////////////////////////
274 void CollisionParabola::
275 fillin(DatagramIterator& scan, BamReader* manager) {
276  CollisionSolid::fillin(scan, manager);
277  _parabola.read_datagram(scan);
278  _t1 = scan.get_stdfloat();
279  _t2 = scan.get_stdfloat();
280 }
float length_squared() const
Returns the square of the vector&#39;s length, cheap and easy.
Definition: lvecBase3.h:749
PN_stdfloat get_t1() const
Returns the starting point on the parabola.
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:122
PN_stdfloat get_t2() const
Returns the ending point on the parabola.
The abstract base class for all things that can collide with other things in the world, and all the things they can collide with (except geometry).
This defines a bounding sphere, consisting of a center and a radius.
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:37
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
void add_data4(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z, PN_stdfloat w)
Sets the write row to a particular 4-component value, and advances the write row. ...
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
Definition: datagram.I:240
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
A lightweight class that represents a single element that may be timed and/or counted via stats...
const CollisionSolid * get_into() const
Returns the CollisionSolid pointer for the particular solid was collided into.
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
Defines a single collision event.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
Definition: geom.h:58
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
bool invert_from(const LMatrix4f &other)
Computes the inverse of the other matrix, and stores the result in this matrix.
Definition: lmatrix.h:2173
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:90
This is the base class for all three-component vectors and points.
Definition: lvecBase4.h:111
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
CollisionParabola()
Creates an invalid parabola.
This defines a parabolic arc, or subset of an arc, similar to the path of a projectile or falling obj...
Defines a series of line strips.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Function to write the important information in the particular object to a Datagram.
static void register_with_read_factory()
Factory method to generate a CollisionParabola object.
void set_row(int row, const LVecBase4f &v)
Replaces the indicated row of the matrix.
Definition: lmatrix.h:1187
A class to retrieve the individual data elements previously stored in a Datagram. ...
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the "origin" of the solid for collision purposes.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
This defines a bounding convex hexahedron.