00001 // Filename: collisionSegment.cxx 00002 // Created by: drose (30Jan01) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 00020 #include "collisionSegment.h" 00021 #include "collisionHandler.h" 00022 #include "collisionEntry.h" 00023 #include "config_collide.h" 00024 00025 #include "geom.h" 00026 #include "lensNode.h" 00027 #include "geomNode.h" 00028 #include "lens.h" 00029 #include "geomLine.h" 00030 #include "geometricBoundingVolume.h" 00031 #include "datagram.h" 00032 #include "datagramIterator.h" 00033 #include "bamReader.h" 00034 #include "bamWriter.h" 00035 00036 TypeHandle CollisionSegment::_type_handle; 00037 00038 00039 //////////////////////////////////////////////////////////////////// 00040 // Function: CollisionSegment::make_copy 00041 // Access: Public, Virtual 00042 // Description: 00043 //////////////////////////////////////////////////////////////////// 00044 CollisionSolid *CollisionSegment:: 00045 make_copy() { 00046 return new CollisionSegment(*this); 00047 } 00048 00049 //////////////////////////////////////////////////////////////////// 00050 // Function: CollisionSegment::test_intersection 00051 // Access: Public, Virtual 00052 // Description: 00053 //////////////////////////////////////////////////////////////////// 00054 PT(CollisionEntry) CollisionSegment:: 00055 test_intersection(const CollisionEntry &entry) const { 00056 return entry.get_into()->test_intersection_from_segment(entry); 00057 } 00058 00059 //////////////////////////////////////////////////////////////////// 00060 // Function: CollisionSegment::xform 00061 // Access: Public, Virtual 00062 // Description: Transforms the solid by the indicated matrix. 00063 //////////////////////////////////////////////////////////////////// 00064 void CollisionSegment:: 00065 xform(const LMatrix4f &mat) { 00066 _a = _a * mat; 00067 _b = _b * mat; 00068 mark_viz_stale(); 00069 mark_bound_stale(); 00070 } 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: CollisionSegment::get_collision_origin 00074 // Access: Public, Virtual 00075 // Description: Returns the point in space deemed to be the "origin" 00076 // of the solid for collision purposes. The closest 00077 // intersection point to this origin point is considered 00078 // to be the most significant. 00079 //////////////////////////////////////////////////////////////////// 00080 LPoint3f CollisionSegment:: 00081 get_collision_origin() const { 00082 return get_point_a(); 00083 } 00084 00085 //////////////////////////////////////////////////////////////////// 00086 // Function: CollisionSegment::output 00087 // Access: Public, Virtual 00088 // Description: 00089 //////////////////////////////////////////////////////////////////// 00090 void CollisionSegment:: 00091 output(ostream &out) const { 00092 out << "segment, a (" << _a << "), b (" << _b << ")"; 00093 } 00094 00095 //////////////////////////////////////////////////////////////////// 00096 // Function: CollisionSegment::set_from_lens 00097 // Access: Public 00098 // Description: Accepts a LensNode and a 2-d point in the range 00099 // [-1,1]. Sets the CollisionSegment so that it begins at 00100 // the LensNode's near plane and extends to the 00101 // far plane, making it suitable for picking objects 00102 // from the screen given a camera and a mouse location. 00103 // 00104 // Returns true if the point was acceptable, false 00105 // otherwise. 00106 //////////////////////////////////////////////////////////////////// 00107 bool CollisionSegment:: 00108 set_from_lens(LensNode *camera, const LPoint2f &point) { 00109 Lens *proj = camera->get_lens(); 00110 00111 bool success = true; 00112 if (!proj->extrude(point, _a, _b)) { 00113 _a = LPoint3f::origin(); 00114 _b = _a + LVector3f::forward(); 00115 success = false; 00116 } 00117 00118 mark_bound_stale(); 00119 mark_viz_stale(); 00120 00121 return success; 00122 } 00123 00124 //////////////////////////////////////////////////////////////////// 00125 // Function: CollisionSegment::recompute_bound 00126 // Access: Protected, Virtual 00127 // Description: 00128 //////////////////////////////////////////////////////////////////// 00129 BoundingVolume *CollisionSegment:: 00130 recompute_bound() { 00131 BoundingVolume *bound = BoundedObject::recompute_bound(); 00132 00133 if (bound->is_of_type(GeometricBoundingVolume::get_class_type())) { 00134 GeometricBoundingVolume *gbound; 00135 DCAST_INTO_R(gbound, bound, bound); 00136 00137 // This makes the assumption that _a and _b are laid out 00138 // sequentially in memory. It works because that's they way 00139 // they're defined in the class. 00140 nassertr(&_a + 1 == &_b, bound); 00141 gbound->around(&_a, &_b + 1); 00142 } 00143 00144 return bound; 00145 } 00146 00147 //////////////////////////////////////////////////////////////////// 00148 // Function: CollisionSegment::fill_viz_geom 00149 // Access: Protected, Virtual 00150 // Description: Fills the _viz_geom GeomNode up with Geoms suitable 00151 // for rendering this solid. 00152 //////////////////////////////////////////////////////////////////// 00153 void CollisionSegment:: 00154 fill_viz_geom() { 00155 if (collide_cat.is_debug()) { 00156 collide_cat.debug() 00157 << "Recomputing viz for " << *this << "\n"; 00158 } 00159 00160 GeomLine *segment = new GeomLine; 00161 PTA_Vertexf verts; 00162 PTA_Colorf colors; 00163 verts.push_back(_a); 00164 verts.push_back(_b); 00165 colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)); 00166 segment->set_coords(verts); 00167 segment->set_colors(colors, G_OVERALL); 00168 00169 segment->set_num_prims(1); 00170 00171 _viz_geom->add_geom(segment, get_other_viz_state()); 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: CollisionSegment::register_with_read_factory 00176 // Access: Public, Static 00177 // Description: Tells the BamReader how to create objects of type 00178 // CollisionSegment. 00179 //////////////////////////////////////////////////////////////////// 00180 void CollisionSegment:: 00181 register_with_read_factory() { 00182 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00183 } 00184 00185 //////////////////////////////////////////////////////////////////// 00186 // Function: CollisionSegment::write_datagram 00187 // Access: Public, Virtual 00188 // Description: Writes the contents of this object to the datagram 00189 // for shipping out to a Bam file. 00190 //////////////////////////////////////////////////////////////////// 00191 void CollisionSegment:: 00192 write_datagram(BamWriter *manager, Datagram &dg) { 00193 CollisionSolid::write_datagram(manager, dg); 00194 _a.write_datagram(dg); 00195 _b.write_datagram(dg); 00196 } 00197 00198 //////////////////////////////////////////////////////////////////// 00199 // Function: CollisionSegment::make_from_bam 00200 // Access: Protected, Static 00201 // Description: This function is called by the BamReader's factory 00202 // when a new object of type CollisionSegment is encountered 00203 // in the Bam file. It should create the CollisionSegment 00204 // and extract its information from the file. 00205 //////////////////////////////////////////////////////////////////// 00206 TypedWritable *CollisionSegment:: 00207 make_from_bam(const FactoryParams ¶ms) { 00208 CollisionSegment *node = new CollisionSegment(); 00209 DatagramIterator scan; 00210 BamReader *manager; 00211 00212 parse_params(params, scan, manager); 00213 node->fillin(scan, manager); 00214 00215 return node; 00216 } 00217 00218 //////////////////////////////////////////////////////////////////// 00219 // Function: CollisionSegment::fillin 00220 // Access: Protected 00221 // Description: This internal function is called by make_from_bam to 00222 // read in all of the relevant data from the BamFile for 00223 // the new CollisionSegment. 00224 //////////////////////////////////////////////////////////////////// 00225 void CollisionSegment:: 00226 fillin(DatagramIterator &scan, BamReader *manager) { 00227 CollisionSolid::fillin(scan, manager); 00228 _a.read_datagram(scan); 00229 _b.read_datagram(scan); 00230 }