inline void FELighting::inlineSetPixel(int offset, LightingData& data, LightSource::PaintingData& paintingData, int lightX, int lightY, float factorX, float factorY, IntPoint& normal2DVector) { m_lightSource->updatePaintingData(paintingData, lightX, lightY, static_cast<float>(data.pixels->item(offset + cAlphaChannelOffset)) * data.surfaceScale); float lightStrength; if (!normal2DVector.x() && !normal2DVector.y()) { // Normal vector is (0, 0, 1). This is a quite frequent case. if (m_lightingType == FELighting::DiffuseLighting) { lightStrength = m_diffuseConstant * paintingData.lightVector.z() / paintingData.lightVectorLength; } else { FloatPoint3D halfwayVector = paintingData.lightVector; halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); float halfwayVectorLength = halfwayVector.length(); if (m_specularExponent == 1) lightStrength = m_specularConstant * halfwayVector.z() / halfwayVectorLength; else lightStrength = m_specularConstant * powf(halfwayVector.z() / halfwayVectorLength, m_specularExponent); } } else { FloatPoint3D normalVector; normalVector.setX(factorX * static_cast<float>(normal2DVector.x()) * data.surfaceScale); normalVector.setY(factorY * static_cast<float>(normal2DVector.y()) * data.surfaceScale); normalVector.setZ(1); float normalVectorLength = normalVector.length(); if (m_lightingType == FELighting::DiffuseLighting) { lightStrength = m_diffuseConstant * (normalVector * paintingData.lightVector) / (normalVectorLength * paintingData.lightVectorLength); } else { FloatPoint3D halfwayVector = paintingData.lightVector; halfwayVector.setZ(halfwayVector.z() + paintingData.lightVectorLength); float halfwayVectorLength = halfwayVector.length(); if (m_specularExponent == 1) lightStrength = m_specularConstant * (normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength); else lightStrength = m_specularConstant * powf((normalVector * halfwayVector) / (normalVectorLength * halfwayVectorLength), m_specularExponent); } } if (lightStrength > 1) lightStrength = 1; if (lightStrength < 0) lightStrength = 0; data.pixels->set(offset, static_cast<unsigned char>(lightStrength * paintingData.colorVector.x())); data.pixels->set(offset + 1, static_cast<unsigned char>(lightStrength * paintingData.colorVector.y())); data.pixels->set(offset + 2, static_cast<unsigned char>(lightStrength * paintingData.colorVector.z())); }
double PannerNode::calculateDopplerRate() { double dopplerShift = 1.0; double dopplerFactor = listener()->dopplerFactor(); if (dopplerFactor > 0.0) { double speedOfSound = listener()->speedOfSound(); const FloatPoint3D &sourceVelocity = m_velocity; const FloatPoint3D &listenerVelocity = listener()->velocity(); // Don't bother if both source and listener have no velocity bool sourceHasVelocity = !sourceVelocity.isZero(); bool listenerHasVelocity = !listenerVelocity.isZero(); if (sourceHasVelocity || listenerHasVelocity) { // Calculate the source to listener vector FloatPoint3D listenerPosition = listener()->position(); FloatPoint3D sourceToListener = m_position - listenerPosition; double sourceListenerMagnitude = sourceToListener.length(); if (!sourceListenerMagnitude) { // Source and listener are at the same position. Skip the computation of the doppler // shift, and just return the cached value. dopplerShift = m_cachedDopplerRate; } else { double listenerProjection = sourceToListener.dot(listenerVelocity) / sourceListenerMagnitude; double sourceProjection = sourceToListener.dot(sourceVelocity) / sourceListenerMagnitude; listenerProjection = -listenerProjection; sourceProjection = -sourceProjection; double scaledSpeedOfSound = speedOfSound / dopplerFactor; listenerProjection = std::min(listenerProjection, scaledSpeedOfSound); sourceProjection = std::min(sourceProjection, scaledSpeedOfSound); dopplerShift = ((speedOfSound - dopplerFactor * listenerProjection) / (speedOfSound - dopplerFactor * sourceProjection)); fixNANs(dopplerShift); // avoid illegal values // Limit the pitch shifting to 4 octaves up and 3 octaves down. if (dopplerShift > 16.0) dopplerShift = 16.0; else if (dopplerShift < 0.125) dopplerShift = 0.125; } } } return dopplerShift; }
float PannerNode::dopplerRate(ContextRenderLock& r) { double dopplerShift = 1.0; // FIXME: optimize for case when neither source nor listener has changed... double dopplerFactor = listener(r)->dopplerFactor(); if (dopplerFactor > 0.0) { double speedOfSound = listener(r)->speedOfSound(); const FloatPoint3D &sourceVelocity = m_velocity; const FloatPoint3D &listenerVelocity = listener(r)->velocity(); // Don't bother if both source and listener have no velocity bool sourceHasVelocity = !sourceVelocity.isZero(); bool listenerHasVelocity = !listenerVelocity.isZero(); if (sourceHasVelocity || listenerHasVelocity) { // Calculate the source to listener vector FloatPoint3D listenerPosition = listener(r)->position(); FloatPoint3D sourceToListener = m_position - listenerPosition; double sourceListenerMagnitude = sourceToListener.length(); double listenerProjection = sourceToListener.dot(listenerVelocity) / sourceListenerMagnitude; double sourceProjection = sourceToListener.dot(sourceVelocity) / sourceListenerMagnitude; listenerProjection = -listenerProjection; sourceProjection = -sourceProjection; double scaledSpeedOfSound = speedOfSound / dopplerFactor; listenerProjection = min(listenerProjection, scaledSpeedOfSound); sourceProjection = min(sourceProjection, scaledSpeedOfSound); dopplerShift = ((speedOfSound - dopplerFactor * listenerProjection) / (speedOfSound - dopplerFactor * sourceProjection)); fixNANs(dopplerShift); // avoid illegal values // Limit the pitch shifting to 4 octaves up and 3 octaves down. if (dopplerShift > 16.0) dopplerShift = 16.0; else if (dopplerShift < 0.125) dopplerShift = 0.125; } } return static_cast<float>(dopplerShift); }