Merge remote-tracking branch 'origin/release/1.9.x'

This commit is contained in:
rdb 2015-12-31 21:03:38 +01:00
commit b1dcd9be46
3 changed files with 58 additions and 100 deletions

View File

@ -442,9 +442,14 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
into_depth = max_dist - orig_dist;
}
// Clamp the surface point to the box bounds.
LPoint3 surface = from_center - normal * dist;
surface = surface.fmax(_min);
surface = surface.fmin(_max);
new_entry->set_surface_normal(normal);
new_entry->set_surface_point(from_center - normal * dist);
new_entry->set_interior_point(from_center - normal * (dist + into_depth));
new_entry->set_surface_point(surface);
new_entry->set_interior_point(surface - normal * into_depth);
new_entry->set_contact_pos(contact_point);
new_entry->set_contact_normal(plane.get_normal());
new_entry->set_t(actual_t);

View File

@ -298,100 +298,50 @@ test_intersection_from_box(const CollisionEntry &entry) const {
const CollisionBox *box;
DCAST_INTO_R(box, entry.get_from(), 0);
CPT(TransformState) wrt_space = entry.get_wrt_space();
CPT(TransformState) wrt_prev_space = entry.get_wrt_prev_space();
// Instead of transforming the box into the sphere's coordinate space,
// we do it the other way around. It's easier that way.
const LMatrix4 &wrt_mat = entry.get_inv_wrt_mat();
const LMatrix4 &wrt_mat = wrt_space->get_mat();
LPoint3 center = wrt_mat.xform_point(_center);
PN_stdfloat radius_sq = wrt_mat.xform_vec(LVector3(0, 0, _radius)).length_squared();
CollisionBox local_b( *box );
local_b.xform( wrt_mat );
LPoint3 box_min = box->get_min();
LPoint3 box_max = box->get_max();
LPoint3 from_center = local_b.get_center();
// Arvo's algorithm.
PN_stdfloat d = 0;
PN_stdfloat s;
LPoint3 orig_center = get_center();
LPoint3 to_center = orig_center;
LPoint3 contact_point(from_center);
PN_stdfloat actual_t = 1.0f;
if (center[0] < box_min[0]) {
s = center[0] - box_min[0];
d += s * s;
PN_stdfloat to_radius = get_radius();
PN_stdfloat to_radius_2 = to_radius * to_radius;
int ip;
PN_stdfloat max_dist = 0.0f;
PN_stdfloat dist = 0.0f; // initial assignment to squelch silly compiler warning
bool intersect;
LPlane plane;
LVector3 normal;
for (ip = 0, intersect=false; ip < 6 && !intersect; ip++) {
plane = local_b.get_plane( ip );
if (local_b.get_plane_points(ip).size() < 3) {
continue;
}
normal = (has_effective_normal() && box->get_respect_effective_normal()) ? get_effective_normal() : plane.get_normal();
#ifndef NDEBUG
/*
if (!IS_THRESHOLD_EQUAL(normal.length_squared(), 1.0f, 0.001), NULL) {
collide_cat.info()
<< "polygon being collided with " << entry.get_into_node_path()
<< " has normal " << normal << " of length " << normal.length()
<< "\n";
normal.normalize();
}
*/
#endif
// The nearest point within the plane to our center is the
// intersection of the line (center, center - normal) with the plane.
if (!plane.intersects_line(dist, to_center, -(plane.get_normal()))) {
// No intersection with plane? This means the plane's effective
// normal was within the plane itself. A useless polygon.
continue;
}
if (dist > to_radius || dist < -to_radius) {
// No intersection with the plane.
continue;
}
LPoint2 p = local_b.to_2d(to_center - dist * plane.get_normal(), ip);
PN_stdfloat edge_dist = 0.0f;
edge_dist = local_b.dist_to_polygon(p, local_b.get_plane_points(ip));
if(edge_dist < 0) {
intersect = true;
continue;
}
if((edge_dist > 0) &&
((edge_dist * edge_dist + dist * dist) > to_radius_2)) {
// No intersection; the circle is outside the polygon.
continue;
}
// The sphere appears to intersect the polygon. If the edge is less
// than to_radius away, the sphere may be resting on an edge of
// the polygon. Determine how far the center of the sphere must
// remain from the plane, based on its distance from the nearest
// edge.
max_dist = to_radius;
if (edge_dist >= 0.0f) {
PN_stdfloat max_dist_2 = max(to_radius_2 - edge_dist * edge_dist, (PN_stdfloat)0.0);
max_dist = csqrt(max_dist_2);
}
if (dist > max_dist) {
// There's no intersection: the sphere is hanging off the edge.
continue;
}
intersect = true;
} else if (center[0] > box_max[0]) {
s = center[0] - box_max[0];
d += s * s;
}
if( !intersect )
if (center[1] < box_min[1]) {
s = center[1] - box_min[1];
d += s * s;
} else if (center[1] > box_max[1]) {
s = center[1] - box_max[1];
d += s * s;
}
if (center[2] < box_min[2]) {
s = center[2] - box_min[2];
d += s * s;
} else if (center[2] > box_max[2]) {
s = center[2] - box_max[2];
d += s * s;
}
if (d > radius_sq) {
return NULL;
}
if (collide_cat.is_debug()) {
collide_cat.debug()
@ -401,14 +351,17 @@ test_intersection_from_box(const CollisionEntry &entry) const {
PT(CollisionEntry) new_entry = new CollisionEntry(entry);
PN_stdfloat into_depth = max_dist - dist;
// To get the interior point, clamp the sphere center to the AABB.
LPoint3 interior = entry.get_wrt_mat().xform_point(center.fmax(box_min).fmin(box_max));
new_entry->set_interior_point(interior);
new_entry->set_surface_normal(normal);
new_entry->set_surface_point(to_center - normal * dist);
new_entry->set_interior_point(to_center - normal * (dist + into_depth));
new_entry->set_contact_pos(contact_point);
new_entry->set_contact_normal(plane.get_normal());
new_entry->set_t(actual_t);
// Now extrapolate the surface point and normal from that.
LVector3 normal = interior - _center;
normal.normalize();
new_entry->set_surface_point(_center + normal * _radius);
new_entry->set_surface_normal(
(has_effective_normal() && box->get_respect_effective_normal())
? get_effective_normal() : normal);
return new_entry;
}

View File

@ -11419,7 +11419,7 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
}
#ifndef OPENGLES // OpenGL ES doesn't have GL_TEXTURE_MAX_LEVEL.
if (_supports_texture_lod) {
if (is_at_least_gl_version(1, 2)) {
// By the time we get here, we have a pretty good prediction for
// the number of mipmaps we're going to have, so tell the GL that's
// all it's going to get.
@ -11934,7 +11934,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
<< "No mipmap level " << n << " defined for " << tex->get_name()
<< "\n";
#ifndef OPENGLES
if (_supports_texture_lod) {
if (is_at_least_gl_version(1, 2)) {
// Tell the GL we have no more mipmaps for it to use.
glTexParameteri(texture_target, GL_TEXTURE_MAX_LEVEL, n - mipmap_bias);
}
@ -12154,7 +12154,7 @@ upload_simple_texture(CLP(TextureContext) *gtc) {
#ifndef OPENGLES
// Turn off mipmaps for the simple texture.
if (tex->uses_mipmaps() && _supports_texture_lod) {
if (tex->uses_mipmaps() && is_at_least_gl_version(1, 2)) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
}
#endif
@ -12820,7 +12820,7 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
GLint num_expected_levels = tex->get_expected_num_mipmap_levels();
GLint highest_level = num_expected_levels;
#ifndef OPENGLES
if (_supports_texture_lod) {
if (is_at_least_gl_version(1, 2)) {
glGetTexParameteriv(target, GL_TEXTURE_MAX_LEVEL, &highest_level);
highest_level = min(highest_level, num_expected_levels);
}