Fix more shadowing issues - this time shadows inside objects

This should work for all docking tunnels (except the straight-through ones) - so closes #94 - but the glare effect as a whole will need a better way of handling it after 1.80 is out as there are still a bunch of strange cases: straight-through docking tunnels, odd effects around Torus stations and other large "pancake"-shaped objects, and so on.
This commit is contained in:
cim 2014-06-19 21:04:17 +01:00
parent a1efd52f9a
commit 3d0cf308f2
2 changed files with 48 additions and 8 deletions

View File

@ -457,13 +457,48 @@ BOOL shadowAtPointOcclusionToValue(HPVector e1pos, GLfloat e1rad, Entity *e2, OO
// check projected sizes of discs
GLfloat d2_sun = HPdistance2(e1pos, the_sun->position);
GLfloat d2_e2sun = HPdistance2(e2->position, the_sun->position);
GLfloat d2_e2 = HPdistance2( e1pos, e2->position);
if (d2_e2sun > d2_sun)
{
// you are nearer the sun than the potential occluder, so it can't shade you
// you are nearer the sun than the potential occluder, so it
// probably can't shade you
if (d2_e2 < cr_e2 * cr_e2 && [e2 isShip])
{
// exception: if within the collision radius of the other
// object, might still be shadowed by it.
GLfloat bbx = 0.0f, bby = 0.0f, bbz = 0.0f;
BoundingBox bb = [(ShipEntity*)e2 totalBoundingBox];
bounding_box_get_dimensions(bb,&bbx,&bby,&bbz);
float minbb = bbx;
if (bby < minbb) { minbb = bby; }
if (bbz < minbb) { minbb = bbz; }
minbb -= e1rad; // subtract object's size
/* closer to the object than the shortest axis. This check
* branch is basically for docking at a rock hermit facing
* away from the sun, but it checks the shortest bounding
* box size rather than the collision radius to avoid
* getting weird shadowing effects around large planar
* entities like the OXP Torus Station.
*
* Well... more weird shadowing effects than there already
* are, anyway.
*
* There are more accurate ways to check "sphere inside
* bounding box" but this seems accurate enough and is
* simpler.
*
* - CIM
*/
if (d2_e2 < minbb * minbb)
{
*outValue = 0.1;
return YES;
}
}
return NO;
}
GLfloat d2_e2 = HPdistance2( e1pos, e2->position);
GLfloat cr_sun = the_sun->collision_radius;
GLfloat cr2_sun_scaled = cr_sun * cr_sun * d2_e2 / d2_sun;

View File

@ -1996,6 +1996,7 @@ static GLfloat sBaseMass = 0.0;
if (EXPECT_NOT(!sun)) return 0.0f;
// check if camera position is shadowed
OOViewID vdir = [UNIVERSE viewDirection];
unsigned i;
unsigned ent_count = UNIVERSE->n_entities;
Entity **uni_entities = UNIVERSE->sortedEntities; // grab the public sorted list
@ -2007,11 +2008,15 @@ static GLfloat sBaseMass = 0.0;
([uni_entities[i] isShip] &&
[uni_entities[i] isVisible]))
{
float shadow = 1.5f;
shadowAtPointOcclusionToValue([self viewpointPosition],1.0f,uni_entities[i],sun,&shadow);
/* BUG: if the shadowing entity is not spherical, this gives over-shadowing. True elsewhere as well, but not so obvious there. */
if (shadow < 1) {
return 0.0f;
// the player ship can't shadow internal views
if (EXPECT(vdir > VIEW_STARBOARD || ![uni_entities[i] isPlayer]))
{
float shadow = 1.5f;
shadowAtPointOcclusionToValue([self viewpointPosition],1.0f,uni_entities[i],sun,&shadow);
/* BUG: if the shadowing entity is not spherical, this gives over-shadowing. True elsewhere as well, but not so obvious there. */
if (shadow < 1) {
return 0.0f;
}
}
}
}
@ -2020,7 +2025,7 @@ static GLfloat sBaseMass = 0.0;
relativePosition = HPVectorToVector(HPvector_subtract([self viewpointPosition], [sun position]));
unitRelativePosition = vector_normal_or_zbasis(relativePosition);
switch ([UNIVERSE viewDirection])
switch (vdir)
{
case VIEW_FORWARD:
measuredCos = -dot_product(unitRelativePosition, v_forward);