PageRenderTime 34ms CodeModel.GetById 9ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llbreastmotion.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 396 lines | 234 code | 76 blank | 86 comment | 27 complexity | b25708502bc935ba370d6e6b5e24b367 MD5 | raw file
  1/** 
  2 * @file llbreastmotion.cpp
  3 * @brief Implementation of LLBreastMotion 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 "llbreastmotion.h"
 37#include "llcharacter.h"
 38#include "llviewercontrol.h"
 39#include "llviewervisualparam.h"
 40#include "llvoavatarself.h"
 41
 42#define MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION 0.f;
 43
 44#define N_PARAMS 2
 45
 46// User-set params
 47static const std::string breast_param_names_user[N_PARAMS] =
 48{
 49	"Breast_Female_Cleavage_Driver",
 50	"Breast_Gravity_Driver"
 51};
 52
 53// Params driven by this algorithm
 54static const std::string breast_param_names_driven[N_PARAMS] =
 55{
 56	"Breast_Female_Cleavage",
 57	"Breast_Gravity"
 58};
 59
 60
 61
 62LLBreastMotion::LLBreastMotion(const LLUUID &id) : 
 63	LLMotion(id),
 64	mCharacter(NULL)
 65{
 66	mName = "breast_motion";
 67	mChestState = new LLJointState;
 68
 69	mBreastMassParam = (F32)1.0;
 70	mBreastDragParam = LLVector3((F32)0.1, (F32)0.1, (F32)0.1);
 71	mBreastSmoothingParam = (U32)2;
 72	mBreastGravityParam = (F32)0.0;
 73
 74	mBreastSpringParam = LLVector3((F32)3.0, (F32)0.0, (F32)3.0);
 75	mBreastGainParam = LLVector3((F32)50.0, (F32)0.0, (F32)50.0);
 76	mBreastDampingParam = LLVector3((F32)0.3, (F32)0.0, (F32)0.3);
 77	mBreastMaxVelocityParam = LLVector3((F32)10.0, (F32)0.0, (F32)10.0);
 78
 79	mBreastParamsUser[0] = mBreastParamsUser[1] = mBreastParamsUser[2] = NULL;
 80	mBreastParamsDriven[0] = mBreastParamsDriven[1] = mBreastParamsDriven[2] = NULL;
 81
 82	mCharLastPosition_world_pt = LLVector3(0,0,0);
 83	mCharLastVelocity_local_vec = LLVector3(0,0,0);
 84	mCharLastAcceleration_local_vec = LLVector3(0,0,0);
 85	mBreastLastPosition_local_pt = LLVector3(0,0,0);
 86	mBreastLastUpdatePosition_local_pt = LLVector3(0,0,0);
 87	mBreastVelocity_local_vec = LLVector3(0,0,0);
 88}
 89
 90LLBreastMotion::~LLBreastMotion()
 91{
 92}
 93
 94BOOL LLBreastMotion::onActivate() 
 95{ 
 96	return TRUE; 
 97}
 98
 99void LLBreastMotion::onDeactivate() 
100{
101}
102
103LLMotion::LLMotionInitStatus LLBreastMotion::onInitialize(LLCharacter *character)
104{
105	mCharacter = character;
106
107	if (!mChestState->setJoint(character->getJoint("mChest")))
108	{
109		return STATUS_FAILURE;
110	}
111
112	mChestState->setUsage(LLJointState::ROT);
113	addJointState( mChestState );
114	
115	for (U32 i=0; i < N_PARAMS; i++)
116	{
117		mBreastParamsUser[i] = NULL;
118		mBreastParamsDriven[i] = NULL;
119		mBreastParamsMin[i] = 0;
120		mBreastParamsMax[i] = 0;
121		if (breast_param_names_user[i] != "" && breast_param_names_driven[i] != "")
122		{
123			mBreastParamsUser[i] = (LLViewerVisualParam*)mCharacter->getVisualParam(breast_param_names_user[i].c_str());
124			mBreastParamsDriven[i] = (LLViewerVisualParam*)mCharacter->getVisualParam(breast_param_names_driven[i].c_str());
125			if (mBreastParamsDriven[i])
126			{
127				mBreastParamsMin[i] = mBreastParamsDriven[i]->getMinWeight();
128				mBreastParamsMax[i] = mBreastParamsDriven[i]->getMaxWeight();
129			}
130		}
131	}
132	
133	mTimer.reset();
134	return STATUS_SUCCESS;
135}
136
137F32 LLBreastMotion::getMinPixelArea() 
138{
139	return MIN_REQUIRED_PIXEL_AREA_BREAST_MOTION;
140}
141	
142
143F32 LLBreastMotion::calculateTimeDelta()
144{
145	const F32 time = mTimer.getElapsedTimeF32();
146	const F32 time_delta = time - mLastTime;
147	mLastTime = time;
148	return time_delta;
149}
150
151// Local space means "parameter space".
152LLVector3 LLBreastMotion::toLocal(const LLVector3 &world_vector)
153{
154	LLVector3 local_vec(0,0,0);
155
156	LLJoint *chest_joint = mChestState->getJoint();
157	const LLQuaternion world_rot = chest_joint->getWorldRotation();
158	
159	// Cleavage
160	LLVector3 breast_dir_world_vec = LLVector3(-1,0,0) * world_rot; // -1 b/c cleavage param changes opposite to direction
161	breast_dir_world_vec.normalize();
162	local_vec[0] = world_vector * breast_dir_world_vec;
163	
164	// Up-Down Bounce
165	LLVector3 breast_up_dir_world_vec = LLVector3(0,0,1) * world_rot;
166	breast_up_dir_world_vec.normalize();
167	local_vec[1] = world_vector * breast_up_dir_world_vec;
168
169	return local_vec;
170}
171
172LLVector3 LLBreastMotion::calculateVelocity_local(const F32 time_delta)
173{
174	LLJoint *chest_joint = mChestState->getJoint();
175	const LLVector3 world_pos_pt = chest_joint->getWorldPosition();
176	const LLQuaternion world_rot = chest_joint->getWorldRotation();
177	const LLVector3 last_world_pos_pt = mCharLastPosition_world_pt;
178	const LLVector3 char_velocity_world_vec = (world_pos_pt-last_world_pos_pt) / time_delta;
179	const LLVector3 char_velocity_local_vec = toLocal(char_velocity_world_vec);
180
181	return char_velocity_local_vec;
182}
183
184LLVector3 LLBreastMotion::calculateAcceleration_local(const LLVector3 &new_char_velocity_local_vec,
185													  const F32 time_delta)
186{
187	LLVector3 char_acceleration_local_vec = new_char_velocity_local_vec - mCharLastVelocity_local_vec;
188	
189	char_acceleration_local_vec = 
190		char_acceleration_local_vec * 1.0/mBreastSmoothingParam + 
191		mCharLastAcceleration_local_vec * (mBreastSmoothingParam-1.0)/mBreastSmoothingParam;
192
193	mCharLastAcceleration_local_vec = char_acceleration_local_vec;
194
195	return char_acceleration_local_vec;
196}
197
198BOOL LLBreastMotion::onUpdate(F32 time, U8* joint_mask)
199{
200	// Skip if disabled globally.
201	if (!gSavedSettings.getBOOL("AvatarPhysics"))
202	{
203		return TRUE;
204	}
205
206	// Higher LOD is better.  This controls the granularity
207	// and frequency of updates for the motions.
208	const F32 lod_factor = LLVOAvatar::sPhysicsLODFactor;
209	if (lod_factor == 0)
210	{
211		return TRUE;
212	}
213	
214	if (mCharacter->getSex() != SEX_FEMALE) return TRUE;
215	const F32 time_delta = calculateTimeDelta();
216	if (time_delta < .01 || time_delta > 10.0) return TRUE;
217
218
219	////////////////////////////////////////////////////////////////////////////////
220	// Get all parameters and settings
221	//
222
223	mBreastMassParam = mCharacter->getVisualParamWeight("Breast_Physics_Mass");
224	mBreastSmoothingParam = (U32)(mCharacter->getVisualParamWeight("Breast_Physics_Smoothing"));
225	mBreastGravityParam = mCharacter->getVisualParamWeight("Breast_Physics_Gravity");
226
227	mBreastSpringParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Spring");
228	mBreastGainParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Gain");
229	mBreastDampingParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Damping");
230	mBreastMaxVelocityParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Max_Velocity");
231	mBreastDragParam[0] = mCharacter->getVisualParamWeight("Breast_Physics_Side_Drag");
232
233	mBreastSpringParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Spring");
234	mBreastGainParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Gain");
235	mBreastDampingParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Damping");
236	mBreastMaxVelocityParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Max_Velocity");
237	mBreastDragParam[1] = mCharacter->getVisualParamWeight("Breast_Physics_UpDown_Drag");
238
239
240	// Get the current morph parameters.
241	LLVector3 breast_user_local_pt(0,0,0);
242	for (U32 i=0; i < N_PARAMS; i++)
243	{
244		if (mBreastParamsUser[i] != NULL)
245		{
246			breast_user_local_pt[i] = mBreastParamsUser[i]->getWeight();
247		}
248	}
249	
250	LLVector3 breast_current_local_pt = mBreastLastPosition_local_pt;
251
252	//
253	// End parameters and settings
254	////////////////////////////////////////////////////////////////////////////////
255
256
257	////////////////////////////////////////////////////////////////////////////////
258	// Calculate velocity and acceleration in parameter space.
259	//
260
261	const LLVector3 char_velocity_local_vec = calculateVelocity_local(time_delta);
262	const LLVector3 char_acceleration_local_vec = calculateAcceleration_local(char_velocity_local_vec, time_delta);
263	mCharLastVelocity_local_vec = char_velocity_local_vec;
264
265	LLJoint *chest_joint = mChestState->getJoint();
266	mCharLastPosition_world_pt = chest_joint->getWorldPosition();
267
268	//
269	// End velocity and acceleration
270	////////////////////////////////////////////////////////////////////////////////
271
272
273	////////////////////////////////////////////////////////////////////////////////
274	// Calculate the total force 
275	//
276
277	// Spring force is a restoring force towards the original user-set breast position.
278	// F = kx
279	const LLVector3 spring_length_local = breast_current_local_pt-breast_user_local_pt;
280	LLVector3 force_spring_local_vec = -spring_length_local; force_spring_local_vec *= mBreastSpringParam;
281
282	// Acceleration is the force that comes from the change in velocity of the torso.
283	// F = ma + mg
284	LLVector3 force_accel_local_vec = char_acceleration_local_vec * mBreastMassParam;
285	const LLVector3 force_gravity_local_vec = toLocal(LLVector3(0,0,1))* mBreastGravityParam * mBreastMassParam;
286	force_accel_local_vec += force_gravity_local_vec;
287	force_accel_local_vec *= mBreastGainParam;
288
289	// Damping is a restoring force that opposes the current velocity.
290	// F = -kv
291	LLVector3 force_damping_local_vec = -mBreastDampingParam; 
292	force_damping_local_vec *= mBreastVelocity_local_vec;
293	
294	// Drag is a force imparted by velocity, intuitively it is similar to wind resistance.
295	// F = .5v*v
296	LLVector3 force_drag_local_vec = .5*char_velocity_local_vec;
297	force_drag_local_vec *= char_velocity_local_vec;
298	force_drag_local_vec *= mBreastDragParam[0];
299
300	LLVector3 force_net_local_vec = 
301		force_accel_local_vec + 
302		force_gravity_local_vec +
303		force_spring_local_vec + 
304		force_damping_local_vec + 
305		force_drag_local_vec;
306
307	//
308	// End total force
309	////////////////////////////////////////////////////////////////////////////////
310
311	
312	////////////////////////////////////////////////////////////////////////////////
313	// Calculate new params
314	//
315
316	// Calculate the new acceleration based on the net force.
317	// a = F/m
318	LLVector3 acceleration_local_vec = force_net_local_vec / mBreastMassParam;
319	mBreastVelocity_local_vec += acceleration_local_vec;
320	mBreastVelocity_local_vec.clamp(-mBreastMaxVelocityParam*100.0, mBreastMaxVelocityParam*100.0);
321
322	// Temporary debugging setting to cause all avatars to move, for profiling purposes.
323	if (gSavedSettings.getBOOL("AvatarPhysicsTest"))
324	{
325		mBreastVelocity_local_vec[0] = sin(mTimer.getElapsedTimeF32()*4.0)*5.0;
326		mBreastVelocity_local_vec[1] = sin(mTimer.getElapsedTimeF32()*3.0)*5.0;
327	}
328	// Calculate the new parameters and clamp them to the min/max ranges.
329	LLVector3 new_local_pt = breast_current_local_pt + mBreastVelocity_local_vec*time_delta;
330	new_local_pt.clamp(mBreastParamsMin,mBreastParamsMax);
331		
332	// Set the new parameters.
333	for (U32 i=0; i < 3; i++)
334	{
335		// If the param is disabled, just set the param to the user value.
336		if (mBreastMaxVelocityParam[i] == 0)
337		{
338			new_local_pt[i] = breast_user_local_pt[i];
339		}
340		if (mBreastParamsDriven[i])
341		{
342			mCharacter->setVisualParamWeight(mBreastParamsDriven[i],
343											 new_local_pt[i],
344											 FALSE);
345		}
346	}
347
348	mBreastLastPosition_local_pt = new_local_pt;
349	
350	//
351	// End calculate new params
352	////////////////////////////////////////////////////////////////////////////////
353	
354
355	////////////////////////////////////////////////////////////////////////////////
356	// Conditionally update the visual params
357	//
358
359	// Updating the visual params (i.e. what the user sees) is fairly expensive.
360	// So only update if the params have changed enough, and also take into account
361	// the graphics LOD settings.
362	
363	// For non-self, if the avatar is small enough visually, then don't update.
364	const BOOL is_self = (dynamic_cast<LLVOAvatarSelf *>(this) != NULL);
365	if (!is_self)
366	{
367		const F32 area_for_max_settings = 0.0;
368		const F32 area_for_min_settings = 1400.0;
369
370		const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor);
371		const F32 pixel_area = fsqrtf(mCharacter->getPixelArea());
372		if (pixel_area < area_for_this_setting)
373		{
374			return TRUE;
375		}
376	}
377
378	// If the parameter hasn't changed enough, then don't update.
379	LLVector3 position_diff = mBreastLastUpdatePosition_local_pt-new_local_pt;
380	for (U32 i=0; i < 3; i++)
381	{
382		const F32 min_delta = (1.0-lod_factor)*(mBreastParamsMax[i]-mBreastParamsMin[i])/2.0;
383		if (llabs(position_diff[i]) > min_delta)
384		{
385			mCharacter->updateVisualParams();
386			mBreastLastUpdatePosition_local_pt = new_local_pt;
387			return TRUE;
388		}
389	}
390	
391	//
392	// End update visual params
393	////////////////////////////////////////////////////////////////////////////////
394
395	return TRUE;
396}