00001 // Filename: collisionRay.cxx 00002 // Created by: drose (22Jun00) 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 #include "collisionRay.h" 00020 #include "collisionHandler.h" 00021 #include "collisionEntry.h" 00022 #include "config_collide.h" 00023 #include "geom.h" 00024 #include "geomNode.h" 00025 #include "geomLinestrip.h" 00026 #include "boundingLine.h" 00027 #include "lensNode.h" 00028 #include "lens.h" 00029 #include "datagram.h" 00030 #include "datagramIterator.h" 00031 #include "bamReader.h" 00032 #include "bamWriter.h" 00033 00034 TypeHandle CollisionRay::_type_handle; 00035 00036 00037 //////////////////////////////////////////////////////////////////// 00038 // Function: CollisionRay::make_copy 00039 // Access: Public, Virtual 00040 // Description: 00041 //////////////////////////////////////////////////////////////////// 00042 CollisionSolid *CollisionRay:: 00043 make_copy() { 00044 return new CollisionRay(*this); 00045 } 00046 00047 //////////////////////////////////////////////////////////////////// 00048 // Function: CollisionRay::test_intersection 00049 // Access: Public, Virtual 00050 // Description: 00051 //////////////////////////////////////////////////////////////////// 00052 PT(CollisionEntry) CollisionRay:: 00053 test_intersection(const CollisionEntry &entry) const { 00054 return entry.get_into()->test_intersection_from_ray(entry); 00055 } 00056 00057 //////////////////////////////////////////////////////////////////// 00058 // Function: CollisionRay::xform 00059 // Access: Public, Virtual 00060 // Description: Transforms the solid by the indicated matrix. 00061 //////////////////////////////////////////////////////////////////// 00062 void CollisionRay:: 00063 xform(const LMatrix4f &mat) { 00064 _origin = _origin * mat; 00065 _direction = _direction * mat; 00066 mark_viz_stale(); 00067 mark_bound_stale(); 00068 } 00069 00070 //////////////////////////////////////////////////////////////////// 00071 // Function: CollisionRay::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 LPoint3f CollisionRay:: 00079 get_collision_origin() const { 00080 return get_origin(); 00081 } 00082 00083 //////////////////////////////////////////////////////////////////// 00084 // Function: CollisionRay::output 00085 // Access: Public, Virtual 00086 // Description: 00087 //////////////////////////////////////////////////////////////////// 00088 void CollisionRay:: 00089 output(ostream &out) const { 00090 out << "ray, o (" << _origin << "), d (" << _direction << ")"; 00091 } 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: CollisionRay::set_from_lens 00095 // Access: Public 00096 // Description: Accepts a LensNode and a 2-d point in the range 00097 // [-1,1]. Sets the CollisionRay so that it begins at 00098 // the LensNode's near plane and extends to 00099 // infinity, making it suitable for picking objects from 00100 // the screen given a camera and a mouse location. 00101 // 00102 // Returns true if the point was acceptable, false 00103 // otherwise. 00104 //////////////////////////////////////////////////////////////////// 00105 bool CollisionRay:: 00106 set_from_lens(LensNode *camera, const LPoint2f &point) { 00107 Lens *lens = camera->get_lens(); 00108 00109 bool success = true; 00110 LPoint3f near_point, far_point; 00111 if (!lens->extrude(point, near_point, far_point)) { 00112 _origin = LPoint3f::origin(); 00113 _direction = LVector3f::forward(); 00114 success = false; 00115 } else { 00116 _origin = near_point; 00117 _direction = far_point - near_point; 00118 } 00119 00120 mark_bound_stale(); 00121 mark_viz_stale(); 00122 00123 return success; 00124 } 00125 00126 //////////////////////////////////////////////////////////////////// 00127 // Function: CollisionRay::recompute_bound 00128 // Access: Protected, Virtual 00129 // Description: 00130 //////////////////////////////////////////////////////////////////// 00131 BoundingVolume *CollisionRay:: 00132 recompute_bound() { 00133 BoundedObject::recompute_bound(); 00134 // Less than ideal: we throw away whatever we just allocated in 00135 // BoundedObject. 00136 return set_bound_ptr(new BoundingLine(_origin, _origin + _direction)); 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: CollisionRay::fill_viz_geom 00141 // Access: Protected, Virtual 00142 // Description: Fills the _viz_geom GeomNode up with Geoms suitable 00143 // for rendering this solid. 00144 //////////////////////////////////////////////////////////////////// 00145 void CollisionRay:: 00146 fill_viz_geom() { 00147 if (collide_cat.is_debug()) { 00148 collide_cat.debug() 00149 << "Recomputing viz for " << *this << "\n"; 00150 } 00151 00152 GeomLinestrip *ray = new GeomLinestrip; 00153 PTA_Vertexf verts; 00154 PTA_Colorf colors; 00155 PTA_int lengths; 00156 00157 #define NUM_POINTS 100 00158 verts.reserve(NUM_POINTS); 00159 colors.reserve(NUM_POINTS); 00160 00161 for (int i = 0; i < NUM_POINTS; i++) { 00162 verts.push_back(_origin + (double)i * _direction); 00163 colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f)+ 00164 ((double)i / 100.0) * Colorf(0.0f, 0.0f, 0.0f, -1.0f)); 00165 } 00166 ray->set_coords(verts); 00167 ray->set_colors(colors, G_PER_VERTEX); 00168 00169 lengths.push_back(NUM_POINTS-1); 00170 ray->set_lengths(lengths); 00171 00172 ray->set_num_prims(1); 00173 00174 _viz_geom->add_geom(ray, get_other_viz_state()); 00175 } 00176 00177 //////////////////////////////////////////////////////////////////// 00178 // Function: CollisionRay::register_with_read_factory 00179 // Access: Public, Static 00180 // Description: Tells the BamReader how to create objects of type 00181 // CollisionRay. 00182 //////////////////////////////////////////////////////////////////// 00183 void CollisionRay:: 00184 register_with_read_factory() { 00185 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00186 } 00187 00188 //////////////////////////////////////////////////////////////////// 00189 // Function: CollisionRay::write_datagram 00190 // Access: Public, Virtual 00191 // Description: Writes the contents of this object to the datagram 00192 // for shipping out to a Bam file. 00193 //////////////////////////////////////////////////////////////////// 00194 void CollisionRay:: 00195 write_datagram(BamWriter *manager, Datagram &dg) { 00196 CollisionSolid::write_datagram(manager, dg); 00197 _origin.write_datagram(dg); 00198 _direction.write_datagram(dg); 00199 } 00200 00201 //////////////////////////////////////////////////////////////////// 00202 // Function: CollisionRay::make_from_bam 00203 // Access: Protected, Static 00204 // Description: This function is called by the BamReader's factory 00205 // when a new object of type CollisionRay is encountered 00206 // in the Bam file. It should create the CollisionRay 00207 // and extract its information from the file. 00208 //////////////////////////////////////////////////////////////////// 00209 TypedWritable *CollisionRay:: 00210 make_from_bam(const FactoryParams ¶ms) { 00211 CollisionRay *node = new CollisionRay(); 00212 DatagramIterator scan; 00213 BamReader *manager; 00214 00215 parse_params(params, scan, manager); 00216 node->fillin(scan, manager); 00217 00218 return node; 00219 } 00220 00221 //////////////////////////////////////////////////////////////////// 00222 // Function: CollisionRay::fillin 00223 // Access: Protected 00224 // Description: This internal function is called by make_from_bam to 00225 // read in all of the relevant data from the BamFile for 00226 // the new CollisionRay. 00227 //////////////////////////////////////////////////////////////////// 00228 void CollisionRay:: 00229 fillin(DatagramIterator &scan, BamReader *manager) { 00230 CollisionSolid::fillin(scan, manager); 00231 _origin.read_datagram(scan); 00232 _direction.read_datagram(scan); 00233 }