bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits) { // We're comparing strict equality of LLSD representation rather than // performing any conversions. So if the types aren't equal, the LLSD // values aren't equal. if (lhs.type() != rhs.type()) { return false; } // Here we know both types are equal. Now compare values. switch (lhs.type()) { case LLSD::TypeUndefined: // Both are TypeUndefined. There's nothing more to know. return true; case LLSD::TypeReal: // This is where the 'bits' argument comes in handy. If passed // explicitly, it means to use is_approx_equal_fraction() to compare. if (bits >= 0) { return is_approx_equal_fraction(lhs.asReal(), rhs.asReal(), bits); } // Otherwise we compare bit representations, and the usual caveats // about comparing floating-point numbers apply. Omitting 'bits' when // comparing Real values is only useful when we expect identical bit // representation for a given Real value, e.g. for integer-valued // Reals. return (lhs.asReal() == rhs.asReal()); #define COMPARE_SCALAR(type) \ case LLSD::Type##type: \ /* LLSD::URI has operator!=() but not operator==() */ \ /* rely on the optimizer for all others */ \ return (! (lhs.as##type() != rhs.as##type())) COMPARE_SCALAR(Boolean); COMPARE_SCALAR(Integer); COMPARE_SCALAR(String); COMPARE_SCALAR(UUID); COMPARE_SCALAR(Date); COMPARE_SCALAR(URI); COMPARE_SCALAR(Binary); #undef COMPARE_SCALAR case LLSD::TypeArray: { LLSD::array_const_iterator lai(lhs.beginArray()), laend(lhs.endArray()), rai(rhs.beginArray()), raend(rhs.endArray()); // Compare array elements, walking the two arrays in parallel. for ( ; lai != laend && rai != raend; ++lai, ++rai) { // If any one array element is unequal, the arrays are unequal. if (! llsd_equals(*lai, *rai, bits)) return false; } // Here we've reached the end of one or the other array. They're equal // only if they're BOTH at end: that is, if they have equal length too. return (lai == laend && rai == raend); } case LLSD::TypeMap: { // Build a set of all rhs keys. std::set<LLSD::String> rhskeys; for (LLSD::map_const_iterator rmi(rhs.beginMap()), rmend(rhs.endMap()); rmi != rmend; ++rmi) { rhskeys.insert(rmi->first); } // Now walk all the lhs keys. for (LLSD::map_const_iterator lmi(lhs.beginMap()), lmend(lhs.endMap()); lmi != lmend; ++lmi) { // Try to erase this lhs key from the set of rhs keys. If rhs has // no such key, the maps are unequal. erase(key) returns count of // items erased. if (rhskeys.erase(lmi->first) != 1) return false; // Both maps have the current key. Compare values. if (! llsd_equals(lmi->second, rhs[lmi->first], bits)) return false; } // We've now established that all the lhs keys have equal values in // both maps. The maps are equal unless rhs contains a superset of // those keys. return rhskeys.empty(); } default: // We expect that every possible type() value is specifically handled // above. Failing to extend this switch to support a new LLSD type is // an error that must be brought to the coder's attention. LL_ERRS("llsd_equals") << "llsd_equals(" << lhs << ", " << rhs << ", " << bits << "): " "unknown type " << lhs.type() << LL_ENDL; return false; // pacify the compiler } }
static bool handleFlexLODChanged(const LLSD& newvalue) { LLVolumeImplFlexible::sUpdateFactor = (F32) newvalue.asReal(); return true; }
static bool handleBandwidthChanged(const LLSD& newvalue) { gViewerThrottle.setMaxBandwidth((F32) newvalue.asReal()); return true; }
static bool handleTerrainScaleChanged(const LLSD& inputvalue) { LLSD newvalue = 1.f / inputvalue.asReal(); LLDrawPoolTerrain::sDetailScale = newvalue.asReal(); return true; }
static bool handleAvatarPhysicsLODChanged(const LLSD& newvalue) { LLVOAvatar::sPhysicsLODFactor = (F32) newvalue.asReal(); return true; }
static bool handleAvatarBoobXYInfluence(const LLSD& newvalue) { LLVOAvatar::sBoobConfig.XYInfluence = (F32) newvalue.asReal(); return true; }
void LLFilterSD2XMLRPC::streamOut(std::ostream& ostr, const LLSD& sd) { ostr << "<value>"; switch(sd.type()) { case LLSD::TypeMap: { #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(map) BEGIN" << llendl; #endif ostr << "<struct>"; if(ostr.fail()) { llinfos << "STREAM FAILURE writing struct" << llendl; } LLSD::map_const_iterator it = sd.beginMap(); LLSD::map_const_iterator end = sd.endMap(); for(; it != end; ++it) { ostr << "<member><name>" << xml_escape_string((*it).first) << "</name>"; streamOut(ostr, (*it).second); if(ostr.fail()) { llinfos << "STREAM FAILURE writing '" << (*it).first << "' with sd type " << (*it).second.type() << llendl; } ostr << "</member>"; } ostr << "</struct>"; #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(map) END" << llendl; #endif break; } case LLSD::TypeArray: { #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(array) BEGIN" << llendl; #endif ostr << "<array><data>"; LLSD::array_const_iterator it = sd.beginArray(); LLSD::array_const_iterator end = sd.endArray(); for(; it != end; ++it) { streamOut(ostr, *it); if(ostr.fail()) { llinfos << "STREAM FAILURE writing array element sd type " << (*it).type() << llendl; } } #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(array) END" << llendl; #endif ostr << "</data></array>"; break; } case LLSD::TypeUndefined: // treat undefined as a bool with a false value. case LLSD::TypeBoolean: #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(bool)" << llendl; #endif ostr << "<boolean>" << (sd.asBoolean() ? "1" : "0") << "</boolean>"; break; case LLSD::TypeInteger: #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(int)" << llendl; #endif ostr << "<i4>" << sd.asInteger() << "</i4>"; break; case LLSD::TypeReal: #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(real)" << llendl; #endif ostr << "<double>" << sd.asReal() << "</double>"; break; case LLSD::TypeString: #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(string)" << llendl; #endif ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>"; break; case LLSD::TypeUUID: #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(uuid)" << llendl; #endif // serialize it as a string ostr << "<string>" << sd.asString() << "</string>"; break; case LLSD::TypeURI: { #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(uri)" << llendl; #endif // serialize it as a string ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>"; break; } case LLSD::TypeBinary: { #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(binary)" << llendl; #endif // this is pretty inefficient, but we'll deal with that // problem when it becomes one. ostr << "<base64>"; LLSD::Binary buffer = sd.asBinary(); if(!buffer.empty()) { // *TODO: convert to LLBase64 int b64_buffer_length = apr_base64_encode_len(buffer.size()); char* b64_buffer = new char[b64_buffer_length]; b64_buffer_length = apr_base64_encode_binary( b64_buffer, &buffer[0], buffer.size()); ostr.write(b64_buffer, b64_buffer_length - 1); delete[] b64_buffer; } ostr << "</base64>"; break; } case LLSD::TypeDate: #if LL_SPEW_STREAM_OUT_DEBUGGING llinfos << "streamOut(date)" << llendl; #endif // no need to escape this since it will be alpha-numeric. ostr << "<dateTime.iso8601>" << sd.asString() << "</dateTime.iso8601>"; break; default: // unhandled type llwarns << "Unhandled structured data type: " << sd.type() << llendl; break; } ostr << "</value>"; }
static bool handleAvatarBoobVelMaxChanged(const LLSD& newvalue) { LLVOAvatar::sBoobConfig.velMax = Meta7BoobUtils::convertVelMax((F32) newvalue.asReal()); LLVOAvatar::sBoobConfig.velMin = LLVOAvatar::sBoobConfig.velMin*LLVOAvatar::sBoobConfig.velMax; return true; }
// virtual S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const { S32 format_count = 1; switch(data.type()) { case LLSD::TypeMap: { ostr.put('{'); U32 size_nbo = htonl(data.size()); ostr.write((const char*)(&size_nbo), sizeof(U32)); LLSD::map_const_iterator iter = data.beginMap(); LLSD::map_const_iterator end = data.endMap(); for(; iter != end; ++iter) { ostr.put('k'); formatString((*iter).first, ostr); format_count += format((*iter).second, ostr); } ostr.put('}'); break; } case LLSD::TypeArray: { ostr.put('['); U32 size_nbo = htonl(data.size()); ostr.write((const char*)(&size_nbo), sizeof(U32)); LLSD::array_const_iterator iter = data.beginArray(); LLSD::array_const_iterator end = data.endArray(); for(; iter != end; ++iter) { format_count += format(*iter, ostr); } ostr.put(']'); break; } case LLSD::TypeUndefined: ostr.put('!'); break; case LLSD::TypeBoolean: if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL); else ostr.put(BINARY_FALSE_SERIAL); break; case LLSD::TypeInteger: { ostr.put('i'); U32 value_nbo = htonl(data.asInteger()); ostr.write((const char*)(&value_nbo), sizeof(U32)); break; } case LLSD::TypeReal: { ostr.put('r'); F64 value_nbo = ll_htond(data.asReal()); ostr.write((const char*)(&value_nbo), sizeof(F64)); break; } case LLSD::TypeUUID: { ostr.put('u'); LLUUID value = data.asUUID(); ostr.write((const char*)(&value.mData), UUID_BYTES); break; } case LLSD::TypeString: ostr.put('s'); formatString(data.asString(), ostr); break; case LLSD::TypeDate: { ostr.put('d'); F64 value = data.asReal(); ostr.write((const char*)(&value), sizeof(F64)); break; } case LLSD::TypeURI: ostr.put('l'); formatString(data.asString(), ostr); break; case LLSD::TypeBinary: { // *FIX: memory inefficient. ostr.put('b'); std::vector<U8> buffer = data.asBinary(); U32 size_nbo = htonl(buffer.size()); ostr.write((const char*)(&size_nbo), sizeof(U32)); if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); break; } default: // *NOTE: This should never happen. ostr.put('!'); break; } return format_count; }
static bool handleAvMorphTimeChanged(const LLSD& newvalue) { LLVOAvatar::sAvMorphTime = (F32) newvalue.asReal(); return true; }
static bool handleAvatarBoobMassChanged(const LLSD& newvalue) { LLVOAvatar::sBoobConfig.mass = Meta7BoobUtils::convertMass((F32) newvalue.asReal()); return true; }
//static void LLManip::updatePivotZ(const LLSD &data) { sPivotZ = (F32)data.asReal(); }
template <> void jc_rebind::rebind_callback<F32>(const LLSD &data, F32 *reciever){ *reciever = data.asReal(); }
void LLStatGraph::setValue(const LLSD& value) { mValue = (F32)value.asReal(); }
static bool handleAvatarBoobVelMinChanged(const LLSD& newvalue) { LLVOAvatar::sBoobConfig.velMin = EmeraldBoobUtils::convertVelMin((F32) newvalue.asReal())*LLVOAvatar::sBoobConfig.velMax; return true; }
void LLInspectAvatar::onVolumeChange(const LLSD& data) { F32 volume = (F32)data.asReal(); gVoiceClient->setUserVolume(mAvatarID, volume); }
static bool handleAvatarBoobToggleChanged(const LLSD& newvalue) { LLVOAvatar::sBoobConfig.enabled = (BOOL) newvalue.asReal(); return true; }
S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const { S32 format_count = 1; std::string pre; std::string post; if (options & LLSDFormatter::OPTIONS_PRETTY) { for (U32 i = 0; i < level; i++) { pre += " "; } post = "\n"; } switch(data.type()) { case LLSD::TypeMap: if (0 == data.size()) { ostr << pre << "<map />" << post; } else { ostr << pre << "<map>" << post; LLSD::map_const_iterator iter = data.beginMap(); LLSD::map_const_iterator end = data.endMap(); for (; iter != end; ++iter) { ostr << pre << "<key>" << escapeString((*iter).first) << "</key>" << post; format_count += format_impl((*iter).second, ostr, options, level + 1); } ostr << pre << "</map>" << post; } break; case LLSD::TypeArray: if (0 == data.size()) { ostr << pre << "<array />" << post; } else { ostr << pre << "<array>" << post; LLSD::array_const_iterator iter = data.beginArray(); LLSD::array_const_iterator end = data.endArray(); for(; iter != end; ++iter) { format_count += format_impl(*iter, ostr, options, level + 1); } ostr << pre << "</array>" << post; } break; case LLSD::TypeUndefined: ostr << pre << "<undef />" << post; break; case LLSD::TypeBoolean: ostr << pre << "<boolean>"; if (mBoolAlpha || (ostr.flags() & std::ios::boolalpha)) { ostr << (data.asBoolean() ? "true" : "false"); } else { ostr << (data.asBoolean() ? 1 : 0); } ostr << "</boolean>" << post; break; case LLSD::TypeInteger: ostr << pre << "<integer>" << data.asInteger() << "</integer>" << post; break; case LLSD::TypeReal: ostr << pre << "<real>"; if (mRealFormat.empty()) { ostr << data.asReal(); } else { formatReal(data.asReal(), ostr); } ostr << "</real>" << post; break; case LLSD::TypeUUID: if (data.asUUID().isNull()) { ostr << pre << "<uuid />" << post; } else { ostr << pre << "<uuid>" << data.asUUID() << "</uuid>" << post; } break; case LLSD::TypeString: if (data.asString().empty()) ostr << pre << "<string />" << post; else ostr << pre << "<string>" << escapeString(data.asString()) <<"</string>" << post; break; case LLSD::TypeDate: ostr << pre << "<date>" << data.asDate() << "</date>" << post; break; case LLSD::TypeURI: ostr << pre << "<uri>" << escapeString(data.asString()) << "</uri>" << post; break; case LLSD::TypeBinary: { LLSD::Binary buffer = data.asBinary(); if (buffer.empty()) { ostr << pre << "<binary />" << post; } else { // *FIX: memory inefficient. // *TODO: convert to use LLBase64 ostr << pre << "<binary encoding=\"base64\">"; int b64_buffer_length = apr_base64_encode_len(buffer.size()); char* b64_buffer = new char[b64_buffer_length]; b64_buffer_length = apr_base64_encode_binary(b64_buffer, &buffer[0], buffer.size()); ostr.write(b64_buffer, b64_buffer_length - 1); delete[] b64_buffer; ostr << "</binary>" << post; } break; } default: // *NOTE: This should never happen. ostr << pre << "<undef />" << post; break; } return format_count; }
void ensure_equals(const std::string& msg, const LLSD& actual, const LLSD& expected) { ensure_equals(msg + " type", actual.type(), expected.type()); switch (actual.type()) { case LLSD::TypeUndefined: return; case LLSD::TypeBoolean: ensure_equals(msg + " boolean", actual.asBoolean(), expected.asBoolean()); return; case LLSD::TypeInteger: ensure_equals(msg + " integer", actual.asInteger(), expected.asInteger()); return; case LLSD::TypeReal: ensure_equals(msg + " real", actual.asReal(), expected.asReal()); return; case LLSD::TypeString: ensure_equals(msg + " string", actual.asString(), expected.asString()); return; case LLSD::TypeUUID: ensure_equals(msg + " uuid", actual.asUUID(), expected.asUUID()); return; case LLSD::TypeDate: ensure_equals(msg + " date", actual.asDate(), expected.asDate()); return; case LLSD::TypeURI: ensure_equals(msg + " uri", actual.asURI(), expected.asURI()); return; case LLSD::TypeBinary: ensure_equals(msg + " binary", actual.asBinary(), expected.asBinary()); return; case LLSD::TypeMap: { ensure_equals(msg + " map size", actual.size(), expected.size()); LLSD::map_const_iterator actual_iter = actual.beginMap(); LLSD::map_const_iterator expected_iter = expected.beginMap(); while(actual_iter != actual.endMap()) { ensure_equals(msg + " map keys", actual_iter->first, expected_iter->first); ensure_equals(msg + "[" + actual_iter->first + "]", actual_iter->second, expected_iter->second); ++actual_iter; ++expected_iter; } return; } case LLSD::TypeArray: { ensure_equals(msg + " array size", actual.size(), expected.size()); for(int i = 0; i < actual.size(); ++i) { ensure_equals(msg + llformat("[%d]", i), actual[i], expected[i]); } return; } default: // should never get here, but compiler produces warning if we // don't cover this case, and at Linden warnings are fatal. throw failure(STRINGIZE("invalid type field " << actual.type())); } }
void LLAvatarListItem::onVolumeChange(const LLSD& data) { F32 volume = (F32)data.asReal(); LLVoiceClient::getInstance()->setUserVolume(mAvatarId, volume); }
void LLPanelIMControlPanel::onVolumeChange(const LLSD& data) { F32 volume = (F32)data.asReal(); LLVoiceClient::getInstance()->setUserVolume(mAvatarID, volume); }
// static void LLViewerCamera::updateCameraAngle( void* user_data, const LLSD& value) { LLViewerCamera* self=(LLViewerCamera*)user_data; self->setDefaultFOV(value.asReal()); }
static bool handleVolumeLODChanged(const LLSD& newvalue) { LLVOVolume::sLODFactor = (F32) newvalue.asReal(); LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f; return true; }
static bool handleHTTPBandwidthChanged(const LLSD& newvalue) { AIPerService::setHTTPThrottleBandwidth((F32) newvalue.asReal()); return true; }
static bool handleTreeLODChanged(const LLSD& newvalue) { LLVOTree::sTreeFactor = (F32) newvalue.asReal(); return true; }
static bool handleAvatarBoobHardnessChanged(const LLSD& newvalue) { LLVOAvatar::sBoobConfig.hardness = EmeraldBoobUtils::convertHardness((F32) newvalue.asReal()); return true; }
static bool handleFogRatioChanged(const LLSD& newvalue) { F32 fog_ratio = llmax(MIN_USER_FOG_RATIO, llmin((F32) newvalue.asReal(), MAX_USER_FOG_RATIO)); gSky.setFogRatio(fog_ratio); return true; }
static bool handleAvatarBoobFrictionChanged(const LLSD& newvalue) { LLVOAvatar::sBoobConfig.friction = EmeraldBoobUtils::convertFriction((F32) newvalue.asReal()); return true; }
// virtual S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const { S32 format_count = 1; switch(data.type()) { case LLSD::TypeMap: { ostr << "{"; bool need_comma = false; LLSD::map_const_iterator iter = data.beginMap(); LLSD::map_const_iterator end = data.endMap(); for(; iter != end; ++iter) { if(need_comma) ostr << ","; need_comma = true; ostr << '\''; serialize_string((*iter).first, ostr); ostr << "':"; format_count += format((*iter).second, ostr); } ostr << "}"; break; } case LLSD::TypeArray: { ostr << "["; bool need_comma = false; LLSD::array_const_iterator iter = data.beginArray(); LLSD::array_const_iterator end = data.endArray(); for(; iter != end; ++iter) { if(need_comma) ostr << ","; need_comma = true; format_count += format(*iter, ostr); } ostr << "]"; break; } case LLSD::TypeUndefined: ostr << "!"; break; case LLSD::TypeBoolean: if(mBoolAlpha || #if( LL_WINDOWS || __GNUC__ > 2) (ostr.flags() & std::ios::boolalpha) #else (ostr.flags() & 0x0100) #endif ) { ostr << (data.asBoolean() ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL); } else { ostr << (data.asBoolean() ? 1 : 0); } break; case LLSD::TypeInteger: ostr << "i" << data.asInteger(); break; case LLSD::TypeReal: ostr << "r"; if(mRealFormat.empty()) { ostr << data.asReal(); } else { formatReal(data.asReal(), ostr); } break; case LLSD::TypeUUID: ostr << "u" << data.asUUID(); break; case LLSD::TypeString: ostr << '\''; serialize_string(data.asString(), ostr); ostr << '\''; break; case LLSD::TypeDate: ostr << "d\"" << data.asDate() << "\""; break; case LLSD::TypeURI: ostr << "l\""; serialize_string(data.asString(), ostr); ostr << "\""; break; case LLSD::TypeBinary: { // *FIX: memory inefficient. std::vector<U8> buffer = data.asBinary(); ostr << "b(" << buffer.size() << ")\""; if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); ostr << "\""; break; } default: // *NOTE: This should never happen. ostr << "!"; break; } return format_count; }
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; }