16 #include "collisionFloorMesh.h" 17 #include "collisionHandler.h" 18 #include "collisionEntry.h" 19 #include "collisionSphere.h" 20 #include "collisionLine.h" 21 #include "collisionRay.h" 22 #include "collisionSegment.h" 23 #include "config_collide.h" 24 #include "pointerToArray.h" 28 #include "datagramIterator.h" 29 #include "bamReader.h" 30 #include "bamWriter.h" 31 #include "boundingBox.h" 32 #include "boundingPlane.h" 34 #include "geomTriangles.h" 35 #include "geomLinestrips.h" 36 #include "geomVertexWriter.h" 38 PStatCollector CollisionFloorMesh::_volume_pcollector(
"Collision Volumes:CollisionFloorMesh");
39 PStatCollector CollisionFloorMesh::_test_pcollector(
"Collision Tests:CollisionFloorMesh");
59 Vertices::iterator vi;
60 for (vi=_vertices.begin();vi!=_vertices.end();++vi) {
62 (*vi).set(pt[0],pt[1],pt[2]);
64 Triangles::iterator ti;
65 for (ti=_triangles.begin();ti!=_triangles.end();++ti) {
71 tri.min_x=min(min(v1[0],v2[0]),v3[0]);
72 tri.max_x=max(max(v1[0],v2[0]),v3[0]);
73 tri.min_y=min(min(v1[1],v2[1]),v3[1]);
74 tri.max_y=max(max(v1[1],v2[1]),v3[1]);
76 CollisionSolid::xform(mat);
100 void CollisionFloorMesh::
101 output(ostream &out)
const {
111 compute_internal_bounds()
const {
112 if (_vertices.empty()) {
116 Vertices::const_iterator pi = _vertices.begin();
122 for (++pi; pi != _vertices.end(); ++pi) {
125 n.set(min(n[0], p[0]),
128 x.set(max(x[0], p[0]),
144 DCAST_INTO_R(ray, entry.
get_from(), NULL);
145 LPoint3 from_origin = ray->get_origin() * entry.get_wrt_mat();
147 double fx = from_origin[0];
148 double fy = from_origin[1];
150 CollisionFloorMesh::Triangles::const_iterator ti;
151 for (ti = _triangles.begin(); ti < _triangles.end(); ++ti) {
154 if (fx < tri.min_x || fx >= tri.max_x || fy < tri.min_y || fy >= tri.max_y) {
159 LPoint3 p0 = _vertices[tri.p1];
160 LPoint3 p1 = _vertices[tri.p2];
161 LPoint3 p2 = _vertices[tri.p3];
162 PN_stdfloat p0x = p0[0];
163 PN_stdfloat p0y = p0[1];
164 PN_stdfloat e0x, e0y, e1x, e1y, e2x, e2y;
167 e0x = fx - p0x; e0y = fy - p0y;
168 e1x = p1[0] - p0x; e1y = p1[1] - p0y;
169 e2x = p2[0] - p0x; e2y = p2[1] - p0y;
171 if (e2x == 0.0)
continue;
173 if (u < 0.0 || u > 1.0)
continue;
174 if (e1y == 0)
continue;
175 v = (e0y - (e2y * u)) / e1y;
176 if (v < 0.0)
continue;
178 PN_stdfloat d = (e2y * e1x) - (e2x * e1y);
179 if (d == 0.0)
continue;
180 u = ((e0y * e1x) - (e0x * e1y)) / d;
181 if (u < 0.0 || u > 1.0)
continue;
182 v = (e0x - (e2x * u)) / e1x;
183 if (v < 0.0)
continue;
185 if (u + v <= 0.0 || u + v > 1.0)
continue;
187 PN_stdfloat mag = u + v;
188 PN_stdfloat p0z = p0[2];
190 PN_stdfloat uz = (p2[2] - p0z) * mag;
191 PN_stdfloat vz = (p1[2] - p0z) * mag;
192 PN_stdfloat finalz = p0z + vz + (((uz - vz) * u) / (u + v));
195 new_entry->set_surface_normal(
LPoint3(0, 0, 1));
196 new_entry->set_surface_point(
LPoint3(fx, fy, finalz));
209 test_intersection_from_sphere(
const CollisionEntry &entry)
const {
211 DCAST_INTO_R(sphere, entry.
get_from(), NULL);
212 LPoint3 from_origin = sphere->get_center() * entry.get_wrt_mat();
214 double fx = from_origin[0];
215 double fy = from_origin[1];
217 PN_stdfloat fz = PN_stdfloat(from_origin[2]);
218 PN_stdfloat rad = sphere->get_radius();
219 CollisionFloorMesh::Triangles::const_iterator ti;
220 for (ti = _triangles.begin(); ti < _triangles.end(); ++ti) {
223 if (fx < tri.min_x || fx >= tri.max_x || fy < tri.min_y || fy >= tri.max_y) {
228 LPoint3 p0 = _vertices[tri.p1];
229 LPoint3 p1 = _vertices[tri.p2];
230 LPoint3 p2 = _vertices[tri.p3];
231 PN_stdfloat p0x = p0[0];
232 PN_stdfloat p0y = p0[1];
233 PN_stdfloat e0x, e0y, e1x, e1y, e2x, e2y;
236 e0x = fx - p0x; e0y = fy - p0y;
237 e1x = p1[0] - p0x; e1y = p1[1] - p0y;
238 e2x = p2[0] - p0x; e2y = p2[1] - p0y;
240 if (e2x == 0.0)
continue;
242 if (u < 0.0 || u > 1.0)
continue;
243 if (e1y == 0)
continue;
244 v = (e0y - (e2y * u)) / e1y;
245 if (v < 0.0)
continue;
247 PN_stdfloat d = (e2y * e1x) - (e2x * e1y);
248 if (d == 0.0)
continue;
249 u = ((e0y * e1x) - (e0x * e1y)) / d;
250 if (u < 0.0 || u > 1.0)
continue;
251 v = (e0x - (e2x * u)) / e1x;
252 if (v < 0.0)
continue;
254 if (u + v <= 0.0 || u + v > 1.0)
continue;
256 PN_stdfloat mag = u + v;
257 PN_stdfloat p0z = p0[2];
259 PN_stdfloat uz = (p2[2] - p0z) * mag;
260 PN_stdfloat vz = (p1[2] - p0z) * mag;
261 PN_stdfloat finalz = p0z+vz+(((uz - vz) *u)/(u+v));
262 PN_stdfloat dz = fz - finalz;
267 new_entry->set_surface_normal(
LPoint3(0, 0, 1));
268 new_entry->set_surface_point(
LPoint3(fx, fy, finalz));
282 void CollisionFloorMesh::
284 if (collide_cat.is_debug()) {
286 <<
"Recomputing viz for " << *
this <<
"\n";
290 (
"collision", GeomVertexFormat::get_v3(),
297 Triangles::iterator ti;
298 Vertices::iterator vi;
299 for (vi = _vertices.begin(); vi != _vertices.end(); vi++) {
303 for (ti = _triangles.begin(); ti != _triangles.end(); ++ti) {
305 mesh->add_vertex(tri.p1);
306 mesh->add_vertex(tri.p2);
307 mesh->add_vertex(tri.p3);
308 wire->add_vertex(tri.p1);
309 wire->add_vertex(tri.p2);
310 wire->add_vertex(tri.p3);
311 wire->add_vertex(tri.p1);
312 wire->close_primitive();
313 mesh->close_primitive();
318 geom->add_primitive(mesh);
319 geom2->add_primitive(wire);
323 _bounds_viz_geom->add_geom(geom, get_solid_bounds_viz_state());
324 _bounds_viz_geom->add_geom(geom2, get_wireframe_bounds_viz_state());
336 return _volume_pcollector;
348 return _test_pcollector;
362 for (
size_t i = 0; i < _vertices.size(); i++) {
363 _vertices[i].write_datagram(me);
366 for (
size_t i = 0; i < _triangles.size(); i++) {
386 void CollisionFloorMesh::
389 CollisionSolid::fillin(scan, manager);
391 for (
size_t i = 0; i < num_verts; i++) {
395 _vertices.push_back(vert);
398 for (
size_t i = 0; i < num_tris; i++) {
409 _triangles.push_back(tri);
424 parse_params(params, scan, manager);
425 me->fillin(scan, manager);
445 void CollisionFloorMesh::
446 write(ostream &out,
int indent_level)
const {
447 indent(out, indent_level) << (*this) <<
"\n";
456 add_triangle(
unsigned int pointA,
unsigned int pointB,
unsigned int pointC) {
461 LPoint3 v1 = _vertices[pointA];
462 LPoint3 v2 = _vertices[pointB];
463 LPoint3 v3 = _vertices[pointC];
465 tri.min_x=min(min(v1[0],v2[0]),v3[0]);
466 tri.max_x=max(max(v1[0],v2[0]),v3[0]);
467 tri.min_y=min(min(v1[1],v2[1]),v3[1]);
468 tri.max_y=max(max(v1[1],v2[1]),v3[1]);
470 _triangles.push_back(tri);
void add_triangle(unsigned int pointA, unsigned int pointB, unsigned int pointC)
store a triangle for processing
This object provides a high-level interface for quickly writing a sequence of numeric values from a v...
An axis-aligned bounding box; that is, a minimum and maximum coordinate triple.
An infinite ray, with a specific origin and direction.
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
void read_datagram(DatagramIterator &source)
Reads the vector from the Datagram using get_stdfloat().
The abstract base class for all things that can collide with other things in the world, and all the things they can collide with (except geometry).
Base class for objects that can be written to and read from Bam files.
virtual PStatCollector & get_test_pcollector()
Returns a PStatCollector that is used to count the number of intersection tests made against a solid ...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
A spherical collision volume or object.
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
static const LPoint3f & origin(CoordinateSystem cs=CS_default)
Returns the origin of the indicated coordinate system.
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
PN_uint16 get_uint16()
Extracts an unsigned 16-bit integer.
CollisionFloorMesh()
This is only for the convenience of CollisionPolygon.
static TypedWritable * make_CollisionFloorMesh(const FactoryParams ¶ms)
Factory method to generate a CollisionPolygon object.
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
This is an abstract class for any volume in any sense which can be said to define the locality of ref...
A lightweight class that represents a single element that may be timed and/or counted via stats...
virtual void xform(const LMatrix4 &mat)
Transforms the solid by the indicated matrix.
This is a 4-by-4 transform matrix.
Defines a single collision event.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
A container for geometry primitives.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
void add_data3(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z)
Sets the write row to a particular 3-component value, and advances the write row. ...
virtual void write_datagram(BamWriter *manager, Datagram &me)
Function to write the important information in the particular object to a Datagram.
virtual LPoint3 get_collision_origin() const
Returns the point in space deemed to be the "origin" of the solid for collision purposes.
This object represents a solid made entirely of triangles, which will only be tested again z axis ali...
void register_factory(TypeHandle handle, CreateFunc *func)
Registers a new kind of thing the Factory will be able to create.
void add_uint16(PN_uint16 value)
Adds an unsigned 16-bit integer to the datagram.
static void register_with_read_factory()
Factory method to generate a CollisionPolygon object.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
Defines a series of line strips.
Defines a series of disconnected triangles.
A class to retrieve the individual data elements previously stored in a Datagram. ...
TypeHandle is the identifier used to differentiate C++ class types.
virtual PStatCollector & get_volume_pcollector()
Returns a PStatCollector that is used to count the number of bounding volume tests made against a sol...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
const CollisionSolid * get_from() const
Returns the CollisionSolid pointer for the particular solid that triggered this collision.