void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) { // set up the iterators LLSD::map_iterator cIt = mParamValues.beginMap(); // keep cloud positions and coverage the same /// TODO masking will do this later F32 cloudPos1X = (F32) mParamValues["cloud_pos_density1"][0].asReal(); F32 cloudPos1Y = (F32) mParamValues["cloud_pos_density1"][1].asReal(); F32 cloudPos2X = (F32) mParamValues["cloud_pos_density2"][0].asReal(); F32 cloudPos2Y = (F32) mParamValues["cloud_pos_density2"][1].asReal(); F32 cloudCover = (F32) mParamValues["cloud_shadow"][0].asReal(); LLSD srcVal; LLSD destVal; // do the interpolation for all the ones saved as vectors // skip the weird ones for(; cIt != mParamValues.endMap(); cIt++) { // check params to make sure they're actually there if(src.mParamValues.has(cIt->first)) { srcVal = src.mParamValues[cIt->first]; } else { continue; } if(dest.mParamValues.has(cIt->first)) { destVal = dest.mParamValues[cIt->first]; } else { continue; } // skip if not a vector if(!cIt->second.isArray()) { continue; } // only Real vectors allowed if(!cIt->second[0].isReal()) { continue; } // make sure all the same size if( cIt->second.size() != srcVal.size() || cIt->second.size() != destVal.size()) { continue; } // more error checking might be necessary; for(int i=0; i < cIt->second.size(); ++i) { cIt->second[i] = (1.0f - weight) * (F32) srcVal[i].asReal() + weight * (F32) destVal[i].asReal(); } } // now mix the extra parameters setStarBrightness((1 - weight) * (F32) src.getStarBrightness() + weight * (F32) dest.getStarBrightness()); llassert(src.getSunAngle() >= - F_PI && src.getSunAngle() <= 3 * F_PI); llassert(dest.getSunAngle() >= - F_PI && dest.getSunAngle() <= 3 * F_PI); llassert(src.getEastAngle() >= 0 && src.getEastAngle() <= 4 * F_PI); llassert(dest.getEastAngle() >= 0 && dest.getEastAngle() <= 4 * F_PI); // sun angle and east angle require some handling to make sure // they go in circles. Yes quaternions would work better. F32 srcSunAngle = src.getSunAngle(); F32 destSunAngle = dest.getSunAngle(); F32 srcEastAngle = src.getEastAngle(); F32 destEastAngle = dest.getEastAngle(); if(fabsf(srcSunAngle - destSunAngle) > F_PI) { if(srcSunAngle > destSunAngle) { destSunAngle += 2 * F_PI; } else { srcSunAngle += 2 * F_PI; } } if(fabsf(srcEastAngle - destEastAngle) > F_PI) { if(srcEastAngle > destEastAngle) { destEastAngle += 2 * F_PI; } else { srcEastAngle += 2 * F_PI; } } setSunAngle((1 - weight) * srcSunAngle + weight * destSunAngle); setEastAngle((1 - weight) * srcEastAngle + weight * destEastAngle); // now setup the sun properly // reset those cloud positions mParamValues["cloud_pos_density1"][0] = cloudPos1X; mParamValues["cloud_pos_density1"][1] = cloudPos1Y; mParamValues["cloud_pos_density2"][0] = cloudPos2X; mParamValues["cloud_pos_density2"][1] = cloudPos2Y; mParamValues["cloud_shadow"][0] = cloudCover; }
void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) { // set up the iterators // keep cloud positions and coverage the same /// TODO masking will do this later F32 cloudPos1X = (F32) mParamValues["cloud_pos_density1"][0].asReal(); F32 cloudPos1Y = (F32) mParamValues["cloud_pos_density1"][1].asReal(); F32 cloudPos2X = (F32) mParamValues["cloud_pos_density2"][0].asReal(); F32 cloudPos2Y = (F32) mParamValues["cloud_pos_density2"][1].asReal(); F32 cloudCover = (F32) mParamValues["cloud_shadow"][0].asReal(); LLSD srcVal; LLSD destVal; // Iterate through values for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter) { // If param exists in both src and dest, set the holder variables, otherwise skip if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first)) { srcVal = src.mParamValues[iter->first]; destVal = dest.mParamValues[iter->first]; } else { continue; } if(iter->second.isReal()) // If it's a real, interpolate directly { iter->second = srcVal.asReal() + ((destVal.asReal() - srcVal.asReal()) * weight); } else if(iter->second.isArray() && iter->second[0].isReal() // If it's an array of reals, loop through the reals and interpolate on those && iter->second.size() == srcVal.size() && iter->second.size() == destVal.size()) { // Actually do interpolation: old value + (difference in values * factor) for(int i=0; i < iter->second.size(); ++i) { // iter->second[i] = (1.f-weight)*(F32)srcVal[i].asReal() + weight*(F32)destVal[i].asReal(); // old way of doing it -- equivalent but one more operation iter->second[i] = srcVal[i].asReal() + ((destVal[i].asReal() - srcVal[i].asReal()) * weight); } } else // Else, skip { continue; } } // now mix the extra parameters setStarBrightness((1 - weight) * (F32) src.getStarBrightness() + weight * (F32) dest.getStarBrightness()); llassert(src.getSunAngle() >= - F_PI && src.getSunAngle() <= 3 * F_PI); llassert(dest.getSunAngle() >= - F_PI && dest.getSunAngle() <= 3 * F_PI); llassert(src.getEastAngle() >= 0 && src.getEastAngle() <= 4 * F_PI); llassert(dest.getEastAngle() >= 0 && dest.getEastAngle() <= 4 * F_PI); // sun angle and east angle require some handling to make sure // they go in circles. Yes quaternions would work better. F32 srcSunAngle = src.getSunAngle(); F32 destSunAngle = dest.getSunAngle(); F32 srcEastAngle = src.getEastAngle(); F32 destEastAngle = dest.getEastAngle(); if(fabsf(srcSunAngle - destSunAngle) > F_PI) { if(srcSunAngle > destSunAngle) { destSunAngle += 2 * F_PI; } else { srcSunAngle += 2 * F_PI; } } if(fabsf(srcEastAngle - destEastAngle) > F_PI) { if(srcEastAngle > destEastAngle) { destEastAngle += 2 * F_PI; } else { srcEastAngle += 2 * F_PI; } } setSunAngle((1 - weight) * srcSunAngle + weight * destSunAngle); setEastAngle((1 - weight) * srcEastAngle + weight * destEastAngle); // now setup the sun properly // reset those cloud positions mParamValues["cloud_pos_density1"][0] = cloudPos1X; mParamValues["cloud_pos_density1"][1] = cloudPos1Y; mParamValues["cloud_pos_density2"][0] = cloudPos2X; mParamValues["cloud_pos_density2"][1] = cloudPos2Y; mParamValues["cloud_shadow"][0] = cloudCover; }