void PannerNode::calculateAzimuthElevation(double* outAzimuth, double* outElevation) { double azimuth = 0.0; // Calculate the source-listener vector FloatPoint3D listenerPosition = listener()->position(); FloatPoint3D sourceListener = m_position - listenerPosition; // normalize() does nothing if the length of |sourceListener| is zero. sourceListener.normalize(); // Align axes FloatPoint3D listenerFront = listener()->orientation(); FloatPoint3D listenerUp = listener()->upVector(); FloatPoint3D listenerRight = listenerFront.cross(listenerUp); listenerRight.normalize(); FloatPoint3D listenerFrontNorm = listenerFront; listenerFrontNorm.normalize(); FloatPoint3D up = listenerRight.cross(listenerFrontNorm); float upProjection = sourceListener.dot(up); FloatPoint3D projectedSource = sourceListener - upProjection * up; projectedSource.normalize(); azimuth = 180.0 * acos(projectedSource.dot(listenerRight)) / piDouble; fixNANs(azimuth); // avoid illegal values // Source in front or behind the listener double frontBack = projectedSource.dot(listenerFrontNorm); if (frontBack < 0.0) azimuth = 360.0 - azimuth; // Make azimuth relative to "front" and not "right" listener vector if ((azimuth >= 0.0) && (azimuth <= 270.0)) azimuth = 90.0 - azimuth; else azimuth = 450.0 - azimuth; // Elevation double elevation = 90.0 - 180.0 * acos(sourceListener.dot(up)) / piDouble; fixNANs(elevation); // avoid illegal values if (elevation > 90.0) elevation = 180.0 - elevation; else if (elevation < -90.0) elevation = -180.0 - elevation; if (outAzimuth) *outAzimuth = azimuth; if (outElevation) *outElevation = elevation; }
void PannerNode::getAzimuthElevation(double* outAzimuth, double* outElevation) { // FIXME: we should cache azimuth and elevation (if possible), so we only re-calculate if a change has been made. double azimuth = 0.0; // Calculate the source-listener vector FloatPoint3D listenerPosition = listener()->position(); FloatPoint3D sourceListener = m_position - listenerPosition; if (sourceListener.isZero()) { // degenerate case if source and listener are at the same point *outAzimuth = 0.0; *outElevation = 0.0; return; } sourceListener.normalize(); // Align axes FloatPoint3D listenerFront = listener()->orientation(); FloatPoint3D listenerUp = listener()->upVector(); FloatPoint3D listenerRight = listenerFront.cross(listenerUp); listenerRight.normalize(); FloatPoint3D listenerFrontNorm = listenerFront; listenerFrontNorm.normalize(); FloatPoint3D up = listenerRight.cross(listenerFrontNorm); float upProjection = sourceListener.dot(up); FloatPoint3D projectedSource = sourceListener - upProjection * up; projectedSource.normalize(); azimuth = 180.0 * acos(projectedSource.dot(listenerRight)) / piDouble; fixNANs(azimuth); // avoid illegal values // Source in front or behind the listener double frontBack = projectedSource.dot(listenerFrontNorm); if (frontBack < 0.0) azimuth = 360.0 - azimuth; // Make azimuth relative to "front" and not "right" listener vector if ((azimuth >= 0.0) && (azimuth <= 270.0)) azimuth = 90.0 - azimuth; else azimuth = 450.0 - azimuth; // Elevation double elevation = 90.0 - 180.0 * acos(sourceListener.dot(up)) / piDouble; fixNANs(elevation); // avoid illegal values if (elevation > 90.0) elevation = 180.0 - elevation; else if (elevation < -90.0) elevation = -180.0 - elevation; if (outAzimuth) *outAzimuth = azimuth; if (outElevation) *outElevation = elevation; }