PageRenderTime 128ms CodeModel.GetById 51ms app.highlight 68ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llphysicsmotion.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 732 lines | 473 code | 99 blank | 160 comment | 52 complexity | 1ec64911da527e131c1d491298940f99 MD5 | raw file
  1/** 
  2 * @file llphysicsmotion.cpp
  3 * @brief Implementation of LLPhysicsMotion class.
  4 *
  5 * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2011, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27//-----------------------------------------------------------------------------
 28// Header Files
 29//-----------------------------------------------------------------------------
 30#include "llviewerprecompiledheaders.h"
 31#include "linden_common.h"
 32
 33#include "m3math.h"
 34#include "v3dmath.h"
 35
 36#include "llphysicsmotion.h"
 37#include "llagent.h"
 38#include "llcharacter.h"
 39#include "llviewercontrol.h"
 40#include "llviewervisualparam.h"
 41#include "llvoavatarself.h"
 42
 43typedef std::map<std::string, std::string> controller_map_t;
 44typedef std::map<std::string, F32> default_controller_map_t;
 45
 46#define MIN_REQUIRED_PIXEL_AREA_AVATAR_PHYSICS_MOTION 0.f
 47#define TIME_ITERATION_STEP 0.1f
 48
 49inline F64 llsgn(const F64 a)
 50{
 51        if (a >= 0)
 52                return 1;
 53        return -1;
 54}
 55
 56/* 
 57   At a high level, this works by setting temporary parameters that are not stored
 58   in the avatar's list of params, and are not conveyed to other users.  We accomplish
 59   this by creating some new temporary driven params inside avatar_lad that are then driven
 60   by the actual params that the user sees and sets.  For example, in the old system,
 61   the user sets a param called breast bouyancy, which controls the Z value of the breasts.
 62   In our new system, the user still sets the breast bouyancy, but that param is redefined
 63   as a driver param so that affects a new temporary driven param that the bounce is applied
 64   to.
 65*/
 66
 67class LLPhysicsMotion
 68{
 69public:
 70        /*
 71          param_driver_name: The param that controls the params that are being affected by the physics.
 72          joint_name: The joint that the body part is attached to.  The joint is
 73          used to determine the orientation (rotation) of the body part.
 74
 75          character: The avatar that this physics affects.
 76
 77          motion_direction_vec: The direction (in world coordinates) that determines the
 78          motion.  For example, (0,0,1) is up-down, and means that up-down motion is what
 79          determines how this joint moves.
 80
 81          controllers: The various settings (e.g. spring force, mass) that determine how
 82          the body part behaves.
 83        */
 84        LLPhysicsMotion(const std::string &param_driver_name, 
 85                        const std::string &joint_name,
 86                        LLCharacter *character,
 87                        const LLVector3 &motion_direction_vec,
 88                        const controller_map_t &controllers) :
 89                mParamDriverName(param_driver_name),
 90                mJointName(joint_name),
 91                mMotionDirectionVec(motion_direction_vec),
 92                mParamDriver(NULL),
 93                mParamControllers(controllers),
 94                mCharacter(character),
 95                mLastTime(0),
 96                mPosition_local(0),
 97                mVelocityJoint_local(0),
 98                mPositionLastUpdate_local(0)
 99        {
100                mJointState = new LLJointState;
101        }
102
103        BOOL initialize();
104
105        ~LLPhysicsMotion() {}
106
107        BOOL onUpdate(F32 time);
108
109        LLPointer<LLJointState> getJointState() 
110        {
111                return mJointState;
112        }
113protected:
114        F32 getParamValue(const std::string& controller_key)
115        {
116                const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key);
117                if (entry == mParamControllers.end())
118                {
119                        return sDefaultController[controller_key];
120                }
121                const std::string& param_name = (*entry).second.c_str();
122                return mCharacter->getVisualParamWeight(param_name.c_str());
123        }
124        void setParamValue(LLViewerVisualParam *param,
125                           const F32 new_value_local,
126                                                   F32 behavior_maxeffect);
127
128        F32 toLocal(const LLVector3 &world);
129        F32 calculateVelocity_local();
130        F32 calculateAcceleration_local(F32 velocity_local);
131private:
132        const std::string mParamDriverName;
133        const std::string mParamControllerName;
134        const LLVector3 mMotionDirectionVec;
135        const std::string mJointName;
136
137        F32 mPosition_local;
138        F32 mVelocityJoint_local; // How fast the joint is moving
139        F32 mAccelerationJoint_local; // Acceleration on the joint
140
141        F32 mVelocity_local; // How fast the param is moving
142        F32 mPositionLastUpdate_local;
143        LLVector3 mPosition_world;
144
145        LLViewerVisualParam *mParamDriver;
146        const controller_map_t mParamControllers;
147        
148        LLPointer<LLJointState> mJointState;
149        LLCharacter *mCharacter;
150
151        F32 mLastTime;
152        
153        static default_controller_map_t sDefaultController;
154};
155
156default_controller_map_t initDefaultController()
157{
158        default_controller_map_t controller;
159        controller["Mass"] = 0.2f;
160        controller["Gravity"] = 0.0f;
161        controller["Damping"] = .05f;
162        controller["Drag"] = 0.15f;
163        controller["MaxEffect"] = 0.1f;
164        controller["Spring"] = 0.1f;
165        controller["Gain"] = 10.0f;
166        return controller;
167}
168
169default_controller_map_t LLPhysicsMotion::sDefaultController = initDefaultController();
170
171BOOL LLPhysicsMotion::initialize()
172{
173        if (!mJointState->setJoint(mCharacter->getJoint(mJointName.c_str())))
174                return FALSE;
175        mJointState->setUsage(LLJointState::ROT);
176
177        mParamDriver = (LLViewerVisualParam*)mCharacter->getVisualParam(mParamDriverName.c_str());
178        if (mParamDriver == NULL)
179        {
180                llinfos << "Failure reading in  [ " << mParamDriverName << " ]" << llendl;
181                return FALSE;
182        }
183
184        return TRUE;
185}
186
187LLPhysicsMotionController::LLPhysicsMotionController(const LLUUID &id) : 
188        LLMotion(id),
189        mCharacter(NULL)
190{
191        mName = "breast_motion";
192}
193
194LLPhysicsMotionController::~LLPhysicsMotionController()
195{
196        for (motion_vec_t::iterator iter = mMotions.begin();
197             iter != mMotions.end();
198             ++iter)
199        {
200                delete (*iter);
201        }
202}
203
204BOOL LLPhysicsMotionController::onActivate() 
205{ 
206        return TRUE; 
207}
208
209void LLPhysicsMotionController::onDeactivate() 
210{
211}
212
213LLMotion::LLMotionInitStatus LLPhysicsMotionController::onInitialize(LLCharacter *character)
214{
215        mCharacter = character;
216
217        mMotions.clear();
218
219        // Breast Cleavage
220        {
221                controller_map_t controller;
222                controller["Mass"] = "Breast_Physics_Mass";
223                controller["Gravity"] = "Breast_Physics_Gravity";
224                controller["Drag"] = "Breast_Physics_Drag";
225                controller["Damping"] = "Breast_Physics_InOut_Damping";
226                controller["MaxEffect"] = "Breast_Physics_InOut_Max_Effect";
227                controller["Spring"] = "Breast_Physics_InOut_Spring";
228                controller["Gain"] = "Breast_Physics_InOut_Gain";
229                LLPhysicsMotion *motion = new LLPhysicsMotion("Breast_Physics_InOut_Controller",
230                                                                                                          "mChest",
231                                                                                                          character,
232                                                                                                          LLVector3(-1,0,0),
233                                                                                                          controller);
234                if (!motion->initialize())
235                {
236                        llassert_always(FALSE);
237                        return STATUS_FAILURE;
238                }
239                addMotion(motion);
240        }
241
242        // Breast Bounce
243        {
244                controller_map_t controller;
245                controller["Mass"] = "Breast_Physics_Mass";
246                controller["Gravity"] = "Breast_Physics_Gravity";
247                controller["Drag"] = "Breast_Physics_Drag";
248                controller["Damping"] = "Breast_Physics_UpDown_Damping";
249                controller["MaxEffect"] = "Breast_Physics_UpDown_Max_Effect";
250                controller["Spring"] = "Breast_Physics_UpDown_Spring";
251                controller["Gain"] = "Breast_Physics_UpDown_Gain";
252                LLPhysicsMotion *motion = new LLPhysicsMotion("Breast_Physics_UpDown_Controller",
253                                                                                                          "mChest",
254                                                                                                          character,
255                                                                                                          LLVector3(0,0,1),
256                                                                                                          controller);
257                if (!motion->initialize())
258                {
259                        llassert_always(FALSE);
260                        return STATUS_FAILURE;
261                }
262                addMotion(motion);
263        }
264
265        // Breast Sway
266        {
267                controller_map_t controller;
268                controller["Mass"] = "Breast_Physics_Mass";
269                controller["Gravity"] = "Breast_Physics_Gravity";
270                controller["Drag"] = "Breast_Physics_Drag";
271                controller["Damping"] = "Breast_Physics_LeftRight_Damping";
272                controller["MaxEffect"] = "Breast_Physics_LeftRight_Max_Effect";
273                controller["Spring"] = "Breast_Physics_LeftRight_Spring";
274                controller["Gain"] = "Breast_Physics_LeftRight_Gain";
275                LLPhysicsMotion *motion = new LLPhysicsMotion("Breast_Physics_LeftRight_Controller",
276                                                                                                          "mChest",
277                                                                                                          character,
278                                                                                                          LLVector3(0,-1,0),
279                                                                                                          controller);
280                if (!motion->initialize())
281                {
282                        llassert_always(FALSE);
283                        return STATUS_FAILURE;
284                }
285                addMotion(motion);
286        }
287        // Butt Bounce
288        {
289                controller_map_t controller;
290                controller["Mass"] = "Butt_Physics_Mass";
291                controller["Gravity"] = "Butt_Physics_Gravity";
292                controller["Drag"] = "Butt_Physics_Drag";
293                controller["Damping"] = "Butt_Physics_UpDown_Damping";
294                controller["MaxEffect"] = "Butt_Physics_UpDown_Max_Effect";
295                controller["Spring"] = "Butt_Physics_UpDown_Spring";
296                controller["Gain"] = "Butt_Physics_UpDown_Gain";
297                LLPhysicsMotion *motion = new LLPhysicsMotion("Butt_Physics_UpDown_Controller",
298                                                                                                          "mPelvis",
299                                                                                                          character,
300                                                                                                          LLVector3(0,0,-1),
301                                                                                                          controller);
302                if (!motion->initialize())
303                {
304                        llassert_always(FALSE);
305                        return STATUS_FAILURE;
306                }
307                addMotion(motion);
308        }
309
310        // Butt LeftRight
311        {
312                controller_map_t controller;
313                controller["Mass"] = "Butt_Physics_Mass";
314                controller["Gravity"] = "Butt_Physics_Gravity";
315                controller["Drag"] = "Butt_Physics_Drag";
316                controller["Damping"] = "Butt_Physics_LeftRight_Damping";
317                controller["MaxEffect"] = "Butt_Physics_LeftRight_Max_Effect";
318                controller["Spring"] = "Butt_Physics_LeftRight_Spring";
319                controller["Gain"] = "Butt_Physics_LeftRight_Gain";
320                LLPhysicsMotion *motion = new LLPhysicsMotion("Butt_Physics_LeftRight_Controller",
321                                                                                                          "mPelvis",
322                                                                                                          character,
323                                                                                                          LLVector3(0,-1,0),
324                                                                                                          controller);
325                if (!motion->initialize())
326                {
327                        llassert_always(FALSE);
328                        return STATUS_FAILURE;
329                }
330                addMotion(motion);
331        }
332
333        // Belly Bounce
334        {
335                controller_map_t controller;
336                controller["Mass"] = "Belly_Physics_Mass";
337                controller["Gravity"] = "Belly_Physics_Gravity";
338                controller["Drag"] = "Belly_Physics_Drag";
339                controller["Damping"] = "Belly_Physics_UpDown_Damping";
340                controller["MaxEffect"] = "Belly_Physics_UpDown_Max_Effect";
341                controller["Spring"] = "Belly_Physics_UpDown_Spring";
342                controller["Gain"] = "Belly_Physics_UpDown_Gain";
343                LLPhysicsMotion *motion = new LLPhysicsMotion("Belly_Physics_UpDown_Controller",
344                                                                                                          "mPelvis",
345                                                                                                          character,
346                                                                                                          LLVector3(0,0,-1),
347                                                                                                          controller);
348                if (!motion->initialize())
349                {
350                        llassert_always(FALSE);
351                        return STATUS_FAILURE;
352                }
353                addMotion(motion);
354        }
355        
356        return STATUS_SUCCESS;
357}
358
359void LLPhysicsMotionController::addMotion(LLPhysicsMotion *motion)
360{
361        addJointState(motion->getJointState());
362        mMotions.push_back(motion);
363}
364
365F32 LLPhysicsMotionController::getMinPixelArea() 
366{
367        return MIN_REQUIRED_PIXEL_AREA_AVATAR_PHYSICS_MOTION;
368}
369
370// Local space means "parameter space".
371F32 LLPhysicsMotion::toLocal(const LLVector3 &world)
372{
373        LLJoint *joint = mJointState->getJoint();
374        const LLQuaternion rotation_world = joint->getWorldRotation();
375        
376        LLVector3 dir_world = mMotionDirectionVec * rotation_world;
377        dir_world.normalize();
378        return world * dir_world;
379}
380
381F32 LLPhysicsMotion::calculateVelocity_local()
382{
383	const F32 world_to_model_scale = 100.0f;
384        LLJoint *joint = mJointState->getJoint();
385        const LLVector3 position_world = joint->getWorldPosition();
386        const LLQuaternion rotation_world = joint->getWorldRotation();
387        const LLVector3 last_position_world = mPosition_world;
388	const LLVector3 positionchange_world = (position_world-last_position_world) * world_to_model_scale;
389        const LLVector3 velocity_world = positionchange_world;
390        const F32 velocity_local = toLocal(velocity_world);
391        return velocity_local;
392}
393
394F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local)
395{
396//        const F32 smoothing = getParamValue("Smoothing");
397        static const F32 smoothing = 3.0f; // Removed smoothing param since it's probably not necessary
398        const F32 acceleration_local = velocity_local - mVelocityJoint_local;
399        
400        const F32 smoothed_acceleration_local = 
401                acceleration_local * 1.0/smoothing + 
402                mAccelerationJoint_local * (smoothing-1.0)/smoothing;
403        
404        return smoothed_acceleration_local;
405}
406
407BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask)
408{
409        // Skip if disabled globally.
410        if (!gSavedSettings.getBOOL("AvatarPhysics"))
411        {
412                return TRUE;
413        }
414        
415        BOOL update_visuals = FALSE;
416        for (motion_vec_t::iterator iter = mMotions.begin();
417             iter != mMotions.end();
418             ++iter)
419        {
420                LLPhysicsMotion *motion = (*iter);
421                update_visuals |= motion->onUpdate(time);
422        }
423                
424        if (update_visuals)
425                mCharacter->updateVisualParams();
426        
427        return TRUE;
428}
429
430
431// Return TRUE if character has to update visual params.
432BOOL LLPhysicsMotion::onUpdate(F32 time)
433{
434        // static FILE *mFileWrite = fopen("c:\\temp\\avatar_data.txt","w");
435        
436        if (!mParamDriver)
437                return FALSE;
438
439        if (!mLastTime)
440        {
441                mLastTime = time;
442                return FALSE;
443        }
444
445        ////////////////////////////////////////////////////////////////////////////////
446        // Get all parameters and settings
447        //
448
449        const F32 time_delta = time - mLastTime;
450
451	// Don't update too frequently, to avoid precision errors from small time slices.
452	if (time_delta <= .01)
453	{
454		return FALSE;
455	}
456	
457	// If less than 1FPS, we don't want to be spending time updating physics at all.
458        if (time_delta > 1.0)
459        {
460                mLastTime = time;
461                return FALSE;
462        }
463
464        // Higher LOD is better.  This controls the granularity
465        // and frequency of updates for the motions.
466        const F32 lod_factor = LLVOAvatar::sPhysicsLODFactor;
467        if (lod_factor == 0)
468        {
469                return TRUE;
470        }
471
472        LLJoint *joint = mJointState->getJoint();
473
474        const F32 behavior_mass = getParamValue("Mass");
475        const F32 behavior_gravity = getParamValue("Gravity");
476        const F32 behavior_spring = getParamValue("Spring");
477        const F32 behavior_gain = getParamValue("Gain");
478        const F32 behavior_damping = getParamValue("Damping");
479        const F32 behavior_drag = getParamValue("Drag");
480        const BOOL physics_test = FALSE; // Enable this to simulate bouncing on all parts.
481        
482        F32 behavior_maxeffect = getParamValue("MaxEffect");
483        if (physics_test)
484                behavior_maxeffect = 1.0f;
485
486	// Normalize the param position to be from [0,1].
487	// We have to use normalized values because there may be more than one driven param,
488	// and each of these driven params may have its own range.
489	// This means we'll do all our calculations in normalized [0,1] local coordinates.
490	const F32 position_user_local = (mParamDriver->getWeight() - mParamDriver->getMinWeight()) / (mParamDriver->getMaxWeight() - mParamDriver->getMinWeight());
491       	
492	//
493	// End parameters and settings
494	////////////////////////////////////////////////////////////////////////////////
495	
496	
497	////////////////////////////////////////////////////////////////////////////////
498	// Calculate velocity and acceleration in parameter space.
499	//
500        
501	//const F32 velocity_joint_local = calculateVelocity_local(time_iteration_step);
502	const F32 velocity_joint_local = calculateVelocity_local();
503	const F32 acceleration_joint_local = calculateAcceleration_local(velocity_joint_local);
504	
505	//
506	// End velocity and acceleration
507	////////////////////////////////////////////////////////////////////////////////
508	
509	BOOL update_visuals = FALSE;
510	
511	// Break up the physics into a bunch of iterations so that differing framerates will show
512	// roughly the same behavior.
513	for (F32 time_iteration = 0; time_iteration <= time_delta; time_iteration += TIME_ITERATION_STEP)
514	{
515		F32 time_iteration_step = TIME_ITERATION_STEP;
516		if (time_iteration + TIME_ITERATION_STEP > time_delta)
517		{
518			time_iteration_step = time_delta-time_iteration;
519		}
520		
521		// mPositon_local should be in normalized 0,1 range already.  Just making sure...
522		const F32 position_current_local = llclamp(mPosition_local,
523							   0.0f,
524							   1.0f);
525		// If the effect is turned off then don't process unless we need one more update
526		// to set the position to the default (i.e. user) position.
527		if ((behavior_maxeffect == 0) && (position_current_local == position_user_local))
528		{
529			return update_visuals;
530		}
531
532		////////////////////////////////////////////////////////////////////////////////
533		// Calculate the total force 
534		//
535
536		// Spring force is a restoring force towards the original user-set breast position.
537		// F = kx
538		const F32 spring_length = position_current_local - position_user_local;
539		const F32 force_spring = -spring_length * behavior_spring;
540
541		// Acceleration is the force that comes from the change in velocity of the torso.
542		// F = ma
543		const F32 force_accel = behavior_gain * (acceleration_joint_local * behavior_mass);
544
545		// Gravity always points downward in world space.
546		// F = mg
547		const LLVector3 gravity_world(0,0,1);
548		const F32 force_gravity = (toLocal(gravity_world) * behavior_gravity * behavior_mass);
549                
550		// Damping is a restoring force that opposes the current velocity.
551		// F = -kv
552		const F32 force_damping = -behavior_damping * mVelocity_local;
553                
554		// Drag is a force imparted by velocity (intuitively it is similar to wind resistance)
555		// F = .5kv^2
556		const F32 force_drag = .5*behavior_drag*velocity_joint_local*velocity_joint_local*llsgn(velocity_joint_local);
557
558		const F32 force_net = (force_accel + 
559				       force_gravity +
560				       force_spring + 
561				       force_damping + 
562				       force_drag);
563
564		//
565		// End total force
566		////////////////////////////////////////////////////////////////////////////////
567
568        
569		////////////////////////////////////////////////////////////////////////////////
570		// Calculate new params
571		//
572
573		// Calculate the new acceleration based on the net force.
574		// a = F/m
575		const F32 acceleration_new_local = force_net / behavior_mass;
576		static const F32 max_velocity = 100.0f; // magic number, used to be customizable.
577		F32 velocity_new_local = mVelocity_local + acceleration_new_local*time_iteration_step;
578		velocity_new_local = llclamp(velocity_new_local, 
579					     -max_velocity, max_velocity);
580        
581		// Temporary debugging setting to cause all avatars to move, for profiling purposes.
582		if (physics_test)
583		{
584			velocity_new_local = sin(time*4.0);
585		}
586		// Calculate the new parameters, or remain unchanged if max speed is 0.
587		F32 position_new_local = position_current_local + velocity_new_local*time_iteration_step;
588		if (behavior_maxeffect == 0)
589			position_new_local = position_user_local;
590
591		// Zero out the velocity if the param is being pushed beyond its limits.
592		if ((position_new_local < 0 && velocity_new_local < 0) || 
593		    (position_new_local > 1 && velocity_new_local > 0))
594		{
595			velocity_new_local = 0;
596		}
597	
598		// Check for NaN values.  A NaN value is detected if the variables doesn't equal itself.  
599		// If NaN, then reset everything.
600		if ((mPosition_local != mPosition_local) ||
601		    (mVelocity_local != mVelocity_local) ||
602		    (position_new_local != position_new_local))
603		{
604			position_new_local = 0;
605			mVelocity_local = 0;
606			mVelocityJoint_local = 0;
607			mAccelerationJoint_local = 0;
608			mPosition_local = 0;
609			mPosition_world = LLVector3(0,0,0);
610		}
611
612		const F32 position_new_local_clamped = llclamp(position_new_local,
613							       0.0f,
614							       1.0f);
615
616		LLDriverParam *driver_param = dynamic_cast<LLDriverParam *>(mParamDriver);
617		llassert_always(driver_param);
618		if (driver_param)
619		{
620			// If this is one of our "hidden" driver params, then make sure it's
621			// the default value.
622			if ((driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE) &&
623			    (driver_param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE_NO_TRANSMIT))
624			{
625				mCharacter->setVisualParamWeight(driver_param,
626								 0,
627								 FALSE);
628			}
629			for (LLDriverParam::entry_list_t::iterator iter = driver_param->mDriven.begin();
630			     iter != driver_param->mDriven.end();
631			     ++iter)
632			{
633				LLDrivenEntry &entry = (*iter);
634				LLViewerVisualParam *driven_param = entry.mParam;
635				setParamValue(driven_param,position_new_local_clamped, behavior_maxeffect);
636			}
637		}
638        
639		//
640		// End calculate new params
641		////////////////////////////////////////////////////////////////////////////////
642
643		////////////////////////////////////////////////////////////////////////////////
644		// Conditionally update the visual params
645		//
646        
647		// Updating the visual params (i.e. what the user sees) is fairly expensive.
648		// So only update if the params have changed enough, and also take into account
649		// the graphics LOD settings.
650        
651		// For non-self, if the avatar is small enough visually, then don't update.
652		const F32 area_for_max_settings = 0.0;
653		const F32 area_for_min_settings = 1400.0;
654		const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor);
655	        const F32 pixel_area = sqrtf(mCharacter->getPixelArea());
656        
657		const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(mCharacter) != NULL);
658		if ((pixel_area > area_for_this_setting) || is_self)
659		{
660			const F32 position_diff_local = llabs(mPositionLastUpdate_local-position_new_local_clamped);
661			const F32 min_delta = (1.0001f-lod_factor)*0.4f;
662			if (llabs(position_diff_local) > min_delta)
663			{
664				update_visuals = TRUE;
665				mPositionLastUpdate_local = position_new_local;
666			}
667		}
668
669		//
670		// End update visual params
671		////////////////////////////////////////////////////////////////////////////////
672
673		mVelocity_local = velocity_new_local;
674		mAccelerationJoint_local = acceleration_joint_local;
675		mPosition_local = position_new_local;
676	}
677	mLastTime = time;
678	mPosition_world = joint->getWorldPosition();
679	mVelocityJoint_local = velocity_joint_local;
680
681
682        /*
683          // Write out debugging info into a spreadsheet.
684          if (mFileWrite != NULL && is_self)
685          {
686          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",
687          position_new_local,
688          velocity_new_local,
689          acceleration_new_local,
690
691          time_delta,
692
693          mPosition_world[0],
694          mPosition_world[1],
695          mPosition_world[2],
696
697          force_net,
698          force_spring,
699          force_accel,
700          force_damping,
701          force_drag,
702
703          spring_length,
704          velocity_joint_local,
705          acceleration_joint_local
706          );
707          }
708        */
709
710        return update_visuals;
711}
712
713// Range of new_value_local is assumed to be [0 , 1] normalized.
714void LLPhysicsMotion::setParamValue(LLViewerVisualParam *param,
715                                    F32 new_value_normalized,
716				    F32 behavior_maxeffect)
717{
718        const F32 value_min_local = param->getMinWeight();
719        const F32 value_max_local = param->getMaxWeight();
720        const F32 min_val = 0.5f-behavior_maxeffect/2.0;
721        const F32 max_val = 0.5f+behavior_maxeffect/2.0;
722
723	// Scale from [0,1] to [min_val,max_val]
724	const F32 new_value_rescaled = min_val + (max_val-min_val) * new_value_normalized;
725	
726	// Scale from [0,1] to [value_min_local,value_max_local]
727        const F32 new_value_local = value_min_local + (value_max_local-value_min_local) * new_value_rescaled;
728
729        mCharacter->setVisualParamWeight(param,
730                                         new_value_local,
731                                         FALSE);
732}