Panda3D

collisionSegment.cxx

00001 // Filename: collisionSegment.cxx
00002 // Created by:  drose (30Jan01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 
00016 #include "collisionSegment.h"
00017 #include "collisionHandler.h"
00018 #include "collisionEntry.h"
00019 #include "config_collide.h"
00020 #include "geom.h"
00021 #include "lensNode.h"
00022 #include "geomNode.h"
00023 #include "lens.h"
00024 #include "geometricBoundingVolume.h"
00025 #include "datagram.h"
00026 #include "datagramIterator.h"
00027 #include "bamReader.h"
00028 #include "bamWriter.h"
00029 #include "geom.h"
00030 #include "geomLines.h"
00031 #include "boundingHexahedron.h"
00032 #include "geomVertexWriter.h"
00033 
00034 TypeHandle CollisionSegment::_type_handle;
00035 
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: CollisionSegment::make_copy
00039 //       Access: Public, Virtual
00040 //  Description:
00041 ////////////////////////////////////////////////////////////////////
00042 CollisionSolid *CollisionSegment::
00043 make_copy() {
00044   return new CollisionSegment(*this);
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: CollisionSegment::test_intersection
00049 //       Access: Public, Virtual
00050 //  Description:
00051 ////////////////////////////////////////////////////////////////////
00052 PT(CollisionEntry) CollisionSegment::
00053 test_intersection(const CollisionEntry &entry) const {
00054   return entry.get_into()->test_intersection_from_segment(entry);
00055 }
00056 
00057 ////////////////////////////////////////////////////////////////////
00058 //     Function: CollisionSegment::xform
00059 //       Access: Public, Virtual
00060 //  Description: Transforms the solid by the indicated matrix.
00061 ////////////////////////////////////////////////////////////////////
00062 void CollisionSegment::
00063 xform(const LMatrix4 &mat) {
00064   _a = _a * mat;
00065   _b = _b * mat;
00066 
00067   CollisionSolid::xform(mat);
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: CollisionSegment::get_collision_origin
00072 //       Access: Public, Virtual
00073 //  Description: Returns the point in space deemed to be the "origin"
00074 //               of the solid for collision purposes.  The closest
00075 //               intersection point to this origin point is considered
00076 //               to be the most significant.
00077 ////////////////////////////////////////////////////////////////////
00078 LPoint3 CollisionSegment::
00079 get_collision_origin() const {
00080   return get_point_a();
00081 }
00082 
00083 ////////////////////////////////////////////////////////////////////
00084 //     Function: CollisionSegment::output
00085 //       Access: Public, Virtual
00086 //  Description:
00087 ////////////////////////////////////////////////////////////////////
00088 void CollisionSegment::
00089 output(ostream &out) const {
00090   out << "segment, a (" << _a << "), b (" << _b << ")";
00091 }
00092 
00093 ////////////////////////////////////////////////////////////////////
00094 //     Function: CollisionSegment::set_from_lens
00095 //       Access: Public
00096 //  Description: Accepts a LensNode and a 2-d point in the range
00097 //               [-1,1].  Sets the CollisionSegment so that it begins at
00098 //               the LensNode's near plane and extends to the
00099 //               far plane, making it suitable for picking objects
00100 //               from the screen given a camera and a mouse location.
00101 //
00102 //               Returns true if the point was acceptable, false
00103 //               otherwise.
00104 ////////////////////////////////////////////////////////////////////
00105 bool CollisionSegment::
00106 set_from_lens(LensNode *camera, const LPoint2 &point) {
00107   Lens *proj = camera->get_lens();
00108 
00109   bool success = true;
00110   if (!proj->extrude(point, _a, _b)) {
00111     _a = LPoint3::origin();
00112     _b = _a + LVector3::forward();
00113     success = false;
00114   }
00115 
00116   mark_internal_bounds_stale();
00117   mark_viz_stale();
00118 
00119   return success;
00120 }
00121 
00122 ////////////////////////////////////////////////////////////////////
00123 //     Function: CollisionSegment::compute_internal_bounds
00124 //       Access: Protected, Virtual
00125 //  Description:
00126 ////////////////////////////////////////////////////////////////////
00127 PT(BoundingVolume) CollisionSegment::
00128 compute_internal_bounds() const {
00129 
00130   LVector3 pdelta = _b - _a;
00131 
00132   // If p1 and p2 are sufficiently close, just put a sphere around
00133   // them.
00134   PN_stdfloat d2 = pdelta.length_squared();
00135   if (d2 < collision_parabola_bounds_threshold * collision_parabola_bounds_threshold) {
00136     LPoint3 pmid = (_a + _b) * 0.5f;
00137     return new BoundingSphere(pmid, csqrt(d2) * 0.5f);
00138   }
00139 
00140   LMatrix4 from_segment;
00141   look_at(from_segment, pdelta, LPoint3(0,0,1), CS_zup_right);
00142   from_segment.set_row(3, _a);
00143   
00144   PN_stdfloat max_y =  sqrt(d2) + 0.01;
00145   PT(BoundingHexahedron) volume = 
00146     new BoundingHexahedron(LPoint3(-0.01, max_y, -0.01), LPoint3(0.01, max_y, -0.01),
00147                            LPoint3(0.01, max_y, 0.01), LPoint3(-0.01, max_y,  0.01),
00148                            LPoint3(-0.01, -0.01, -0.01), LPoint3(0.01, 0.01, -0.01),
00149                            LPoint3(0.01, -0.01, 0.01), LPoint3(-0.01, -0.01, 0.01));
00150 
00151   volume->xform(from_segment);
00152   return volume.p();
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: CollisionSegment::fill_viz_geom
00157 //       Access: Protected, Virtual
00158 //  Description: Fills the _viz_geom GeomNode up with Geoms suitable
00159 //               for rendering this solid.
00160 ////////////////////////////////////////////////////////////////////
00161 void CollisionSegment::
00162 fill_viz_geom() {
00163   if (collide_cat.is_debug()) {
00164     collide_cat.debug()
00165       << "Recomputing viz for " << *this << "\n";
00166   }
00167 
00168   PT(GeomVertexData) vdata = new GeomVertexData
00169     ("collision", GeomVertexFormat::get_v3cp(),
00170      Geom::UH_static);
00171   GeomVertexWriter vertex(vdata, InternalName::get_vertex());
00172   
00173   vertex.add_data3(_a);
00174   vertex.add_data3(_b);
00175   
00176   PT(GeomLines) line = new GeomLines(Geom::UH_static);
00177   line->add_next_vertices(2);
00178   line->close_primitive();
00179   
00180   PT(Geom) geom = new Geom(vdata);
00181   geom->add_primitive(line);
00182   
00183   _viz_geom->add_geom(geom, get_other_viz_state());
00184   _bounds_viz_geom->add_geom(geom, get_other_bounds_viz_state());
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: CollisionSegment::register_with_read_factory
00189 //       Access: Public, Static
00190 //  Description: Tells the BamReader how to create objects of type
00191 //               CollisionSegment.
00192 ////////////////////////////////////////////////////////////////////
00193 void CollisionSegment::
00194 register_with_read_factory() {
00195   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00196 }
00197 
00198 ////////////////////////////////////////////////////////////////////
00199 //     Function: CollisionSegment::write_datagram
00200 //       Access: Public, Virtual
00201 //  Description: Writes the contents of this object to the datagram
00202 //               for shipping out to a Bam file.
00203 ////////////////////////////////////////////////////////////////////
00204 void CollisionSegment::
00205 write_datagram(BamWriter *manager, Datagram &dg) {
00206   CollisionSolid::write_datagram(manager, dg);
00207   _a.write_datagram(dg);
00208   _b.write_datagram(dg);
00209 }
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: CollisionSegment::make_from_bam
00213 //       Access: Protected, Static
00214 //  Description: This function is called by the BamReader's factory
00215 //               when a new object of type CollisionSegment is encountered
00216 //               in the Bam file.  It should create the CollisionSegment
00217 //               and extract its information from the file.
00218 ////////////////////////////////////////////////////////////////////
00219 TypedWritable *CollisionSegment::
00220 make_from_bam(const FactoryParams &params) {
00221   CollisionSegment *node = new CollisionSegment();
00222   DatagramIterator scan;
00223   BamReader *manager;
00224 
00225   parse_params(params, scan, manager);
00226   node->fillin(scan, manager);
00227 
00228   return node;
00229 }
00230 
00231 ////////////////////////////////////////////////////////////////////
00232 //     Function: CollisionSegment::fillin
00233 //       Access: Protected
00234 //  Description: This internal function is called by make_from_bam to
00235 //               read in all of the relevant data from the BamFile for
00236 //               the new CollisionSegment.
00237 ////////////////////////////////////////////////////////////////////
00238 void CollisionSegment::
00239 fillin(DatagramIterator &scan, BamReader *manager) {
00240   CollisionSolid::fillin(scan, manager);
00241   _a.read_datagram(scan);
00242   _b.read_datagram(scan);
00243 }
 All Classes Functions Variables Enumerations