00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "collisionPlane.h"
00021 #include "collisionHandler.h"
00022 #include "collisionEntry.h"
00023 #include "collisionSphere.h"
00024 #include "collisionRay.h"
00025 #include "config_collide.h"
00026
00027 #include "pointerToArray.h"
00028 #include "geomNode.h"
00029 #include "geom.h"
00030 #include "datagram.h"
00031 #include "datagramIterator.h"
00032 #include "bamReader.h"
00033 #include "bamWriter.h"
00034 #include "omniBoundingVolume.h"
00035 #include "geomQuad.h"
00036
00037 TypeHandle CollisionPlane::_type_handle;
00038
00039
00040
00041
00042
00043
00044 CollisionSolid *CollisionPlane::
00045 make_copy() {
00046 return new CollisionPlane(*this);
00047 }
00048
00049
00050
00051
00052
00053
00054 void CollisionPlane::
00055 xform(const LMatrix4f &mat) {
00056 _plane = _plane * mat;
00057 mark_viz_stale();
00058 mark_bound_stale();
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 LPoint3f CollisionPlane::
00070 get_collision_origin() const {
00071
00072
00073
00074 return LPoint3f::origin();
00075 }
00076
00077
00078
00079
00080
00081
00082 void CollisionPlane::
00083 output(ostream &out) const {
00084 out << "cplane, (" << _plane << ")";
00085 }
00086
00087
00088
00089
00090
00091
00092 BoundingVolume *CollisionPlane::
00093 recompute_bound() {
00094
00095 BoundedObject::recompute_bound();
00096
00097
00098 return set_bound_ptr(new OmniBoundingVolume);
00099 }
00100
00101
00102
00103
00104
00105
00106 PT(CollisionEntry) CollisionPlane::
00107 test_intersection_from_sphere(const CollisionEntry &entry) const {
00108 const CollisionSphere *sphere;
00109 DCAST_INTO_R(sphere, entry.get_from(), 0);
00110
00111 LPoint3f from_center = sphere->get_center() * entry.get_wrt_space();
00112 LVector3f from_radius_v =
00113 LVector3f(sphere->get_radius(), 0.0f, 0.0f) * entry.get_wrt_space();
00114 float from_radius = length(from_radius_v);
00115
00116 float dist = dist_to_plane(from_center);
00117 if (dist > from_radius) {
00118
00119 return NULL;
00120 }
00121
00122 if (collide_cat.is_debug()) {
00123 collide_cat.debug()
00124 << "intersection detected from " << *entry.get_from_node() << " into "
00125 << entry.get_into_node_path() << "\n";
00126 }
00127 PT(CollisionEntry) new_entry = new CollisionEntry(entry);
00128
00129 LVector3f from_normal = get_normal() * entry.get_inv_wrt_space();
00130 float from_depth = from_radius - dist;
00131
00132 new_entry->set_into_surface_normal(get_normal());
00133 new_entry->set_from_surface_normal(from_normal);
00134 new_entry->set_from_depth(from_depth);
00135 new_entry->set_into_intersection_point(from_center - get_normal() * dist);
00136
00137 return new_entry;
00138 }
00139
00140
00141
00142
00143
00144
00145 PT(CollisionEntry) CollisionPlane::
00146 test_intersection_from_ray(const CollisionEntry &entry) const {
00147 const CollisionRay *ray;
00148 DCAST_INTO_R(ray, entry.get_from(), 0);
00149
00150 LPoint3f from_origin = ray->get_origin() * entry.get_wrt_space();
00151 LVector3f from_direction = ray->get_direction() * entry.get_wrt_space();
00152
00153 float t;
00154 if (!_plane.intersects_line(t, from_origin, from_direction)) {
00155
00156 return NULL;
00157 }
00158
00159 if (t < 0.0f) {
00160
00161 return NULL;
00162 }
00163
00164 if (collide_cat.is_debug()) {
00165 collide_cat.debug()
00166 << "intersection detected from " << *entry.get_from_node() << " into "
00167 << entry.get_into_node_path() << "\n";
00168 }
00169 PT(CollisionEntry) new_entry = new CollisionEntry(entry);
00170
00171 LPoint3f into_intersection_point = from_origin + t * from_direction;
00172 new_entry->set_into_surface_normal(get_normal());
00173 new_entry->set_into_intersection_point(into_intersection_point);
00174
00175 return new_entry;
00176 }
00177
00178
00179
00180
00181
00182
00183
00184 void CollisionPlane::
00185 fill_viz_geom() {
00186 if (collide_cat.is_debug()) {
00187 collide_cat.debug()
00188 << "Recomputing viz for " << *this << "\n";
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 LPoint3f cp;
00205 LVector3f p1, p2, p3, p4;
00206
00207 LVector3f normal = get_normal();
00208 float D = _plane._d;
00209
00210 if (fabs(normal[0]) > fabs(normal[1]) &&
00211 fabs(normal[0]) > fabs(normal[2])) {
00212
00213 cp.set(-D / normal[0], 0.0f, 0.0f);
00214 p1 = LPoint3f(-(normal[1] + normal[2] + D)/normal[0], 1.0f, 1.0f) - cp;
00215
00216 } else if (fabs(normal[1]) > fabs(normal[2])) {
00217
00218 cp.set(0.0f, -D / normal[1], 0.0f);
00219 p1 = LPoint3f(1.0f, -(normal[0] + normal[2] + D)/normal[1], 1.0f) - cp;
00220
00221 } else {
00222
00223 cp.set(0.0f, 0.0f, -D / normal[2]);
00224 p1 = LPoint3f(1.0f, 1.0f, -(normal[0] + normal[1] + D)/normal[2]) - cp;
00225 }
00226
00227 p1.normalize();
00228 p2 = cross(normal, p1);
00229 p3 = cross(normal, p2);
00230 p4 = cross(normal, p3);
00231
00232 static const double plane_scale = 10.0;
00233
00234 PTA_Vertexf verts;
00235 verts.push_back(cp + p1 * plane_scale);
00236 verts.push_back(cp + p2 * plane_scale);
00237 verts.push_back(cp + p3 * plane_scale);
00238 verts.push_back(cp + p4 * plane_scale);
00239
00240 GeomQuad *quad = new GeomQuad;
00241 quad->set_coords(verts);
00242 quad->set_num_prims(1);
00243
00244 _viz_geom->add_geom(quad, get_solid_viz_state());
00245 _viz_geom->add_geom(quad, get_wireframe_viz_state());
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 void CollisionPlane::
00255 write_datagram(BamWriter *manager, Datagram &me)
00256 {
00257 CollisionSolid::write_datagram(manager, me);
00258 _plane.write_datagram(me);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 void CollisionPlane::
00270 fillin(DatagramIterator& scan, BamReader* manager)
00271 {
00272 CollisionSolid::fillin(scan, manager);
00273 _plane.read_datagram(scan);
00274 }
00275
00276
00277
00278
00279
00280
00281 TypedWritable* CollisionPlane::
00282 make_CollisionPlane(const FactoryParams ¶ms)
00283 {
00284 CollisionPlane *me = new CollisionPlane;
00285 DatagramIterator scan;
00286 BamReader *manager;
00287
00288 parse_params(params, scan, manager);
00289 me->fillin(scan, manager);
00290 return me;
00291 }
00292
00293
00294
00295
00296
00297
00298 void CollisionPlane::
00299 register_with_read_factory(void)
00300 {
00301 BamReader::get_factory()->register_factory(get_class_type(), make_CollisionPlane);
00302 }