void XenoAudio::SetChannelPos(int i) { if (!audioOn) return; if (sounds[i].pos.IsZero()) { Mix_SetPosition(i, 0, 0); } else { Vector3F delta = sounds[i].pos - listenerPos; float len = delta.Length(); float df = len / MAX_DISTANCE; int d = LRintf(df*255.0f); d = Clamp(d, 0, 255); if (delta.LengthSquared() > 0.001f) { delta.Normalize(); } else { delta.Set(0, 0, -1); } static const Vector3F UP = { 0, 1, 0 }; Vector3F listenerRight = CrossProduct(listenerDir, UP); float dotFront = DotProduct(delta, listenerDir); float dotRight = DotProduct(delta, listenerRight); // 0 is north, 90 is east, etc. WTF. float rad = atan2(dotRight, dotFront); float deg = rad * 180.0f / PI; int degi = int(deg); if (degi < 0) degi += 360; int result = Mix_SetPosition(i, degi, d); GLASSERT(result != 0); (void)result; } }
Model* SpaceTree::QueryRay( const Vector3F& _origin, const Vector3F& _direction, int required, int excluded, const Model** ignore, HitTestMethod testType, Vector3F* intersection ) { //GLOUTPUT(( "query ray\n" )); modelRoot = 0; nodesVisited = 0; modelsFound = 0; requiredFlags = required; excludedFlags = excluded | Model::MODEL_HIDDEN_FROM_TREE; ++queryID; Vector3F dummy; if ( !intersection ) { intersection = &dummy; } Vector3F dir = _direction; dir.Normalize(); Rectangle3F aabb; aabb.min.Set( 0, yMin, 0 ); aabb.max.Set( Map::SIZE, yMax, Map::SIZE ); // Where does this ray enter and leave the spaceTree? // It enters at 'p0' and leaves at 'p1' int p0Test, p1Test; Vector3F p0, p1; int test = IntersectRayAllAABB( _origin, dir, aabb, &p0Test, &p0, &p1Test, &p1 ); if ( test != grinliz::INTERSECT ) { // Can click outside of AABB pretty commonly, actually. return 0; } Plane planes[6]; Rectangle3F rect; rect.FromPair( p0, p1 ); Plane::CreatePlanes( rect, planes ); Model* modelRoot = Query( planes, 6, required, excluded ); // We now have a batch of models. Are any of them a hit?? GLASSERT( testType == TEST_HIT_AABB || testType == TEST_TRI ); float close = FLT_MAX; Model* closeModel = 0; Vector3F testInt; float t; for( Model* root=modelRoot; root; root=root->next ) { if ( Ignore( root, ignore ) ) continue; //GLOUTPUT(( "Consider: %s\n", root->GetResource()->header.name )); int result = grinliz::REJECT; if ( testType == TEST_HIT_AABB ) { Rectangle3F modelAABB; root->CalcHitAABB( &modelAABB ); result = IntersectRayAABB( p0, dir, modelAABB, &testInt, &t ); } else if ( testType == TEST_TRI ) { t = FLT_MAX; result = root->IntersectRay( p0, dir, &testInt ); if ( result == grinliz::INTERSECT ) { Vector3F delta = p0 - testInt; t = delta.LengthSquared(); //GLOUTPUT(( "Hit: %s t=%.2f\n", root->GetResource()->header.name, t )); } } if ( result == grinliz::INTERSECT ) { // Ugly little bug: check for t>=0, else could collide with objects // that touch the bounding box but are before the ray starts. if ( t >= 0.0f && t < close ) { closeModel = root; *intersection = testInt; close = t; } } } if ( closeModel ) { return closeModel; } return 0; }