summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/character/avatar_lad.xml333
-rw-r--r--indra/newview/lldriverparam.h2
-rw-r--r--indra/newview/llphysicsmotion.cpp661
-rw-r--r--indra/newview/llphysicsmotion.h124
-rw-r--r--indra/newview/llpolymesh.cpp56
-rw-r--r--indra/newview/llpolymorph.cpp31
-rw-r--r--indra/newview/llpolymorph.h1
-rw-r--r--indra/newview/llvoavatar.cpp10
-rw-r--r--indra/newview/llvoavatar.h2
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml18
11 files changed, 1193 insertions, 49 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 5cda107bac..e42f3968fa 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -96,7 +96,6 @@ set(viewer_SOURCE_FILES
llbottomtray.cpp
llbox.cpp
llbreadcrumbview.cpp
- llbreastmotion.cpp
llbrowsernotification.cpp
llbuycurrencyhtml.cpp
llcallbacklist.cpp
@@ -380,6 +379,7 @@ set(viewer_SOURCE_FILES
llparcelselection.cpp
llparticipantlist.cpp
llpatchvertexarray.cpp
+ llphysicsmotion.cpp
llplacesinventorybridge.cpp
llplacesinventorypanel.cpp
llpopupview.cpp
@@ -637,7 +637,6 @@ set(viewer_HEADER_FILES
llbottomtray.h
llbox.h
llbreadcrumbview.h
- llbreastmotion.h
llbuycurrencyhtml.h
llcallbacklist.h
llcallfloater.h
@@ -916,6 +915,7 @@ set(viewer_HEADER_FILES
llparcelselection.h
llparticipantlist.h
llpatchvertexarray.h
+ llphysicsmotion.h
llplacesinventorybridge.h
llplacesinventorypanel.h
llpolymesh.h
diff --git a/indra/newview/character/avatar_lad.xml b/indra/newview/character/avatar_lad.xml
index 453ed1baf7..160b8f3408 100644
--- a/indra/newview/character/avatar_lad.xml
+++ b/indra/newview/character/avatar_lad.xml
@@ -3795,6 +3795,18 @@
</param>
<param
+ id="1092"
+ group="1"
+ name="Belly_Torso_Physics_UpDown_Driven"
+ wearable="shape"
+ edit_group="driven"
+ value_default="0"
+ value_min="-1"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
id="626"
sex="female"
group="1"
@@ -4048,16 +4060,11 @@
group="0"
sex="female"
name="Breast_Gravity"
- label="Breast Buoyancy"
wearable="shape"
edit_group="driven"
- label_min="Less Gravity"
- label_max="More Gravity"
value_default="0"
value_min="-1.5"
- value_max="2"
- camera_elevation=".3"
- camera_distance=".8">
+ value_max="2">
<param_morph />
</param>
@@ -4066,16 +4073,11 @@
group="0"
sex="female"
name="Breast_Female_Cleavage"
- label="Breast Cleavage"
wearable="shape"
edit_group="driven"
- label_min="Separate"
- label_max="Join"
value_default="0"
value_min="-.3"
- value_max="1.3"
- camera_elevation=".3"
- camera_distance=".8">
+ value_max="1.3">
<param_morph />
</param>
@@ -4389,6 +4391,18 @@
</param>
<param
+ id="1093"
+ group="1"
+ name="Belly_Legs_Physics_UpDown_Driven"
+ wearable="shape"
+ edit_group="driven"
+ value_min="-1"
+ value_max="1">
+ <param_morph />
+ </param>
+
+
+ <param
id="151"
group="1"
name="Big_Butt_Legs"
@@ -4427,6 +4441,38 @@
</param>
<param
+ id="1089"
+ group="0"
+ name="Butt_Physics_UpDown_Driven"
+ wearable="shape"
+ edit_group="driven"
+ label_min="Separate"
+ label_max="Join"
+ value_default="0"
+ value_min="-2"
+ value_max="2"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_morph />
+ </param>
+
+ <param
+ id="1090"
+ group="0"
+ name="Butt_Physics_LeftRight_Driven"
+ wearable="shape"
+ edit_group="driven"
+ label_min="Separate"
+ label_max="Join"
+ value_default="0"
+ value_min="-2"
+ value_max="2"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_morph />
+ </param>
+
+ <param
id="152"
group="1"
name="Muscular_Legs"
@@ -5140,6 +5186,18 @@
</param>
<param
+ id="1094"
+ group="1"
+ name="Belly_Skirt_Physics_UpDown_Driven"
+ wearable="skirt"
+ edit_group="driven"
+ cross_wearable="true"
+ value_min="-1"
+ value_max="1">
+ <param_morph />
+ </param>
+
+ <param
id="850"
group="1"
wearable="skirt"
@@ -9083,9 +9141,9 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default="2"
- value_min="1"
- value_max="5"
+ value_default=".1"
+ value_min=".1"
+ value_max="1"
camera_elevation=".3"
camera_distance=".8">
<param_driver />
@@ -9137,9 +9195,9 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default="3"
+ value_default=".1"
value_min="0"
- value_max="10"
+ value_max="1"
camera_elevation=".3"
camera_distance=".8">
<param_driver />
@@ -9173,9 +9231,9 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default=".5"
+ value_default=".05"
value_min="0"
- value_max="1"
+ value_max=".1"
camera_elevation=".3"
camera_distance=".8">
<param_driver />
@@ -9191,9 +9249,9 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default=".1"
+ value_default=".15"
value_min="0"
- value_max="1"
+ value_max=".5"
camera_elevation=".3"
camera_distance=".8">
<param_driver />
@@ -9228,9 +9286,9 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default="1.5"
+ value_default=".1"
value_min="0"
- value_max="10"
+ value_max="1"
camera_elevation=".3"
camera_distance=".8">
<param_driver />
@@ -9246,7 +9304,7 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default="50"
+ value_default="10"
value_min="1"
value_max="100"
camera_elevation=".3"
@@ -9264,9 +9322,9 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default=".1"
+ value_default=".05"
value_min="0"
- value_max="1"
+ value_max=".1"
camera_elevation=".3"
camera_distance=".8">
<param_driver />
@@ -9282,9 +9340,9 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default=".1"
+ value_default=".15"
value_min="0"
- value_max="1"
+ value_max=".5"
camera_elevation=".3"
camera_distance=".8">
<param_driver />
@@ -9300,7 +9358,7 @@ render_pass="bump">
edit_group="physics"
label_min="Less"
label_max="More"
- value_default="1"
+ value_default="0"
value_min="0"
value_max="10"
camera_elevation=".3"
@@ -9308,18 +9366,60 @@ render_pass="bump">
<param_driver />
</param>
+ <param
+ id="1104"
+ group="0"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="14"
+ name="Butt_Physics_UpDown_Controller"
+ label="Butt Physics UpDown Controller"
+ label_min="Down"
+ label_max="Up"
+ value_min="-1"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver>
+ <driven
+ id="1089" />
+ </param_driver>
+ </param>
+
+ <param
+ id="1105"
+ group="0"
+ wearable="shape"
+ edit_group="shape_legs"
+ edit_group_order="15"
+ name="Butt_Physics_LeftRight_Controller"
+ label="Butt Physics LeftRight Controller"
+ label_min="Down"
+ label_max="Up"
+ value_min="-1"
+ value_max="1"
+ value_default="0"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver>
+ <driven
+ id="1090" />
+ </param_driver>
+ </param>
+
<param
id="507"
group="0"
sex="female"
- name="Breast_Gravity_Driver"
- label="Breast Buoyancy"
+ name="Breast_Physics_UpDown_Controller"
+ label="Breast Physics UpDown Controller"
wearable="shape"
edit_group="shape_torso"
edit_group_order="7"
label_min="Less"
label_max="More"
- value_default="10"
+ value_default="0"
value_min="-1.5"
value_max="2"
camera_elevation=".3"
@@ -9334,14 +9434,14 @@ render_pass="bump">
id="684"
group="0"
sex="female"
- name="Breast_Female_Cleavage_Driver"
- label="Breast Cleavage"
+ name="Breast_Physics_Side_Controller"
+ label="Breast Physics Side Controller"
wearable="shape"
edit_group="shape_torso"
edit_group_order="8"
label_min="Less"
label_max="More"
- value_default="10"
+ value_default="0"
value_min="-.3"
value_max="1.3"
camera_elevation=".3"
@@ -10076,6 +10176,169 @@ render_pass="bump">
</param>
<param
+ id="1091"
+ group="0"
+ wearable="shape"
+ edit_group="shape_torso"
+ edit_group_order="14"
+ name="Belly_Physics_UpDown_Controller"
+ label="Belly Physics UpDown Controller"
+ label_min="Down"
+ label_max="Up"
+ value_min="-1"
+ value_max="1"
+ value_default="0"
+ camera_distance="1.4"
+ camera_angle="30"
+ camera_elevation=".2">
+ <param_driver>
+ <driven
+ id="1092" />
+ <driven
+ id="1093" />
+ <driven
+ id="1094" />
+ </param_driver>
+ </param>
+
+ <param
+ id="1095"
+ group="0"
+ name="Belly_Physics_UpDown_Spring"
+ label="Belly Physics UpDown Spring"
+ wearable="physics"
+ edit_group="physics"
+ label_min="Less"
+ label_max="More"
+ value_default=".1"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+
+ <param
+ id="1096"
+ group="0"
+ name="Belly_Physics_UpDown_Gain"
+ label="Belly Physics UpDown Gain"
+ wearable="physics"
+ edit_group="physics"
+ label_min="Less"
+ label_max="More"
+ value_default="10"
+ value_min="1"
+ value_max="100"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+
+ <param
+ id="1097"
+ group="0"
+ name="Belly_Physics_UpDown_Damping"
+ label="Belly Physics UpDown Damping"
+ wearable="physics"
+ edit_group="physics"
+ label_min="Less"
+ label_max="More"
+ value_default=".05"
+ value_min="0"
+ value_max=".1"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+
+ <param
+ id="1098"
+ group="0"
+ name="Belly_Physics_UpDown_Max_Velocity"
+ label="Belly Physics UpDown Max Speed"
+ wearable="physics"
+ edit_group="physics"
+ label_min="Less"
+ label_max="More"
+ value_default="0"
+ value_min="0"
+ value_max="10"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+
+ <param
+ id="1100"
+ group="0"
+ name="Butt_Physics_UpDown_Spring"
+ label="Butt Physics UpDown Spring"
+ wearable="physics"
+ edit_group="physics"
+ label_min="Less"
+ label_max="More"
+ value_default=".1"
+ value_min="0"
+ value_max="1"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+
+ <param
+ id="1101"
+ group="0"
+ name="Butt_Physics_UpDown_Gain"
+ label="Butt Physics UpDown Gain"
+ wearable="physics"
+ edit_group="physics"
+ label_min="Less"
+ label_max="More"
+ value_default="10"
+ value_min="1"
+ value_max="100"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+
+ <param
+ id="1102"
+ group="0"
+ name="Butt_Physics_UpDown_Damping"
+ label="Butt Physics UpDown Damping"
+ wearable="physics"
+ edit_group="physics"
+ label_min="Less"
+ label_max="More"
+ value_default=".05"
+ value_min="0"
+ value_max=".1"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+
+ <param
+ id="1103"
+ group="0"
+ name="Butt_Physics_UpDown_Max_Velocity"
+ label="Butt Physics UpDown Max Speed"
+ wearable="physics"
+ edit_group="physics"
+ label_min="Less"
+ label_max="More"
+ value_default="0"
+ value_min="0"
+ value_max="10"
+ camera_elevation=".3"
+ camera_distance=".8">
+ <param_driver />
+ </param>
+
+
+ <param
id="637"
group="0"
wearable="shape"
diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h
index a0e45cf5e5..fb1b44458c 100644
--- a/indra/newview/lldriverparam.h
+++ b/indra/newview/lldriverparam.h
@@ -30,6 +30,7 @@
#include "llviewervisualparam.h"
#include "llwearabletype.h"
+class LLPhysicsMotion;
class LLVOAvatar;
class LLWearable;
@@ -76,6 +77,7 @@ protected:
class LLDriverParam : public LLViewerVisualParam
{
+ friend class LLPhysicsMotion; // physics motion needs to access driven params directly.
public:
LLDriverParam(LLVOAvatar *avatarp);
LLDriverParam(LLWearable *wearablep);
diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp
new file mode 100644
index 0000000000..48e632280e
--- /dev/null
+++ b/indra/newview/llphysicsmotion.cpp
@@ -0,0 +1,661 @@
+/**
+ * @file llphysicsmotion.cpp
+ * @brief Implementation of LLPhysicsMotion class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+//-----------------------------------------------------------------------------
+// Header Files
+//-----------------------------------------------------------------------------
+#include "llviewerprecompiledheaders.h"
+#include "linden_common.h"
+
+#include "m3math.h"
+#include "v3dmath.h"
+
+#include "llphysicsmotion.h"
+#include "llcharacter.h"
+#include "llviewercontrol.h"
+#include "llviewervisualparam.h"
+#include "llvoavatarself.h"
+
+typedef std::map<std::string, std::string> controller_map_t;
+typedef std::map<std::string, F32> default_controller_map_t;
+
+#define MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION 0.f;
+
+inline F64 llsgn(const F64 a)
+{
+ if (a >= 0)
+ return 1;
+ return -1;
+}
+
+/*
+ At a high level, this works by setting temporary parameters that are not stored
+ in the avatar's list of params, and are not conveyed to other users. We accomplish
+ this by creating some new temporary driven params inside avatar_lad that are then driven
+ by the actual params that the user sees and sets. For example, in the old system,
+ the user sets a param called breast bouyancy, which controls the Z value of the breasts.
+ In our new system, the user still sets the breast bouyancy, but that param is redefined
+ as a driver param so that affects a new temporary driven param that the bounce is applied
+ to.
+*/
+
+class LLPhysicsMotion
+{
+public:
+ /*
+ param_user_name: The param (if any) that the user sees and controls. This is what
+ the particular property would look like without physics. For example, it may be
+ the breast gravity. This param's value should will not be altered, and is only
+ used as a reference point for the rest position of the body party. This is usually
+ a driver param and the param(s) that physics is altering are the driven params.
+
+ param_driven_name: The param whose value is actually set by the physics. If you
+ leave this blank (which should suffice normally), the physics will assume that
+ param_user_name is a driver param and will set the params that the driver is
+ in charge of (i.e. the "driven" params).
+
+ joint_name: The joint that the body part is attached to. The joint is
+ used to determine the orientation (rotation) of the body part.
+
+ character: The avatar that this physics affects.
+
+ motion_direction_vec: The direction (in world coordinates) that determines the
+ motion. For example, (0,0,1) is up-down, and means that up-down motion is what
+ determines how this joint moves.
+
+ controllers: The various settings (e.g. spring force, mass) that determine how
+ the body part behaves.
+ */
+ LLPhysicsMotion(const std::string &param_user_name,
+ const std::string &param_driven_name,
+ const std::string &joint_name,
+ LLCharacter *character,
+ const LLVector3 &motion_direction_vec,
+ const controller_map_t &controllers) :
+ mParamUserName(param_user_name),
+ mParamDrivenName(param_driven_name),
+ mJointName(joint_name),
+ mMotionDirectionVec(motion_direction_vec),
+ mParamUser(NULL),
+ mParamDriven(NULL),
+
+ mParamControllers(controllers),
+ mCharacter(character),
+ mLastTime(0),
+ mPosition_local(0),
+ mVelocityJoint_local(0),
+ mPositionLastUpdate_local(0)
+ {
+ mJointState = new LLJointState;
+ }
+
+ BOOL initialize();
+
+ ~LLPhysicsMotion() {}
+
+ BOOL onUpdate(F32 time);
+
+ LLPointer<LLJointState> getJointState()
+ {
+ return mJointState;
+ }
+protected:
+ F32 getParamValue(const std::string& controller_key)
+ {
+ const controller_map_t::const_iterator& entry = mParamControllers.find(controller_key);
+ if (entry == mParamControllers.end())
+ {
+ return sDefaultController[controller_key];
+ }
+ const std::string& param_name = (*entry).second.c_str();
+ return mCharacter->getVisualParamWeight(param_name.c_str());
+ }
+ void setParamValue(LLViewerVisualParam *param,
+ const F32 new_value_local);
+
+ F32 toLocal(const LLVector3 &world);
+ F32 calculateVelocity_local(const F32 time_delta);
+ F32 calculateAcceleration_local(F32 velocity_local,
+ const F32 time_delta);
+private:
+ const std::string mParamDrivenName;
+ const std::string mParamUserName;
+ const LLVector3 mMotionDirectionVec;
+ const std::string mJointName;
+
+ F32 mPosition_local;
+ F32 mVelocityJoint_local; // How fast the joint is moving
+ F32 mAccelerationJoint_local; // Acceleration on the joint
+
+ F32 mVelocity_local; // How fast the param is moving
+ F32 mPositionLastUpdate_local;
+ LLVector3 mPosition_world;
+
+ LLViewerVisualParam *mParamUser;
+ LLViewerVisualParam *mParamDriven;
+ const controller_map_t mParamControllers;
+
+ LLPointer<LLJointState> mJointState;
+ LLCharacter *mCharacter;
+
+ F32 mLastTime;
+
+ static default_controller_map_t sDefaultController;
+};
+
+default_controller_map_t initDefaultController()
+{
+ default_controller_map_t controller;
+ controller["Mass"] = 0.2f;
+ controller["Smoothing"] = 2.0f;
+ controller["Gravity"] = 0.0f;
+ controller["Damping"] = .05f;
+ controller["Drag"] = 0.15f;
+ controller["MaxSpeed"] = 0.1f;
+ controller["Spring"] = 0.1f;
+ controller["Gain"] = 10.0f;
+ return controller;
+}
+
+default_controller_map_t LLPhysicsMotion::sDefaultController = initDefaultController();
+
+BOOL LLPhysicsMotion::initialize()
+{
+ if (!mJointState->setJoint(mCharacter->getJoint(mJointName.c_str())))
+ return FALSE;
+ mJointState->setUsage(LLJointState::ROT);
+
+ mParamUser = (LLViewerVisualParam*)mCharacter->getVisualParam(mParamUserName.c_str());
+ if (mParamDrivenName != "")
+ mParamDriven = (LLViewerVisualParam*)mCharacter->getVisualParam(mParamDrivenName.c_str());
+ if (mParamUser == NULL)
+ {
+ llinfos << "Failure reading in [ " << mParamUserName << " ]" << llendl;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+LLPhysicsMotionController::LLPhysicsMotionController(const LLUUID &id) :
+ LLMotion(id),
+ mCharacter(NULL)
+{
+ mName = "breast_motion";
+}
+
+LLPhysicsMotionController::~LLPhysicsMotionController()
+{
+ for (motion_vec_t::iterator iter = mMotions.begin();
+ iter != mMotions.end();
+ ++iter)
+ {
+ delete (*iter);
+ }
+}
+
+BOOL LLPhysicsMotionController::onActivate()
+{
+ return TRUE;
+}
+
+void LLPhysicsMotionController::onDeactivate()
+{
+}
+
+LLMotion::LLMotionInitStatus LLPhysicsMotionController::onInitialize(LLCharacter *character)
+{
+ mCharacter = character;
+
+ mMotions.clear();
+
+ controller_map_t controller_breast_inout;
+ controller_breast_inout["Mass"] = "Breast_Physics_Mass";
+ controller_breast_inout["Smoothing"] = "Breast_Physics_Smoothing";
+ controller_breast_inout["Gravity"] = "Breast_Physics_Gravity";
+ controller_breast_inout["Damping"] = "Breast_Physics_Side_Damping";
+ controller_breast_inout["Drag"] = "Breast_Physics_Side_Drag";
+ controller_breast_inout["MaxSpeed"] = "Breast_Physics_Side_Max_Velocity";
+ controller_breast_inout["Spring"] = "Breast_Physics_Side_Spring";
+ controller_breast_inout["Gain"] = "Breast_Physics_Side_Gain";
+
+ LLPhysicsMotion *motion_breast_inout = new LLPhysicsMotion("Breast_Physics_Side_Controller",
+ "",
+ "mChest",
+ character,
+ LLVector3(-1,0,0),
+ controller_breast_inout);
+ if (!motion_breast_inout->initialize())
+ return STATUS_FAILURE;
+ addMotion(motion_breast_inout);
+
+ controller_map_t controller_breast_updown;
+ controller_breast_updown["Mass"] = "Breast_Physics_Mass";
+ controller_breast_updown["Smoothing"] = "Breast_Physics_Smoothing";
+ controller_breast_updown["Gravity"] = "Breast_Physics_Gravity";
+ controller_breast_updown["Damping"] = "Breast_Physics_UpDown_Damping";
+ controller_breast_updown["Drag"] = "Breast_Physics_UpDown_Drag";
+ controller_breast_updown["MaxSpeed"] = "Breast_Physics_UpDown_Max_Velocity";
+ controller_breast_updown["Spring"] = "Breast_Physics_UpDown_Spring";
+ controller_breast_updown["Gain"] = "Breast_Physics_UpDown_Gain";
+
+ LLPhysicsMotion *motion_breast_updown = new LLPhysicsMotion("Breast_Physics_UpDown_Controller",
+ "",
+ "mChest",
+ character,
+ LLVector3(0,0,1),
+ controller_breast_updown);
+ if (!motion_breast_updown->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion_breast_updown);
+
+ controller_map_t controller_butt_updown;
+ controller_butt_updown["Damping"] = "Butt_Physics_Updown_Damping";
+ controller_butt_updown["MaxSpeed"] = "Butt_Physics_Updown_Max_Velocity";
+ controller_butt_updown["Spring"] = "Butt_Physics_Updown_Spring";
+ controller_butt_updown["Gain"] = "Butt_Physics_Updown_Gain";
+ LLPhysicsMotion *motion_butt_updown = new LLPhysicsMotion("Butt_Physics_UpDown_Controller",
+ "",
+ "mPelvis",
+ character,
+ LLVector3(0,0,1),
+ controller_butt_updown);
+ if (!motion_butt_updown->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion_butt_updown);
+
+ controller_map_t controller_butt_leftright;
+ controller_butt_leftright["Damping"] = "Butt_Physics_Updown_Damping";
+ controller_butt_leftright["MaxSpeed"] = "Butt_Physics_Updown_Max_Velocity";
+ controller_butt_leftright["Spring"] = "Butt_Physics_Updown_Spring";
+ controller_butt_leftright["Gain"] = "Butt_Physics_Updown_Gain";
+ LLPhysicsMotion *motion_butt_leftright = new LLPhysicsMotion("Butt_Physics_LeftRight_Controller",
+ "",
+ "mPelvis",
+ character,
+ LLVector3(0,1,0),
+ controller_butt_leftright);
+ if (!motion_butt_leftright->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion_butt_leftright);
+
+ controller_map_t controller_belly_updown;
+ controller_belly_updown["Damping"] = "Belly_Physics_Updown_Damping";
+ controller_belly_updown["MaxSpeed"] = "Belly_Physics_Updown_Max_Velocity";
+ controller_belly_updown["Spring"] = "Belly_Physics_Updown_Spring";
+ controller_belly_updown["Gain"] = "Belly_Physics_Updown_Gain";
+ LLPhysicsMotion *motion_belly_updown = new LLPhysicsMotion("Belly_Physics_UpDown_Controller",
+ "",
+ "mChest",
+ character,
+ LLVector3(0,0,-1),
+ controller_belly_updown);
+ if (!motion_belly_updown->initialize())
+ {
+ llassert_always(FALSE);
+ return STATUS_FAILURE;
+ }
+ addMotion(motion_belly_updown);
+
+ return STATUS_SUCCESS;
+}
+
+void LLPhysicsMotionController::addMotion(LLPhysicsMotion *motion)
+{
+ addJointState(motion->getJointState());
+ mMotions.push_back(motion);
+}
+
+F32 LLPhysicsMotionController::getMinPixelArea()
+{
+ return MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION;
+}
+
+// Local space means "parameter space".
+F32 LLPhysicsMotion::toLocal(const LLVector3 &world)
+{
+ LLJoint *joint = mJointState->getJoint();
+ const LLQuaternion rotation_world = joint->getWorldRotation();
+
+ LLVector3 dir_world = mMotionDirectionVec * rotation_world;
+ dir_world.normalize();
+ return world * dir_world;
+}
+
+F32 LLPhysicsMotion::calculateVelocity_local(const F32 time_delta)
+{
+ LLJoint *joint = mJointState->getJoint();
+ const LLVector3 position_world = joint->getWorldPosition();
+ const LLQuaternion rotation_world = joint->getWorldRotation();
+ const LLVector3 last_position_world = mPosition_world;
+ const LLVector3 velocity_world = (position_world-last_position_world) / time_delta;
+ const F32 velocity_local = toLocal(velocity_world);
+ return velocity_local;
+}
+
+F32 LLPhysicsMotion::calculateAcceleration_local(const F32 velocity_local,
+ const F32 time_delta)
+{
+ const F32 smoothing = getParamValue("Smoothing");
+ const F32 acceleration_local = velocity_local - mVelocityJoint_local;
+
+ const F32 smoothed_acceleration_local =
+ acceleration_local * 1.0/smoothing +
+ mAccelerationJoint_local * (smoothing-1.0)/smoothing;
+
+ return smoothed_acceleration_local;
+}
+
+BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask)
+{
+ // Skip if disabled globally.
+ if (!gSavedSettings.getBOOL("AvatarPhysics"))
+ {
+ return TRUE;
+ }
+
+ BOOL update_visuals = FALSE;
+ for (motion_vec_t::iterator iter = mMotions.begin();
+ iter != mMotions.end();
+ ++iter)
+ {
+ LLPhysicsMotion *motion = (*iter);
+ update_visuals |= motion->onUpdate(time);
+ }
+
+ if (update_visuals)
+ mCharacter->updateVisualParams();
+
+ return TRUE;
+}
+
+
+// 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 (!mParamUser)
+ return FALSE;
+
+ if (!mLastTime)
+ {
+ mLastTime = time;
+ return FALSE;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Get all parameters and settings
+ //
+
+ const F32 time_delta = time - mLastTime;
+ if (time_delta > 3.0 || time_delta <= 0.01)
+ {
+ 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_maxspeed = getParamValue("MaxSpeed");
+ const F32 behavior_drag = getParamValue("Drag");
+
+ F32 position_current_local = mPosition_local; // Normalized [0,1] range
+
+ // 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.
+ F32 position_user_local = mParamUser->getWeight();
+ position_user_local = (position_user_local - mParamUser->getMinWeight()) / (mParamUser->getMaxWeight() - mParamUser->getMinWeight());
+
+ //
+ // End parameters and settings
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Calculate velocity and acceleration in parameter space.
+ //
+
+ const F32 velocity_joint_local = calculateVelocity_local(time_delta);
+ const F32 acceleration_joint_local = calculateAcceleration_local(velocity_joint_local, time_delta);
+
+ //
+ // End velocity and acceleration
+ ////////////////////////////////////////////////////////////////////////////////
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // 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 = behavior_gain * (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;
+ F32 velocity_new_local = mVelocity_local + acceleration_new_local;
+ velocity_new_local = llclamp(velocity_new_local,
+ -behavior_maxspeed, behavior_maxspeed);
+
+ // Temporary debugging setting to cause all avatars to move, for profiling purposes.
+ if (gSavedSettings.getBOOL("AvatarPhysicsTest"))
+ {
+ velocity_new_local = sin(time*4.0)*5.0;
+ }
+ // Calculate the new parameters, or remain unchanged if max speed is 0.
+ const F32 position_new_local = (behavior_maxspeed != 0) ?
+ (position_current_local + velocity_new_local*time_delta) :
+ position_user_local;
+
+ // Zero out the velocity if the param is being pushed beyond its limits.
+ if (position_new_local < 0 || position_new_local > 1)
+ {
+ velocity_new_local = 0;
+ }
+
+ const F32 position_new_local_clamped = llclamp(position_new_local,
+ 0.0f,
+ 1.0f);
+
+ // Set the new param.
+ // If a specific param has been declared, then set that one.
+ // Otherwise, assume that the param is a driver param, and
+ // set the params that it drives.
+ if (mParamDriven)
+ {
+ setParamValue(mParamDriven,position_new_local_clamped);
+ }
+ else
+ {
+ LLDriverParam *driver_param = dynamic_cast<LLDriverParam *>(mParamUser);
+ llassert_always(driver_param);
+ if (driver_param)
+ {
+ 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);
+ }
+ }
+ }
+
+ //
+ // 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.
+
+ BOOL update_visuals = FALSE;
+
+ // 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 = fsqrtf(mCharacter->getPixelArea());
+
+ const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(mCharacter) != NULL);
+ 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.01f-lod_factor)*0.75f; // 75% is just an experimental magic number.
+ if (llabs(position_diff_local) > min_delta)
+ {
+ update_visuals = TRUE;
+ mPositionLastUpdate_local = position_new_local;
+ }
+ }
+
+ //
+ // End update visual params
+ ////////////////////////////////////////////////////////////////////////////////
+
+ mVelocityJoint_local = velocity_joint_local;
+
+ mVelocity_local = velocity_new_local;
+ mAccelerationJoint_local = acceleration_joint_local;
+ mPosition_local = position_new_local;
+
+ mPosition_world = joint->getWorldPosition();
+ mLastTime = time;
+
+ /*
+ // 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;
+}
+
+// Range of new_value_local is assumed to be [0 , 1] normalized.
+void LLPhysicsMotion::setParamValue(LLViewerVisualParam *param,
+ F32 new_value_normalized)
+{
+ const F32 value_min_local = param->getMinWeight();
+ const F32 value_max_local = param->getMaxWeight();
+
+ const F32 new_value_local = value_min_local + (value_max_local-value_min_local) * new_value_normalized;
+
+ mCharacter->setVisualParamWeight(param,
+ new_value_local,
+ FALSE);
+}
diff --git a/indra/newview/llphysicsmotion.h b/indra/newview/llphysicsmotion.h
new file mode 100644
index 0000000000..0c0087d269
--- /dev/null
+++ b/indra/newview/llphysicsmotion.h
@@ -0,0 +1,124 @@
+/**
+ * @file llphysicsmotion.h
+ * @brief Implementation of LLPhysicsMotion class.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPHYSICSMOTIONCONTROLLER_H
+#define LL_LLPHYSICSMOTIONCONTROLLER_H
+
+//-----------------------------------------------------------------------------
+// Header files
+//-----------------------------------------------------------------------------
+#include "llmotion.h"
+#include "llframetimer.h"
+
+#define PHYSICS_MOTION_FADEIN_TIME 1.0f
+#define PHYSICS_MOTION_FADEOUT_TIME 1.0f
+
+class LLPhysicsMotion;
+
+//-----------------------------------------------------------------------------
+// class LLPhysicsMotion
+//-----------------------------------------------------------------------------
+class LLPhysicsMotionController :
+ public LLMotion
+{
+public:
+ // Constructor
+ LLPhysicsMotionController(const LLUUID &id);
+
+ // Destructor
+ virtual ~LLPhysicsMotionController();
+
+public:
+ //-------------------------------------------------------------------------
+ // functions to support MotionController and MotionRegistry
+ //-------------------------------------------------------------------------
+
+ // static constructor
+ // all subclasses must implement such a function and register it
+ static LLMotion *create(const LLUUID &id) { return new LLPhysicsMotionController(id); }
+
+public:
+ //-------------------------------------------------------------------------
+ // animation callbacks to be implemented by subclasses
+ //-------------------------------------------------------------------------
+
+ // motions must specify whether or not they loop
+ virtual BOOL getLoop() { return TRUE; }
+
+ // motions must report their total duration
+ virtual F32 getDuration() { return 0.0; }
+
+ // motions must report their "ease in" duration
+ virtual F32 getEaseInDuration() { return PHYSICS_MOTION_FADEIN_TIME; }
+
+ // motions must report their "ease out" duration.
+ virtual F32 getEaseOutDuration() { return PHYSICS_MOTION_FADEOUT_TIME; }
+
+ // called to determine when a motion should be activated/deactivated based on avatar pixel coverage
+ virtual F32 getMinPixelArea();
+
+ // motions must report their priority
+ virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; }
+
+ virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; }
+
+ // run-time (post constructor) initialization,
+ // called after parameters have been set
+ // must return true to indicate success and be available for activation
+ virtual LLMotionInitStatus onInitialize(LLCharacter *character);
+
+ // called when a motion is activated
+ // must return TRUE to indicate success, or else
+ // it will be deactivated
+ virtual BOOL onActivate();
+
+ // called per time step
+ // must return TRUE while it is active, and
+ // must return FALSE when the motion is completed.
+ virtual BOOL onUpdate(F32 time, U8* joint_mask);
+
+ // called when a motion is deactivated
+ virtual void onDeactivate();
+
+ LLCharacter* getCharacter() { return mCharacter; }
+
+protected:
+ void addMotion(LLPhysicsMotion *motion);
+private:
+ LLCharacter* mCharacter;
+
+ typedef std::vector<LLPhysicsMotion *> motion_vec_t;
+ motion_vec_t mMotions;
+};
+
+#endif // LL_LLPHYSICSMOTION_H
+
diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp
index 2942f4befb..a28357b4a9 100644
--- a/indra/newview/llpolymesh.cpp
+++ b/indra/newview/llpolymesh.cpp
@@ -46,6 +46,10 @@
extern LLControlGroup gSavedSettings; // read only
+LLPolyMorphData *clone_morph_param(const LLPolyMorphData *src_data,
+ const LLVector3 &direction,
+ const std::string &name);
+
//-----------------------------------------------------------------------------
// Global table of loaded LLPolyMeshes
//-----------------------------------------------------------------------------
@@ -602,12 +606,40 @@ BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName )
}
mMorphData.insert(morph_data);
- /*
- if (std::string(morphName) == "Breast_Gravity")
+
+ if (!strcmp(morphName, "Big_Belly_Torso"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0,0.05f),
+ "Belly_Torso_Physics_UpDown_Driven"));
+ }
+
+ if (!strcmp(morphName, "Big_Belly_Legs"))
{
- LLPolyMorphData *morph_data_clone = new LLPolyMorphData(std::string(morphName));
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0,0.05f),
+ "Belly_Legs_Physics_UpDown_Driven"));
+ }
+
+ if (!strcmp(morphName, "skirt_belly"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0,0.05f),
+ "Belly_Skirt_Physics_UpDown_Driven"));
+ }
+
+ if (!strcmp(morphName, "Small_Butt"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0,0.01f),
+ "Butt_Physics_UpDown_Driven"));
+ }
+ if (!strcmp(morphName, "Small_Butt"))
+ {
+ mMorphData.insert(clone_morph_param(morph_data,
+ LLVector3(0,0.01f,0),
+ "Butt_Physics_LeftRight_Driven"));
}
- */
}
S32 numRemaps;
@@ -1164,4 +1196,20 @@ void LLPolySkeletalDistortion::apply( ESex avatar_sex )
mLastWeight = mCurWeight;
}
+
+LLPolyMorphData *clone_morph_param(const LLPolyMorphData *src_data,
+ const LLVector3 &direction,
+ const std::string &name)
+{
+ LLPolyMorphData* cloned_morph_data = new LLPolyMorphData(*src_data);
+ cloned_morph_data->mName = name;
+ for (U32 v=0; v < cloned_morph_data->mNumIndices; v++)
+ {
+ cloned_morph_data->mCoords[v] = direction;
+ cloned_morph_data->mNormals[v] = LLVector3(0,0,0);
+ cloned_morph_data->mBinormals[v] = LLVector3(0,0,0);
+ }
+ return cloned_morph_data;
+}
+
// End
diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp
index ec41ef08f5..5a67fd482a 100644
--- a/indra/newview/llpolymorph.cpp
+++ b/indra/newview/llpolymorph.cpp
@@ -59,6 +59,37 @@ LLPolyMorphData::LLPolyMorphData(const std::string& morph_name)
mMesh = NULL;
}
+LLPolyMorphData::LLPolyMorphData(const LLPolyMorphData &rhs) :
+ mName(rhs.mName),
+ mNumIndices(rhs.mNumIndices),
+ mTotalDistortion(rhs.mTotalDistortion),
+ mAvgDistortion(rhs.mAvgDistortion),
+ mMaxDistortion(rhs.mMaxDistortion),
+ mVertexIndices(NULL),
+ mCoords(NULL),
+ mNormals(NULL),
+ mBinormals(NULL),
+ mTexCoords(NULL)
+{
+ const S32 numVertices = mNumIndices;
+
+ mCoords = new LLVector3[numVertices];
+ mNormals = new LLVector3[numVertices];
+ mBinormals = new LLVector3[numVertices];
+ mTexCoords = new LLVector2[numVertices];
+ mVertexIndices = new U32[numVertices];
+
+ for (S32 v=0; v < numVertices; v++)
+ {
+ mCoords[v] = rhs.mCoords[v];
+ mNormals[v] = rhs.mNormals[v];
+ mBinormals[v] = rhs.mBinormals[v];
+ mTexCoords[v] = rhs.mTexCoords[v];
+ mVertexIndices[v] = rhs.mVertexIndices[v];
+ }
+}
+
+
//-----------------------------------------------------------------------------
// ~LLPolyMorphData()
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h
index bc111882b7..8a024f2e9e 100644
--- a/indra/newview/llpolymorph.h
+++ b/indra/newview/llpolymorph.h
@@ -46,6 +46,7 @@ class LLPolyMorphData
public:
LLPolyMorphData(const std::string& morph_name);
~LLPolyMorphData();
+ LLPolyMorphData(const LLPolyMorphData &rhs);
BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh);
const std::string& getName() { return mName; }
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 3476dc80e8..2c5e728c87 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -48,7 +48,7 @@
#include "llanimationstates.h"
#include "llavatarnamecache.h"
#include "llavatarpropertiesprocessor.h"
-#include "llbreastmotion.h"
+#include "llphysicsmotion.h"
#include "llviewercontrol.h"
#include "llcallingcard.h" // IDEVO for LLAvatarTracker
#include "lldrawpoolavatar.h"
@@ -126,7 +126,7 @@ const LLUUID ANIM_AGENT_HEAD_ROT = LLUUID("e6e8d1dd-e643-fff7-b238-c6b4b056a68d"
const LLUUID ANIM_AGENT_PELVIS_FIX = LLUUID("0c5dd2a2-514d-8893-d44d-05beffad208b"); //"pelvis_fix"
const LLUUID ANIM_AGENT_TARGET = LLUUID("0e4896cb-fba4-926c-f355-8720189d5b55"); //"target"
const LLUUID ANIM_AGENT_WALK_ADJUST = LLUUID("829bc85b-02fc-ec41-be2e-74cc6dd7215d"); //"walk_adjust"
-const LLUUID ANIM_AGENT_BREAST_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"breast_motion"
+const LLUUID ANIM_AGENT_PHYSICS_MOTION = LLUUID("7360e029-3cb8-ebc4-863e-212df440d987"); //"physics_motion"
//-----------------------------------------------------------------------------
@@ -1149,7 +1149,7 @@ void LLVOAvatar::initClass()
gAnimLibrary.animStateSetString(ANIM_AGENT_BODY_NOISE,"body_noise");
gAnimLibrary.animStateSetString(ANIM_AGENT_BREATHE_ROT,"breathe_rot");
- gAnimLibrary.animStateSetString(ANIM_AGENT_BREAST_MOTION,"breast_motion");
+ gAnimLibrary.animStateSetString(ANIM_AGENT_PHYSICS_MOTION,"physics_motion");
gAnimLibrary.animStateSetString(ANIM_AGENT_EDITING,"editing");
gAnimLibrary.animStateSetString(ANIM_AGENT_EYE,"eye");
gAnimLibrary.animStateSetString(ANIM_AGENT_FLY_ADJUST,"fly_adjust");
@@ -1288,7 +1288,7 @@ void LLVOAvatar::initInstance(void)
// motions without a start/stop bit
registerMotion( ANIM_AGENT_BODY_NOISE, LLBodyNoiseMotion::create );
registerMotion( ANIM_AGENT_BREATHE_ROT, LLBreatheMotionRot::create );
- registerMotion( ANIM_AGENT_BREAST_MOTION, LLBreastMotion::create );
+ registerMotion( ANIM_AGENT_PHYSICS_MOTION, LLPhysicsMotionController::create );
registerMotion( ANIM_AGENT_EDITING, LLEditingMotion::create );
registerMotion( ANIM_AGENT_EYE, LLEyeMotion::create );
registerMotion( ANIM_AGENT_FEMALE_WALK, LLKeyframeWalkMotion::create );
@@ -1702,7 +1702,7 @@ void LLVOAvatar::startDefaultMotions()
startMotion( ANIM_AGENT_EYE );
startMotion( ANIM_AGENT_BODY_NOISE );
startMotion( ANIM_AGENT_BREATHE_ROT );
- startMotion( ANIM_AGENT_BREAST_MOTION );
+ startMotion( ANIM_AGENT_PHYSICS_MOTION );
startMotion( ANIM_AGENT_HAND_MOTION );
startMotion( ANIM_AGENT_PELVIS_FIX );
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index f5f90b2912..3659fb055f 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -50,7 +50,7 @@
extern const LLUUID ANIM_AGENT_BODY_NOISE;
extern const LLUUID ANIM_AGENT_BREATHE_ROT;
-extern const LLUUID ANIM_AGENT_BREAST_MOTION;
+extern const LLUUID ANIM_AGENT_PHYSICS_MOTION;
extern const LLUUID ANIM_AGENT_EDITING;
extern const LLUUID ANIM_AGENT_EYE;
extern const LLUUID ANIM_AGENT_FLY_ADJUST;
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 30de6d14c6..e183b0ba78 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2500,8 +2500,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Body Thin">Body Thin</string>
<string name="Bow Legged">Bow Legged</string>
-<string name="Breast Buoyancy">Breast Buoyancy</string>
-<string name="Breast Cleavage">Breast Cleavage</string>
+<string name="Breast Physics Updown Controller">Breast Buoyancy</string>
+<string name="Breast Physics Side Controller">Breast Cleavage</string>
<string name="Breast Size">Breast Size</string>
<string name="Bridge Width">Bridge Width</string>
<string name="Broad">Broad</string>
@@ -2527,9 +2527,23 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Breast Physics UpDown Drag">Breast UpDown Drag</string>
<string name="Breast Physics UpDown Max Speed">Breast UpDown Max Speed</string>
+<string name="Belly Physics UpDown Controller">Belly Updown Bounce</string>
+<string name="Belly Physics UpDown Spring">Belly Updown Spring</string>
+<string name="Belly Physics UpDown Gain">Belly Updown Gain</string>
+<string name="Belly Physics UpDown Damping">Belly Updown Damping</string>
+<string name="Belly Physics UpDown Max Speed">Belly Updown Max Speed</string>
+
+<string name="Butt Physics UpDown Controller">Butt UpDown Bounce</string>
+<string name="Butt Physics LeftRight Controller">Butt LeftRight Bounce</string>
+<string name="Butt Physics UpDown Spring">Butt UpDown Spring</string>
+<string name="Butt Physics UpDown Gain">Butt UpDown Gain</string>
+<string name="Butt Physics UpDown Damping">Butt UpDown Damping</string>
+<string name="Butt Physics UpDown Max Speed">Butt UpDown Max Speed</string>
+
<string name="Bushy Eyebrows">Bushy Eyebrows</string>
<string name="Bushy Hair">Bushy Hair</string>
<string name="Butt Size">Butt Size</string>
+<string name="Butt Gravity">Butt Gravity</string>
<string name="bustle skirt">Bustle Skirt</string>
<string name="no bustle">No Bustle</string>
<string name="more bustle">More Bustle</string>