Panda3D
 All Classes Functions Variables Enumerations
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 ////////////////////////////////////////////////////////////////////
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 ////////////////////////////////////////////////////////////////////
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 ////////////////////////////////////////////////////////////////////
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 ////////////////////////////////////////////////////////////////////
231 void CollisionParabola::
232 register_with_read_factory() {
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 }
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
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
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
float length_squared() const
Returns the square of the vector&#39;s length, cheap and easy.
Definition: lvecBase3.h:748
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_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...
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 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.
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. ...
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 ...
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the &quot;origin&quot; of the solid for collision purposes.
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.