Panda3D
|
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 ¶ms) { 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 }