UIRectangle UIRectangle::toLocal(UIRectangle r) { UIRectangle ret = r; ret.br = toLocal(ret.br); ret.tl = toLocal(ret.tl); return ret; }
void WirechamberCalibrator::tweakPosition(Side s, AxisDirection d, wireHit& h, double E) const { if(h.rawCenter == kUndefinedPosition) return; unsigned int n; float c; toLocal(s,d,h.rawCenter,n,c); h.center = fromLocal(s,d,n,cathsegs[s][d][n]->adjustPos(c,E)); }
bool ConcurrentTableSharedStore::cas(const String& key, int64_t old, int64_t val) { ReadLock l(m_lock); Map::accessor acc; if (!m_vars.find(acc, tagStringData(key.get()))) { return false; } auto& sval = acc->second; if (sval.expired()) return false; auto const oldHandle = sval.data.match( [&] (APCHandle* h) { return h; }, [&] (char* file) { return unserialize(key, &sval); } ); if (!oldHandle || oldHandle->toLocal().toInt64() != old) { return false; } auto const pair = APCHandle::Create(Variant(val), false, APCHandleLevel::Outer, false); APCStats::getAPCStats().updateAPCValue(pair.handle, pair.size, oldHandle, sval.dataSize, sval.expire == 0, false); oldHandle->unreferenceRoot(sval.dataSize); sval.data = pair.handle; sval.dataSize = pair.size; return true; }
int64_t ConcurrentTableSharedStore::inc(const String& key, int64_t step, bool& found) { found = false; ReadLock l(m_lock); Map::accessor acc; if (!m_vars.find(acc, tagStringData(key.get()))) { return 0; } auto& sval = acc->second; if (sval.expired()) return 0; /* * Inc only works on KindOfDouble or KindOfInt64, which are never kept in * file-backed storage from priming. So we don't need to try to deserialize * anything or handle the case that sval.data is file-backed. */ auto const oldHandle = sval.data.left(); if (oldHandle == nullptr) return 0; if (oldHandle->type() != KindOfInt64 && oldHandle->type() != KindOfDouble) { return 0; } auto const ret = oldHandle->toLocal().toInt64() + step; auto const pair = APCHandle::Create(Variant(ret), false); APCStats::getAPCStats().updateAPCValue(pair.handle, pair.size, oldHandle, sval.dataSize, sval.expire == 0, false); oldHandle->unreferenceRoot(sval.dataSize); sval.data = pair.handle; sval.dataSize = pair.size; found = true; return ret; }
void TexturedObjectScrollView::onTouchUp(TouchEvent &event){ float touchDurationSec = (event.timestamp - event.prevTimestamp) / 1000000.0f; if(touchDurationSec < 0.3 && event.position.distance(event.firstPosition) < 20 ){ //tapped! go to browsing TexturedObject * touchedObject = NULL; int texIndex = -1; int ID = -1; ofVec2f virtualPoint = toLocal(event.position); virtualPoint.x += xOffset; for(size_t i = 0; i < layout.size(); i++){ if(layout[i].placement.inside(virtualPoint)){ touchedObject = layout[i].texObjTex.texObj; texIndex = layout[i].texObjTex.texIndex; ID = layout[i].ID; //TODO send event! TouchedImage ti; ti.objTex.texObj = touchedObject; ti.objTex.texIndex = texIndex; ti.who = this; ti.layoutID = ID; ofNotifyEvent(eventTextureClicked, ti, this); } } } if(touchID == event.id){ touchID = -1; } }
bool Menubar::_openMenu( int nb ) { MenuBarItem * pItem = m_items.get(nb-1); if( pItem == 0 || !pItem->m_pMenu ) return false; Coord pos = toLocal( Coord(0, 0) ); if( m_pSkin ) pos = m_pSkin->contentRect( pos, StateEnum::Normal ).pos(); int bordersWidth = _getEntryBorder().width(); MenuBarItem * pI = m_items.first(); while( pI != pItem ) { if( pI->isVisible() ) pos.x += pI->m_width + bordersWidth; pI = pI->next(); } Rect r(pos, pI->m_width+bordersWidth, size().h ); PopupLayer * pLayer = 0; if( parent() ) pLayer = parent()->_getPopupLayer(); if( !pLayer ) return false; pLayer->openPopup( pItem->m_pMenu, this, r - pLayer->globalPos(), Origo::SouthWest ); return true; }
ConnectionResult CanvasComponent::getConnectionStart(const cease::MouseEvent& event) { Vec2f local = toLocal(event.getPos()); for (int i=0; i<inputNodes.size(); i++) { if (inputNodes[i]->contains(local)) { if (inputNodes[i]->isConnected()) { return ConnectionResult(TYPE_DISCONNECT_INPUT, inputNodes[i]); } } } for (int i=0; i<outputNodes.size(); i++) { if (outputNodes[i]->contains(local)) { if (outputNodes[i]->isConnected()) { return ConnectionResult(TYPE_DISCONNECT_OUTPUT, outputNodes[i]); } else { return ConnectionResult(TYPE_OUTPUT, outputNodes[i]); } } } return ConnectionResult(); }
uint32_t Menubar::_getItemAtAbsPos( int x, int y ) { Coord pos = toLocal( Coord(x, y) ); if( m_pSkin ) pos = m_pSkin->contentRect( pos, StateEnum::Normal ).pos(); if( y > 0 && x > 0 && y < (int) size().h ) { int bordersWidth = _getEntryBorder().width(); MenuBarItem * pItem = m_items.first(); int item = 1; while( pItem ) { if(pItem->isVisible()) { x -= pItem->m_width+bordersWidth; if( x < 0 ) return item; } pItem = pItem->next(); item++; } } return 0; }
Primitive* Body::getPrimitiveAtPoint(const QPointF &pnt_) { QPointF pnt = toLocal(pnt_); foreach( Primitive* p, m_primitives) { if ( p->isPointInside(pnt) ) return p; } return 0; }
bool UIScrollBar::checkHover(Point2D pt) { //box is always inside scrollbar _hover = inside(pt) ? true : false ; if ( _hover ) _box.checkHover( toLocal(pt) ); return _hover; }
void TexturedObjectScrollView::onTouchDown(TouchEvent &event){ if(touchID == -1){ touchID = event.id; scrollInertia = 0.0; //scrollHandleAlpha = 1.0; prevX = toLocal(event.position).x; } }
bool SelectorBase::touchesBegan( app::TouchEvent &event ) { setTouchCanceled( false ); auto &firstTouch = event.getTouches().front(); vec2 pos = toLocal( firstTouch.getPos() ); updateSelection( pos ); firstTouch.setHandled(); return true; }
std::istream* RPKGAdapter::getStream(const std::wstring& name) { if (files.find(name) == files.end()) { Log::error() << "No such file in RPKG archive: " << name; return 0; } RPKGEntry e = files[name]; return getRPKGFileStream(e, boost::shared_ptr<std::istream>(new std::ifstream(toLocal(m_fileName).c_str(), ios::binary | ios::in))); }
F32 LLPhysicsMotion::calculateVelocity_local() { const F32 world_to_model_scale = 100.0f; LLJoint *joint = mJointState->getJoint(); const LLVector3 position_world = joint->getWorldPosition(); const LLVector3 last_position_world = mPosition_world; const LLVector3 positionchange_world = (position_world-last_position_world) * world_to_model_scale; const LLVector3 velocity_world = positionchange_world; const F32 velocity_local = toLocal(velocity_world); return velocity_local; }
LLVector3 LLBreastMotion::calculateVelocity_local(const F32 time_delta) { LLJoint *chest_joint = mChestState->getJoint(); const LLVector3 world_pos_pt = chest_joint->getWorldPosition(); const LLQuaternion world_rot = chest_joint->getWorldRotation(); const LLVector3 last_world_pos_pt = mCharLastPosition_world_pt; const LLVector3 char_velocity_world_vec = (world_pos_pt-last_world_pos_pt) / time_delta; const LLVector3 char_velocity_local_vec = toLocal(char_velocity_world_vec); return char_velocity_local_vec; }
member_rval::ptr_u APCLocalArray::GetValueRef(const ArrayData* adIn, ssize_t pos) { auto const ad = asApcArray(adIn); assert(unsigned(pos) < ad->getSize()); auto const elms = ad->localCache(); auto const tv = &elms[pos]; if (tv->m_type != KindOfUninit) return tv; auto const sv = ad->m_arr->getValue(pos); tvAsVariant(tv) = sv->toLocal(); assert(tv->m_type != KindOfUninit); return tv; }
void TexturedObjectScrollView::onTouchMove(TouchEvent &event){ if(touchID == event.id){ scrollHandleAlpha = 1.0; ofVec2f localPos = toLocal(event.position); xOffset += (prevX - localPos.x); scrollInertia = (prevX - localPos.x) * config.scrollUserForceGain; prevX = localPos.x; fboDirty = FBO_DIRTY_TIME; xOffset = ofClamp(xOffset, -canvas.width, layoutWidth - getWidth() + canvas.width); } }
bool SelectorBase::touchesEnded( app::TouchEvent &event ) { if( isTouchCanceled() ) return false; vec2 pos = toLocal( event.getTouches().front().getPos() ); if( ! hitTestInsideCancelPadding( pos ) ) { setTouchCanceled( true ); return false; } updateSelection( pos ); return true; }
//FIXME: Pass std::wstring to std::ifstream constructor void RPKGAdapter::load(const wstring& fileName) { rpkgArchive.open(toLocal(fileName).c_str(), ios::binary | ios::in); if (!rpkgArchive.is_open()) { Log::error() << "Cannot load RPKG archive " << fileName << ": " << fromLocal(strerror(errno)); return; } std::list<RPKGEntry> l = loadRPKG(rpkgArchive); for (std::list<RPKGEntry>::const_iterator i = l.begin(); i != l.end(); i++) files[i->name] = *i; Log::info() << "Loaded " << files.size() << " files from RPKG archive " << fileName; m_fileName = fileName; }
Object APCObject::createObject() const { auto cls = m_cls.left(); assert(cls != nullptr); auto obj = Object::attach( m_fast_init ? ObjectData::newInstanceNoPropInit(const_cast<Class*>(cls)) : ObjectData::newInstance(const_cast<Class*>(cls)) ); auto const numProps = cls->numDeclProperties(); auto const objProp = obj->propVec(); auto const apcProp = persistentProps(); if (m_fast_init) { // re-entry is possible while we're executing toLocal() on each // property, so heap inspectors may see partially initid objects // not yet exposed to PHP. unsigned i = 0; try { for (; i < numProps; ++i) { new (objProp + i) Variant(apcProp[i]->toLocal()); } } catch (...) { for (; i < numProps; ++i) { new (objProp + i) Variant(); } throw; } } else { for (unsigned i = 0; i < numProps; ++i) { tvAsVariant(&objProp[i]) = apcProp[i]->toLocal(); } } if (UNLIKELY(numProps < m_propCount)) { auto dynProps = apcProp[numProps]; assert(dynProps->kind() == APCKind::StaticArray || dynProps->kind() == APCKind::UncountedArray || dynProps->kind() == APCKind::SharedArray); obj->setDynPropArray(dynProps->toLocal().asCArrRef()); } if (!m_no_wakeup) obj->invokeWakeup(); return obj; }
Object APCObject::createObject() const { auto cls = m_cls.left(); assert(cls != nullptr); auto obj = Object::attach( m_fast_init ? ObjectData::newInstanceNoPropInit(const_cast<Class*>(cls)) : ObjectData::newInstance(const_cast<Class*>(cls)) ); auto const numProps = cls->numDeclProperties(); auto const objProp = obj->propVec(); auto const apcProp = persistentProps(); if (m_fast_init) { unsigned i = 0; try { while (i < numProps) { new (objProp + i) Variant(apcProp[i]->toLocal()); ++i; } } catch (...) { while (i < numProps) { new (objProp + i) Variant(); ++i; } throw; } } else { for (unsigned i = 0; i < numProps; ++i) { tvAsVariant(&objProp[i]) = apcProp[i]->toLocal(); } } if (UNLIKELY(numProps < m_propCount)) { auto dynProps = apcProp[numProps]; assert(dynProps->kind() == APCKind::StaticArray || dynProps->kind() == APCKind::UncountedArray || dynProps->kind() == APCKind::SharedArray); obj->setDynPropArray(dynProps->toLocal().asCArrRef()); } if (!m_no_wakeup) obj->invokeWakeup(); return obj; }
const Variant& APCLocalArray::GetValueRef(const ArrayData* adIn, ssize_t pos) { auto const ad = asApcArray(adIn); auto const sv = ad->m_arr->getValue(pos); if (LIKELY(ad->m_localCache != nullptr)) { assert(unsigned(pos) < ad->m_arr->capacity()); TypedValue* tv = &ad->m_localCache[pos]; if (tv->m_type != KindOfUninit) { return tvAsCVarRef(tv); } } else { static_assert(KindOfUninit == 0, "must be 0 since we use req::calloc"); unsigned cap = ad->m_arr->capacity(); ad->m_localCache = req::calloc_raw_array<TypedValue>(cap); } auto const tv = &ad->m_localCache[pos]; tvAsVariant(tv) = sv->toLocal(); assert(tv->m_type != KindOfUninit); return tvAsCVarRef(tv); }
void RPKGAdapter::load(const string& fileName) { #ifdef WIN32 rpkgArchive.open(toLocal(fileName).c_str(), ios::binary | ios::in); #else rpkgArchive.open(fileName, ios::binary | ios::in); #endif if (!rpkgArchive.is_open()) { Log::error() << "Cannot load RPKG archive " << fileName << ": " << strerror(errno); return; } std::list<RPKGEntry> l = loadRPKG(rpkgArchive); for (std::list<RPKGEntry>::const_iterator i = l.begin(); i != l.end(); ++i) { std::string path = i->name; std::transform(i->name.begin(), i->name.end(), path.begin(), ::tolower); files[path] = *i; } Log::info() << "Loaded " << files.size() << " files from RPKG archive " << fileName; m_fileName = fileName; }
BOOL LLBreastMotion::onUpdate(F32 time, U8* joint_mask) { // Skip if disabled globally. if (!gSavedSettings.getBOOL("AvatarPhysics")) { return TRUE; } // Higher LOD is better. This controls the granularity // and frequency of updates for the motions. const F32 lod_factor = LLVOAvatar::sPhysicsLODFactor; if (lod_factor == 0) { return TRUE; } if (mCharacter->getSex() != SEX_FEMALE) return TRUE; const F32 time_delta = calculateTimeDelta(); if (time_delta < .01 || time_delta > 10.0) return TRUE; //////////////////////////////////////////////////////////////////////////////// // Get all parameters and settings // mBreastMassParam = mCharacter->getVisualParamWeight("Breast_Physics_Mass"); mBreastSmoothingParam = (U32)(mCharacter->getVisualParamWeight("Breast_Physics_Smoothing")); mBreastGravityParam = mCharacter->getVisualParamWeight("Breast_Physics_Gravity"); mBreastSpringParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Spring"); mBreastGainParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Gain"); mBreastDampingParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Damping"); mBreastMaxVelocityParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Max_Velocity"); mBreastDragParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Drag"); mBreastSpringParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Spring"); mBreastGainParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Gain"); mBreastDampingParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Damping"); mBreastMaxVelocityParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Max_Velocity"); mBreastDragParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Drag"); // Get the current morph parameters. LLVector3 breast_user_local_pt(0,0,0); for (U32 i=0; i < N_PARAMS; i++) { if (mBreastParamsUser[i] != NULL) { breast_user_local_pt[i] = mBreastParamsUser[i]->getWeight(); } } LLVector3 breast_current_local_pt = mBreastLastPosition_local_pt; // // End parameters and settings //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Calculate velocity and acceleration in parameter space. // const LLVector3 char_velocity_local_vec = calculateVelocity_local(time_delta); const LLVector3 char_acceleration_local_vec = calculateAcceleration_local(char_velocity_local_vec, time_delta); mCharLastVelocity_local_vec = char_velocity_local_vec; LLJoint *chest_joint = mChestState->getJoint(); mCharLastPosition_world_pt = chest_joint->getWorldPosition(); // // End velocity and acceleration //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Calculate the total force // // Spring force is a restoring force towards the original user-set breast position. // F = kx const LLVector3 spring_length_local = breast_current_local_pt-breast_user_local_pt; LLVector3 force_spring_local_vec = -spring_length_local; force_spring_local_vec *= mBreastSpringParam; // Acceleration is the force that comes from the change in velocity of the torso. // F = ma + mg LLVector3 force_accel_local_vec = char_acceleration_local_vec * mBreastMassParam; const LLVector3 force_gravity_local_vec = toLocal(LLVector3(0,0,1))* mBreastGravityParam * mBreastMassParam; force_accel_local_vec += force_gravity_local_vec; force_accel_local_vec *= mBreastGainParam; // Damping is a restoring force that opposes the current velocity. // F = -kv LLVector3 force_damping_local_vec = -mBreastDampingParam; force_damping_local_vec *= mBreastVelocity_local_vec; // Drag is a force imparted by velocity, intuitively it is similar to wind resistance. // F = .5v*v LLVector3 force_drag_local_vec = .5*char_velocity_local_vec; force_drag_local_vec *= char_velocity_local_vec; force_drag_local_vec *= mBreastDragParam[0]; LLVector3 force_net_local_vec = force_accel_local_vec + force_gravity_local_vec + force_spring_local_vec + force_damping_local_vec + force_drag_local_vec; // // End total force //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Calculate new params // // Calculate the new acceleration based on the net force. // a = F/m LLVector3 acceleration_local_vec = force_net_local_vec / mBreastMassParam; mBreastVelocity_local_vec += acceleration_local_vec; mBreastVelocity_local_vec.clamp(-mBreastMaxVelocityParam*100.0, mBreastMaxVelocityParam*100.0); // Temporary debugging setting to cause all avatars to move, for profiling purposes. if (gSavedSettings.getBOOL("AvatarPhysicsTest")) { mBreastVelocity_local_vec[0] = sin(mTimer.getElapsedTimeF32()*4.0)*5.0; mBreastVelocity_local_vec[1] = sin(mTimer.getElapsedTimeF32()*3.0)*5.0; } // Calculate the new parameters and clamp them to the min/max ranges. LLVector3 new_local_pt = breast_current_local_pt + mBreastVelocity_local_vec*time_delta; new_local_pt.clamp(mBreastParamsMin,mBreastParamsMax); // Set the new parameters. for (U32 i=0; i < 3; i++) { // If the param is disabled, just set the param to the user value. if (mBreastMaxVelocityParam[i] == 0) { new_local_pt[i] = breast_user_local_pt[i]; } if (mBreastParamsDriven[i]) { mCharacter->setVisualParamWeight(mBreastParamsDriven[i], new_local_pt[i], FALSE); } } mBreastLastPosition_local_pt = new_local_pt; // // End calculate new params //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Conditionally update the visual params // // Updating the visual params (i.e. what the user sees) is fairly expensive. // So only update if the params have changed enough, and also take into account // the graphics LOD settings. // For non-self, if the avatar is small enough visually, then don't update. const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(this) != NULL); if (!is_self) { const F32 area_for_max_settings = 0.0; const F32 area_for_min_settings = 1400.0; const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor); const F32 pixel_area = fsqrtf(mCharacter->getPixelArea()); if (pixel_area < area_for_this_setting) { return TRUE; } } // If the parameter hasn't changed enough, then don't update. LLVector3 position_diff = mBreastLastUpdatePosition_local_pt-new_local_pt; for (U32 i=0; i < 3; i++) { const F32 min_delta = (1.0-lod_factor)*(mBreastParamsMax[i]-mBreastParamsMin[i])/2.0; if (llabs(position_diff[i]) > min_delta) { mCharacter->updateVisualParams(); mBreastLastUpdatePosition_local_pt = new_local_pt; return TRUE; } } // // End update visual params //////////////////////////////////////////////////////////////////////////////// return TRUE; }
LocalTime LocalTime::Now() { return toLocal(Time::Now()); }
static TVector3 floorXYZ_Local(double zvtx, double physeta, double physphi) { return toLocal(floorXYZ(zvtx,physeta,physphi)); }
// Return TRUE if character has to update visual params. BOOL LLPhysicsMotion::onUpdate(F32 time) { // static FILE *mFileWrite = fopen("c:\\temp\\avatar_data.txt","w"); if (!mParamDriver) return FALSE; if (!mLastTime) { mLastTime = time; return FALSE; } //////////////////////////////////////////////////////////////////////////////// // Get all parameters and settings // const F32 time_delta = time - mLastTime; // Don't update too frequently, to avoid precision errors from small time slices. if (time_delta <= .01) { return FALSE; } // If less than 1FPS, we don't want to be spending time updating physics at all. if (time_delta > 1.0) { mLastTime = time; return FALSE; } // Higher LOD is better. This controls the granularity // and frequency of updates for the motions. const F32 lod_factor = LLVOAvatar::sPhysicsLODFactor; if (lod_factor == 0) { return TRUE; } LLJoint *joint = mJointState->getJoint(); const F32 behavior_mass = getParamValue("Mass"); const F32 behavior_gravity = getParamValue("Gravity"); const F32 behavior_spring = getParamValue("Spring"); const F32 behavior_gain = getParamValue("Gain"); const F32 behavior_damping = getParamValue("Damping"); const F32 behavior_drag = getParamValue("Drag"); const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts. F32 behavior_maxeffect = getParamValue("MaxEffect"); if (physics_test) behavior_maxeffect = 1.0f; // Normalize the param position to be from [0,1]. // We have to use normalized values because there may be more than one driven param, // and each of these driven params may have its own range. // This means we'll do all our calculations in normalized [0,1] local coordinates. const F32 position_user_local = (mParamDriver->getWeight() - mParamDriver->getMinWeight()) / (mParamDriver->getMaxWeight() - mParamDriver->getMinWeight()); // // End parameters and settings //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Calculate velocity and acceleration in parameter space. // //const F32 velocity_joint_local = calculateVelocity_local(time_iteration_step); const F32 velocity_joint_local = calculateVelocity_local(); const F32 acceleration_joint_local = calculateAcceleration_local(velocity_joint_local); // // End velocity and acceleration //////////////////////////////////////////////////////////////////////////////// BOOL update_visuals = FALSE; // Break up the physics into a bunch of iterations so that differing framerates will show // roughly the same behavior. for (F32 time_iteration = 0; time_iteration <= time_delta; time_iteration += TIME_ITERATION_STEP) { F32 time_iteration_step = TIME_ITERATION_STEP; if (time_iteration + TIME_ITERATION_STEP > time_delta) { time_iteration_step = time_delta-time_iteration; } // mPositon_local should be in normalized 0,1 range already. Just making sure... const F32 position_current_local = llclamp(mPosition_local, 0.0f, 1.0f); // If the effect is turned off then don't process unless we need one more update // to set the position to the default (i.e. user) position. if ((behavior_maxeffect == 0) && (position_current_local == position_user_local)) { return update_visuals; } //////////////////////////////////////////////////////////////////////////////// // Calculate the total force // // Spring force is a restoring force towards the original user-set breast position. // F = kx const F32 spring_length = position_current_local - position_user_local; const F32 force_spring = -spring_length * behavior_spring; // Acceleration is the force that comes from the change in velocity of the torso. // F = ma const F32 force_accel = behavior_gain * (acceleration_joint_local * behavior_mass); // Gravity always points downward in world space. // F = mg const LLVector3 gravity_world(0,0,1); const F32 force_gravity = (toLocal(gravity_world) * behavior_gravity * behavior_mass); // Damping is a restoring force that opposes the current velocity. // F = -kv const F32 force_damping = -behavior_damping * mVelocity_local; // Drag is a force imparted by velocity (intuitively it is similar to wind resistance) // F = .5kv^2 const F32 force_drag = .5*behavior_drag*velocity_joint_local*velocity_joint_local*llsgn(velocity_joint_local); const F32 force_net = (force_accel + force_gravity + force_spring + force_damping + force_drag); // // End total force //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Calculate new params // // Calculate the new acceleration based on the net force. // a = F/m const F32 acceleration_new_local = force_net / behavior_mass; static const F32 max_velocity = 100.0f; // magic number, used to be customizable. F32 velocity_new_local = mVelocity_local + acceleration_new_local*time_iteration_step; velocity_new_local = llclamp(velocity_new_local, -max_velocity, max_velocity); // Temporary debugging setting to cause all avatars to move, for profiling purposes. if (physics_test) { velocity_new_local = sin(time*4.0); } // Calculate the new parameters, or remain unchanged if max speed is 0. F32 position_new_local = position_current_local + velocity_new_local*time_iteration_step; if (behavior_maxeffect == 0) position_new_local = position_user_local; // Zero out the velocity if the param is being pushed beyond its limits. if ((position_new_local < 0 && velocity_new_local < 0) || (position_new_local > 1 && velocity_new_local > 0)) { velocity_new_local = 0; } // Check for NaN values. A NaN value is detected if the variables doesn't equal itself. // If NaN, then reset everything. if ((mPosition_local != mPosition_local) || (mVelocity_local != mVelocity_local) || (position_new_local != position_new_local)) { position_new_local = 0; mVelocity_local = 0; mVelocityJoint_local = 0; mAccelerationJoint_local = 0; mPosition_local = 0; mPosition_world = LLVector3(0,0,0); } const F32 position_new_local_clamped = llclamp(position_new_local, 0.0f, 1.0f); LLDriverParam *driver_param = dynamic_cast<LLDriverParam *>(mParamDriver); llassert_always(driver_param); if (driver_param) { // If this is one of our "hidden" driver params, then make sure it's // the default value. if ((driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) && (driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT)) { mCharacter->setVisualParamWeight(driver_param, 0, FALSE); } for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin(); iter != driver_param->mDriven.end(); ++iter) { LLDrivenEntry &entry = (*iter); LLViewerVisualParam *driven_param = entry.mParam; setParamValue(driven_param,position_new_local_clamped, behavior_maxeffect); } } // // End calculate new params //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // Conditionally update the visual params // // Updating the visual params (i.e. what the user sees) is fairly expensive. // So only update if the params have changed enough, and also take into account // the graphics LOD settings. // For non-self, if the avatar is small enough visually, then don't update. const F32 area_for_max_settings = 0.0; const F32 area_for_min_settings = 1400.0; const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor); const F32 pixel_area = (F32)sqrt(mCharacter->getPixelArea()); const BOOL is_self = (dynamic_cast<LLVOAvatar *>(mCharacter) != NULL && ((LLVOAvatar*)mCharacter)->isSelf()); if ((pixel_area > area_for_this_setting) || is_self) { const F32 position_diff_local = llabs(mPositionLastUpdate_local-position_new_local_clamped); const F32 min_delta = (1.0001f-lod_factor)*0.4f; if (llabs(position_diff_local) > min_delta) { update_visuals = TRUE; mPositionLastUpdate_local = position_new_local; } } // // End update visual params //////////////////////////////////////////////////////////////////////////////// mVelocity_local = velocity_new_local; mAccelerationJoint_local = acceleration_joint_local; mPosition_local = position_new_local; } mLastTime = time; mPosition_world = joint->getWorldPosition(); mVelocityJoint_local = velocity_joint_local; /* // Write out debugging info into a spreadsheet. if (mFileWrite != NULL && is_self) { fprintf(mFileWrite,"%f\t%f\t%f \t\t%f \t\t%f\t%f\t%f\t \t\t%f\t%f\t%f\t%f\t%f \t\t%f\t%f\t%f\n", position_new_local, velocity_new_local, acceleration_new_local, time_delta, mPosition_world[0], mPosition_world[1], mPosition_world[2], force_net, force_spring, force_accel, force_damping, force_drag, spring_length, velocity_joint_local, acceleration_joint_local ); } */ return update_visuals; }