51 if ((
self = [super
init]))
69 if ((
self = [
self init]))
77- (id) initAtLocation:(HPVector)locn withRadius:(GLfloat)rad withinRegion:(
CollisionRegion *)otherRegion
79 if ((
self = [
self init]))
101 return [NSString stringWithFormat:@"<%@ %p>{ID: %d, %lu subregions, %u ents}", [
self class], self, crid, [subregions count], n_entities];
107 [subregions makeObjectsPerformSelector:@selector(clearSubregions)];
108 [subregions removeAllObjects];
112- (void) addSubregionAtPosition:(HPVector)pos withRadius:(GLfloat)rad
133 sub = [[
CollisionRegion alloc] initAtLocation:pos withRadius:rad withinRegion:self];
135 [subregions addObject:sub];
144 if (region ==
nil)
return NO;
148 GLfloat r1 = region->
radius;
150 if ((position.x < loc.x - r1)||(position.x > loc.x + r1)||
151 (position.y < loc.y - r1)||(position.y > loc.y + r1)||
152 (position.z < loc.z - r1)||(position.z > loc.z + r1))
163 if (region ==
nil)
return NO;
167 GLfloat r1 = region->
radius;
169 if ((position.x - rad < loc.x - r1)||(position.x + rad > loc.x + r1)||
170 (position.y - rad < loc.y - r1)||(position.y + rad > loc.y + r1)||
171 (position.z - rad < loc.z - r1)||(position.z + rad > loc.z + r1))
182 if (region ==
nil)
return NO;
188 if ((position.x < loc.x - r1)||(position.x > loc.x + r1)||
189 (position.y < loc.y - r1)||(position.y > loc.y + r1)||
190 (position.z < loc.z - r1)||(position.z > loc.z + r1))
203 [subregions makeObjectsPerformSelector:@selector(clearEntityList)];
209- (void) addEntity:(
Entity *)ent
217 if (new_store == NULL)
219 [NSException raise:NSMallocException format:@"Not enough memory to grow collision region member list."];
230- (BOOL) checkEntity:(
Entity *)ent
249 [
self addEntity:ent];
258 [subregions makeObjectsPerformSelector:@selector(findCollisions)];
268 double dist2, r1, r2, r0, min_dist2;
270 Entity *entities_to_test[n_entities];
273 unsigned n_entities_to_test = 0;
279 entities_to_test[n_entities_to_test++] = e1;
286 OOLog(
@"collisionRegion.debug",
@"DEBUG in collision region %@ testing %d out of %d entities",
self, n_entities_to_test,
n_entities);
290 if (n_entities_to_test < 2)
return;
294 for (i = 0; i < n_entities_to_test; i++)
296 e1 = entities_to_test[i];
299 [[e1 collisionArray] removeAllObjects];
300 e1->hasCollided = NO;
304 [(ShipEntity*)e1 setProximityAlert:nil];
314 for (i = 0; i < n_entities_to_test; i++)
316 e1 = entities_to_test[i];
337 dist2 = HPdistance2(e2->
position, p1);
344 OOLog(
@"collisionRegion.debug",
@"DEBUG Testing collision between %@ (%@) and %@ (%@)",
358 if (dist2 >= min_dist2)
373 if (dist2 < min_dist2)
380 if ([se1 shipIsInDockingCorridor:(
ShipEntity *)e2])
392 if ([se2 shipIsInDockingCorridor:(
ShipEntity *)e1])
483 GLfloat d2_sun = HPdistance2(e1pos, the_sun->
position);
485 GLfloat d2_e2 = HPdistance2( e1pos, e2->
position);
487 if (d2_e2sun > d2_sun)
491 if (d2_e2 < cr_e2 * cr_e2 && [e2 isShip])
495 GLfloat bbx = 0.0f, bby = 0.0f, bbz = 0.0f;
497 bounding_box_get_dimensions(bb,&bbx,&bby,&bbz);
499 if (bby < minbb) { minbb = bby; }
500 if (bbz < minbb) { minbb = bbz; }
518 if (d2_e2 < minbb * minbb)
529 GLfloat cr2_sun_scaled = cr_sun * cr_sun * d2_e2 / d2_sun;
530 if (cr_e2 * cr_e2 < cr2_sun_scaled)
540 float d2_e = sqrt(d2_e2);
546 theta_diff = asin(1) - asin(cr_sun / sqrt(d2_sun));
550 theta_diff = asin(cr_e2 / d2_e) - asin(cr_sun / sqrt(d2_sun));
555 HPVector p_e1 = e1pos;
556 Vector v_sun = HPVectorToVector(HPvector_subtract(p_sun, p_e1));
557 v_sun = vector_normal_or_zbasis(v_sun);
559 Vector v_e2 = HPVectorToVector(HPvector_subtract(p_e2, p_e1));
560 v_e2 = vector_normal_or_xbasis(v_e2);
562 float phi = acos(dot_product(v_sun, v_e2));
563 *outValue = (phi / theta_diff);
565 if (phi > theta_diff)
593 if ([
UNIVERSE reducedDetail])
return;
602 unsigned ent_count =
UNIVERSE->n_entities;
604 Entity *planets[ent_count];
605 unsigned n_planets = 0;
607 unsigned n_ships = 0;
609 for (i = 0; i < ent_count; i++)
611 if (uni_entities[i]->isSunlit)
614 if ([uni_entities[i] isPlanet])
617 planets[n_planets++] = uni_entities[i];
622 else if ([uni_entities[i] isShip] &&
623 [uni_entities[i] isVisible] &&
626 ships[n_ships++] = uni_entities[i];
632 [subregions makeObjectsPerformSelector:@selector(findShadowedEntities)];
642 BOOL occluder_moved = NO;
643 if ([e1 status] == STATUS_COCKPIT_DISPLAY)
652 occluder = [UNIVERSE entityForUniversalID:e1->shadingEntityID];
655 occluder_moved = occluder->hasMoved;
658 if (([e1 isShip] ||[e1 isPlanet]) && (e1->
hasMoved || occluder_moved))
661 e1->shadingEntityID = NO_TARGET;
664 if ([e1 isPlayer] && ([(PlayerEntity*)e1 showDemoShips]))
685 for (j = 0; j < n_planets; j++)
687 float occlusionNumber;
706 for (j = 0; j < n_ships; j++)
722 return [NSString stringWithFormat:@"p%u - c%u", checks_this_tick, checks_within_range];
728 NSMutableString *result = [[NSMutableString alloc] initWithFormat:@"%d:", n_entities];
732 [result appendString:[sub
debugOut]];
734 return [result autorelease];
#define MINIMUM_SHADOWING_ENTITY_RADIUS
#define COLLISION_MAX_ENTITIES
#define COLLISION_REGION_BORDER_RADIUS
BOOL shadowAtPointOcclusionToValue(HPVector e1pos, GLfloat e1rad, Entity *e2, OOSunEntity *the_sun, float *outValue)
static BOOL positionIsWithinBorders(HPVector position, CollisionRegion *region)
static BOOL positionIsWithinRegion(HPVector position, CollisionRegion *region)
static BOOL sphereIsWithinRegion(HPVector position, GLfloat rad, CollisionRegion *region)
#define OOLog(class, format,...)
#define PROXIMITY_WARN_DISTANCE2
NSString * collisionDescription()
static BOOL positionIsWithinBorders(HPVector position, CollisionRegion *region)
static BOOL positionIsWithinRegion(HPVector position, CollisionRegion *region)
void addSubregionAtPosition:withRadius:(HPVector pos,[withRadius] GLfloat rad)
static BOOL entityByEntityOcclusionToValue(Entity *e1, Entity *e2, OOSunEntity *the_sun, float *outValue)
NSMutableArray * subregions
CollisionRegion * parentRegion
unsigned checks_this_tick
void findShadowedEntities()
static BOOL sphereIsWithinRegion(HPVector position, GLfloat rad, CollisionRegion *region)
unsigned checks_within_range
static BOOL testEntityOccludedByEntity(Entity *e1, Entity *e2, OOSunEntity *the_sun)
BOOL shadowAtPointOcclusionToValue(HPVector e1pos, GLfloat e1rad, Entity *e2, OOSunEntity *the_sun, float *outValue)
OOUniversalID universalID
NSMutableArray * collisionArray()
unsigned collisionTestFilter
OOUniversalID shadingEntityID
BOOL checkCloseCollisionWith:(Entity *other)
void setCollisionRegion:(CollisionRegion *region)
BOOL checkCloseCollisionWith:(Entity *other)
void setProximityAlert:(ShipEntity *targetEntity)
BOOL shipIsInDockingCorridor:(ShipEntity *ship)