Prep for animesh.

This commit is contained in:
Shyotl
2019-03-09 01:51:50 -06:00
parent cd340f0fb6
commit 5d75b3b223
28 changed files with 700 additions and 333 deletions

View File

@@ -236,6 +236,14 @@
<boolean>false</boolean>
</map>
<key>ObjectAnimation</key>
<map>
<key>flavor</key>
<string>template</string>
<key>trusted-sender</key>
<boolean>false</boolean>
</map>
<key>AvatarAppearance</key>
<map>
<key>flavor</key>

View File

@@ -185,8 +185,9 @@ LLAvatarAppearance::LLAvatarAppearance(LLWearableData* wearable_data) :
mHeadOffset(),
mRoot(NULL),
mWearableData(wearable_data),
mNumBones(0),
mIsBuilt(FALSE)
mNumBones(0),
mIsBuilt(FALSE),
mInitFlags(0)
{
llassert_always(mWearableData);
mBakedTextureDatas.resize(LLAvatarAppearanceDefines::BAKED_NUM_INDICES);
@@ -282,6 +283,8 @@ void LLAvatarAppearance::initInstance()
}
buildCharacter();
mInitFlags |= 1<<0;
}
// virtual
@@ -1370,12 +1373,12 @@ LLVector3 LLAvatarAppearance::getVolumePos(S32 joint_index, LLVector3& volume_of
//-----------------------------------------------------------------------------
// findCollisionVolume()
//-----------------------------------------------------------------------------
LLJoint* LLAvatarAppearance::findCollisionVolume(U32 volume_id)
LLJoint* LLAvatarAppearance::findCollisionVolume(S32 volume_id)
{
//SNOW-488: As mNumCollisionVolumes is a S32 and we are casting from a U32 to a S32
//to compare we also need to be sure of the wrap around case producing (S32) <0
//or in terms of the U32 an out of bounds index in the array.
if ((S32)volume_id > (S32)mCollisionVolumes.size() || (S32)volume_id<0)
if ((S32)volume_id > (S32)mCollisionVolumes.size() || volume_id<0)
{
return NULL;
}
@@ -1828,13 +1831,34 @@ const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases
{
LLAvatarSkeletonInfo::bone_info_list_t::const_iterator iter;
for (iter = sAvatarSkeletonInfo->mBoneInfoList.begin(); iter != sAvatarSkeletonInfo->mBoneInfoList.end(); ++iter)
for (iter = sAvatarSkeletonInfo->mBoneInfoList.begin();
iter != sAvatarSkeletonInfo->mBoneInfoList.end();
++iter)
{
//LLAvatarBoneInfo *bone_info = *iter;
makeJointAliases( *iter );
}
LLAvatarXmlInfo::attachment_info_list_t::iterator attach_iter;
for (attach_iter = sAvatarXmlInfo->mAttachmentInfoList.begin();
attach_iter != sAvatarXmlInfo->mAttachmentInfoList.end();
++attach_iter)
{
LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *attach_iter;
std::string bone_name = info->mName;
// Also accept the name with spaces substituted with
// underscores. This gives a mechanism for referencing such joints
// in daes, which don't allow spaces.
std::string sub_space_to_underscore = bone_name;
LLStringUtil::replaceChar(sub_space_to_underscore, ' ', '_');
if (sub_space_to_underscore != bone_name)
{
mJointAliasMap[sub_space_to_underscore] = bone_name;
}
}
}
return mJointAliasMap;
}

View File

@@ -71,6 +71,7 @@ public:
static void initClass(); // initializes static members
static void cleanupClass(); // Cleanup data that's only init'd once per class.
virtual void initInstance(); // Called after construction to initialize the instance.
S32 mInitFlags;
virtual BOOL loadSkeletonNode();
BOOL loadMeshNodes();
BOOL loadLayersets();
@@ -93,7 +94,7 @@ public:
/*virtual*/ const char* getAnimationPrefix() { return "avatar"; }
/*virtual*/ LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset);
/*virtual*/ LLJoint* findCollisionVolume(U32 volume_id);
/*virtual*/ LLJoint* findCollisionVolume(S32 volume_id);
/*virtual*/ S32 getCollisionVolumeID(std::string &name);
/*virtual*/ LLPolyMesh* getHeadMesh();
/*virtual*/ LLPolyMesh* getUpperBodyMesh();
@@ -234,7 +235,7 @@ protected:
** RENDERING
**/
public:
BOOL mIsDummy; // for special views
BOOL mIsDummy; // for special views and animated object controllers; local to viewer
//--------------------------------------------------------------------
// Morph masks

View File

@@ -182,7 +182,7 @@ public:
virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset) { return LLVector3::zero; }
virtual LLJoint* findCollisionVolume(U32 volume_id) { return NULL; }
virtual LLJoint* findCollisionVolume(S32 volume_id) { return NULL; }
virtual S32 getCollisionVolumeID(std::string &name) { return -1; }

View File

@@ -69,6 +69,17 @@ public:
private:
map_type m_map;
};
inline bool operator==(const LLVector3OverrideMap& a, const LLVector3OverrideMap& b)
{
return a.getMap() == b.getMap();
}
inline bool operator!=(const LLVector3OverrideMap& a, const LLVector3OverrideMap& b)
{
return !(a == b);
}
//-----------------------------------------------------------------------------
// class LLJoint
//-----------------------------------------------------------------------------

View File

@@ -623,7 +623,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
LLDataPackerBinaryBuffer dp(anim_data, anim_file_size);
if (!deserialize(dp))
if (!deserialize(dp, getID()))
{
LL_WARNS() << "Failed to decode asset for animation " << getName() << ":" << getID() << LL_ENDL;
mAssetStatus = ASSET_FETCH_FAILED;
@@ -1291,7 +1291,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
//-----------------------------------------------------------------------------
// deserialize()
//-----------------------------------------------------------------------------
BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id)
{
BOOL old_version = FALSE;
@@ -1324,13 +1324,13 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (!dp.unpackU16(version, "version"))
{
LL_WARNS() << "can't read version number" << LL_ENDL;
LL_WARNS() << "can't read version number for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackU16(sub_version, "sub_version"))
{
LL_WARNS() << "can't read sub version number" << LL_ENDL;
LL_WARNS() << "can't read sub version number for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1341,28 +1341,32 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
else if (version != KEYFRAME_MOTION_VERSION || sub_version != KEYFRAME_MOTION_SUBVERSION)
{
#if LL_RELEASE
LL_WARNS() << "Bad animation version " << version << "." << sub_version << LL_ENDL;
LL_WARNS() << "Bad animation version " << version << "." << sub_version
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
#else
LL_ERRS() << "Bad animation version " << version << "." << sub_version << LL_ENDL;
LL_ERRS() << "Bad animation version " << version << "." << sub_version
<< " for animation " << asset_id << LL_ENDL;
#endif
}
if (!dp.unpackS32(temp_priority, "base_priority"))
{
LL_WARNS() << "can't read animation base_priority" << LL_ENDL;
LL_WARNS() << "can't read animation base_priority"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
mJointMotionList->mBasePriority = (LLJoint::JointPriority) temp_priority;
if (mJointMotionList->mBasePriority >= LLJoint::ADDITIVE_PRIORITY)
{
mJointMotionList->mBasePriority = (LLJoint::JointPriority)((int)LLJoint::ADDITIVE_PRIORITY-1);
mJointMotionList->mBasePriority = (LLJoint::JointPriority)((S32)LLJoint::ADDITIVE_PRIORITY-1);
mJointMotionList->mMaxPriority = mJointMotionList->mBasePriority;
}
else if (mJointMotionList->mBasePriority < LLJoint::USE_MOTION_PRIORITY)
{
LL_WARNS() << "bad animation base_priority " << mJointMotionList->mBasePriority << LL_ENDL;
LL_WARNS() << "bad animation base_priority " << mJointMotionList->mBasePriority
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1371,14 +1375,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
//-------------------------------------------------------------------------
if (!dp.unpackF32(mJointMotionList->mDuration, "duration"))
{
LL_WARNS() << "can't read duration" << LL_ENDL;
LL_WARNS() << "can't read duration"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (mJointMotionList->mDuration > MAX_ANIM_DURATION ||
!std::isfinite(mJointMotionList->mDuration))
{
LL_WARNS() << "invalid animation duration" << LL_ENDL;
LL_WARNS() << "invalid animation duration"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1387,13 +1393,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
//-------------------------------------------------------------------------
if (!dp.unpackString(mJointMotionList->mEmoteName, "emote_name"))
{
LL_WARNS() << "can't read optional_emote_animation" << LL_ENDL;
LL_WARNS() << "can't read optional_emote_animation"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if(mJointMotionList->mEmoteName==mID.asString())
{
LL_WARNS() << "Malformed animation mEmoteName==mID" << LL_ENDL;
LL_WARNS() << "Malformed animation mEmoteName==mID"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1403,20 +1411,23 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (!dp.unpackF32(mJointMotionList->mLoopInPoint, "loop_in_point") ||
!std::isfinite(mJointMotionList->mLoopInPoint))
{
LL_WARNS() << "can't read loop point" << LL_ENDL;
LL_WARNS() << "can't read loop point"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackF32(mJointMotionList->mLoopOutPoint, "loop_out_point") ||
!std::isfinite(mJointMotionList->mLoopOutPoint))
{
LL_WARNS() << "can't read loop point" << LL_ENDL;
LL_WARNS() << "can't read loop point"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackS32(mJointMotionList->mLoop, "loop"))
{
LL_WARNS() << "can't read loop" << LL_ENDL;
LL_WARNS() << "can't read loop"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1426,14 +1437,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (!dp.unpackF32(mJointMotionList->mEaseInDuration, "ease_in_duration") ||
!std::isfinite(mJointMotionList->mEaseInDuration))
{
LL_WARNS() << "can't read easeIn" << LL_ENDL;
LL_WARNS() << "can't read easeIn"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackF32(mJointMotionList->mEaseOutDuration, "ease_out_duration") ||
!std::isfinite(mJointMotionList->mEaseOutDuration))
{
LL_WARNS() << "can't read easeOut" << LL_ENDL;
LL_WARNS() << "can't read easeOut"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1443,13 +1456,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
U32 word;
if (!dp.unpackU32(word, "hand_pose"))
{
LL_WARNS() << "can't read hand pose" << LL_ENDL;
LL_WARNS() << "can't read hand pose"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if(word > LLHandMotion::NUM_HAND_POSES)
{
LL_WARNS() << "invalid LLHandMotion::eHandPose index: " << word << LL_ENDL;
LL_WARNS() << "invalid LLHandMotion::eHandPose index: " << word
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1461,18 +1476,21 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
U32 num_motions = 0;
if (!dp.unpackU32(num_motions, "num_joints"))
{
LL_WARNS() << "can't read number of joints" << LL_ENDL;
LL_WARNS() << "can't read number of joints"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (num_motions == 0)
{
LL_WARNS() << "no joints in animation" << LL_ENDL;
LL_WARNS() << "no joints"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
else if (num_motions > LL_CHARACTER_MAX_ANIMATED_JOINTS)
{
LL_WARNS() << "too many joints in animation" << LL_ENDL;
LL_WARNS() << "too many joints"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1500,13 +1518,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
std::string joint_name;
if (!dp.unpackString(joint_name, "joint_name"))
{
LL_WARNS() << "can't read joint name" << LL_ENDL;
LL_WARNS() << "can't read joint name"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (joint_name == "mScreen" || joint_name == "mRoot")
{
LL_WARNS() << "attempted to animate special " << joint_name << " joint" << LL_ENDL;
LL_WARNS() << "attempted to animate special " << joint_name << " joint"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1520,10 +1540,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
// LL_INFOS() << " joint: " << joint_name << LL_ENDL;
if ((joint_num >= (S32)LL_CHARACTER_MAX_ANIMATED_JOINTS) || (joint_num < 0))
{
LL_WARNS() << "Joint will be omitted from animation: joint_num " << joint_num << " is outside of legal range [0-"
<< LL_CHARACTER_MAX_ANIMATED_JOINTS << ") for joint " << joint->getName() << LL_ENDL;
joint = NULL;
}
LL_WARNS() << "Joint will be omitted from animation: joint_num " << joint_num
<< " is outside of legal range [0-"
<< LL_CHARACTER_MAX_ANIMATED_JOINTS << ") for joint " << joint->getName()
<< " for animation " << asset_id << LL_ENDL;
joint = NULL;
}
}
else
{
@@ -1539,7 +1561,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
i++;
}
// </edit>
LL_WARNS() << "joint not found: " << joint_name << LL_ENDL;
LL_WARNS() << "invalid joint name: " << joint_name
<< " for animation " << asset_id << LL_ENDL;
//return FALSE;
}
@@ -1556,13 +1579,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
S32 joint_priority;
if (!dp.unpackS32(joint_priority, "joint_priority"))
{
LL_WARNS() << "can't read joint priority." << LL_ENDL;
LL_WARNS() << "can't read joint priority."
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (joint_priority < LLJoint::USE_MOTION_PRIORITY)
{
LL_WARNS() << "joint priority unknown - too low." << LL_ENDL;
LL_WARNS() << "joint priority unknown - too low."
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1580,7 +1605,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
//---------------------------------------------------------------------
if (!dp.unpackS32(joint_motion->mRotationCurve.mNumKeys, "num_rot_keys") || joint_motion->mRotationCurve.mNumKeys < 0)
{
LL_WARNS() << "can't read number of rotation keys" << LL_ENDL;
LL_WARNS() << "can't read number of rotation keys"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1605,7 +1631,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (!dp.unpackF32(time, "time") ||
!std::isfinite(time))
{
LL_WARNS() << "can't read rotation key (" << k << ")" << LL_ENDL;
LL_WARNS() << "can't read rotation key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1614,7 +1641,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
{
if (!dp.unpackU16(time_short, "time"))
{
LL_WARNS() << "can't read rotation key (" << k << ")" << LL_ENDL;
LL_WARNS() << "can't read rotation key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1622,7 +1650,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (time < 0 || time > mJointMotionList->mDuration)
{
LL_WARNS() << "invalid frame time" << LL_ENDL;
LL_WARNS() << "invalid frame time"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
}
@@ -1656,13 +1685,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if( !(rot_key.mRotation.isFinite()) )
{
LL_WARNS() << "non-finite angle in rotation key" << LL_ENDL;
LL_WARNS() << "non-finite angle in rotation key"
<< " for animation " << asset_id << LL_ENDL;
success = FALSE;
}
if (!success)
{
LL_WARNS() << "can't read rotation key (" << k << ")" << LL_ENDL;
LL_WARNS() << "can't read rotation key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1674,7 +1705,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
//---------------------------------------------------------------------
if (!dp.unpackS32(joint_motion->mPositionCurve.mNumKeys, "num_pos_keys") || joint_motion->mPositionCurve.mNumKeys < 0)
{
LL_WARNS() << "can't read number of position keys" << LL_ENDL;
LL_WARNS() << "can't read number of position keys"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1699,7 +1731,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (!dp.unpackF32(pos_key.mTime, "time") ||
!std::isfinite(pos_key.mTime))
{
LL_WARNS() << "can't read position key (" << k << ")" << LL_ENDL;
LL_WARNS() << "can't read position key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
}
@@ -1707,7 +1740,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
{
if (!dp.unpackU16(time_short, "time"))
{
LL_WARNS() << "can't read position key (" << k << ")" << LL_ENDL;
LL_WARNS() << "can't read position key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1741,13 +1775,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if( !(pos_key.mPosition.isFinite()) )
{
LL_WARNS() << "non-finite position in key" << LL_ENDL;
LL_WARNS() << "non-finite position in key"
<< " for animation " << asset_id << LL_ENDL;
success = FALSE;
}
if (!success)
{
LL_WARNS() << "can't read position key (" << k << ")" << LL_ENDL;
LL_WARNS() << "can't read position key (" << k << ")"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1768,13 +1804,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
S32 num_constraints = 0;
if (!dp.unpackS32(num_constraints, "num_constraints"))
{
LL_WARNS() << "can't read number of constraints" << LL_ENDL;
LL_WARNS() << "can't read number of constraints"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (num_constraints > MAX_CONSTRAINTS || num_constraints < 0)
{
LL_WARNS() << "Bad number of constraints... ignoring: " << num_constraints << LL_ENDL;
LL_WARNS() << "Bad number of constraints... ignoring: " << num_constraints
<< " for animation " << asset_id << LL_ENDL;
}
else
{
@@ -1791,26 +1829,30 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (!dp.unpackU8(byte, "chain_length"))
{
LL_WARNS() << "can't read constraint chain length" << LL_ENDL;
LL_WARNS() << "can't read constraint chain length"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
constraintp->mChainLength = (S32) byte;
if((U32)constraintp->mChainLength > mJointMotionList->getNumJointMotions())
{
LL_WARNS() << "invalid constraint chain length" << LL_ENDL;
LL_WARNS() << "invalid constraint chain length"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackU8(byte, "constraint_type"))
{
LL_WARNS() << "can't read constraint type" << LL_ENDL;
LL_WARNS() << "can't read constraint type"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if( byte >= NUM_CONSTRAINT_TYPES )
{
LL_WARNS() << "invalid constraint type" << LL_ENDL;
LL_WARNS() << "invalid constraint type"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
constraintp->mConstraintType = (EConstraintType)byte;
@@ -1819,37 +1861,39 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
U8 bin_data[BIN_DATA_LENGTH+1];
if (!dp.unpackBinaryDataFixed(bin_data, BIN_DATA_LENGTH, "source_volume"))
{
LL_WARNS() << "can't read source volume name" << LL_ENDL;
LL_WARNS() << "can't read source volume name"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
bin_data[BIN_DATA_LENGTH] = 0; // Ensure null termination
str = (char*)bin_data;
constraintp->mSourceConstraintVolume = mCharacter->getCollisionVolumeID(str);
// <edit>
if(constraintp->mSourceConstraintVolume == -1)
if (constraintp->mSourceConstraintVolume == -1)
{
LL_WARNS() << "can't get source constraint volume" << LL_ENDL;
LL_WARNS() << "not a valid source constraint volume " << str
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
// </edit>
if (!dp.unpackVector3(constraintp->mSourceConstraintOffset, "source_offset"))
{
LL_WARNS() << "can't read constraint source offset" << LL_ENDL;
LL_WARNS() << "can't read constraint source offset"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if( !(constraintp->mSourceConstraintOffset.isFinite()) )
{
LL_WARNS() << "non-finite constraint source offset" << LL_ENDL;
LL_WARNS() << "non-finite constraint source offset"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackBinaryDataFixed(bin_data, BIN_DATA_LENGTH, "target_volume"))
{
LL_WARNS() << "can't read target volume name" << LL_ENDL;
LL_WARNS() << "can't read target volume name"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1864,29 +1908,39 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
{
constraintp->mConstraintTargetType = CONSTRAINT_TARGET_TYPE_BODY;
constraintp->mTargetConstraintVolume = mCharacter->getCollisionVolumeID(str);
if (constraintp->mTargetConstraintVolume == -1)
{
LL_WARNS() << "not a valid target constraint volume " << str
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
}
if (!dp.unpackVector3(constraintp->mTargetConstraintOffset, "target_offset"))
{
LL_WARNS() << "can't read constraint target offset" << LL_ENDL;
LL_WARNS() << "can't read constraint target offset"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if( !(constraintp->mTargetConstraintOffset.isFinite()) )
{
LL_WARNS() << "non-finite constraint target offset" << LL_ENDL;
LL_WARNS() << "non-finite constraint target offset"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackVector3(constraintp->mTargetConstraintDir, "target_dir"))
{
LL_WARNS() << "can't read constraint target direction" << LL_ENDL;
LL_WARNS() << "can't read constraint target direction"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if( !(constraintp->mTargetConstraintDir.isFinite()) )
{
LL_WARNS() << "non-finite constraint target direction" << LL_ENDL;
LL_WARNS() << "non-finite constraint target direction"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1898,25 +1952,29 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (!dp.unpackF32(constraintp->mEaseInStartTime, "ease_in_start") || !std::isfinite(constraintp->mEaseInStartTime))
{
LL_WARNS() << "can't read constraint ease in start time" << LL_ENDL;
LL_WARNS() << "can't read constraint ease in start time"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackF32(constraintp->mEaseInStopTime, "ease_in_stop") || !std::isfinite(constraintp->mEaseInStopTime))
{
LL_WARNS() << "can't read constraint ease in stop time" << LL_ENDL;
LL_WARNS() << "can't read constraint ease in stop time"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackF32(constraintp->mEaseOutStartTime, "ease_out_start") || !std::isfinite(constraintp->mEaseOutStartTime))
{
LL_WARNS() << "can't read constraint ease out start time" << LL_ENDL;
LL_WARNS() << "can't read constraint ease out start time"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
if (!dp.unpackF32(constraintp->mEaseOutStopTime, "ease_out_stop") || !std::isfinite(constraintp->mEaseOutStopTime))
{
LL_WARNS() << "can't read constraint ease out stop time" << LL_ENDL;
LL_WARNS() << "can't read constraint ease out stop time"
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1939,7 +1997,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if (!parent)
{
LL_WARNS() << "Joint with no parent: " << joint->getName()
<< " Emote: " << mJointMotionList->mEmoteName << LL_ENDL;
<< " Emote: " << mJointMotionList->mEmoteName
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
joint = parent;
@@ -1950,7 +2009,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
if ( !constraint_joint )
{
LL_WARNS() << "Invalid joint " << j << LL_ENDL;
LL_WARNS() << "Invalid joint " << j
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
@@ -1962,7 +2022,8 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
}
if (constraintp->mJointStateIndices[i] < 0 )
{
LL_WARNS() << "No joint index for constraint " << i << LL_ENDL;
LL_WARNS() << "No joint index for constraint " << i
<< " for animation " << asset_id << LL_ENDL;
return FALSE;
}
}
@@ -2318,7 +2379,7 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
LL_DEBUGS("Animation") << "Loading keyframe data for: " << motionp->getName() << ":" << motionp->getID() << " (" << size << " bytes)" << LL_ENDL;
LLDataPackerBinaryBuffer dp(buffer, size);
if (motionp->deserialize(dp))
if (motionp->deserialize(dp, asset_uuid))
{
motionp->mAssetStatus = ASSET_LOADED;
}

View File

@@ -266,7 +266,7 @@ public:
public:
U32 getFileSize();
BOOL serialize(LLDataPacker& dp) const;
BOOL deserialize(LLDataPacker& dp);
BOOL deserialize(LLDataPacker& dp, const LLUUID& asset_id);
BOOL isLoaded() { return !!mJointMotionList; }

View File

@@ -126,22 +126,22 @@ LLMotion* LLMotionRegistry::createMotion(LLUUID const& id, LLMotionController* c
// Class Constructor
//-----------------------------------------------------------------------------
LLMotionController::LLMotionController()
: mIsSelf(FALSE),
mTimeFactor(sCurrentTimeFactor),
: mTimeFactor(sCurrentTimeFactor),
mCharacter(NULL),
mAnimTime(0.f),
mActiveMask(0),
mDisableSyncing(0),
mHidden(false),
mHaveVisibleSyncedMotions(false),
mPrevTimerElapsed(0.f),
mAnimTime(0.f),
mLastTime(0.0f),
mHasRunOnce(FALSE),
mPaused(FALSE),
mPauseTime(0.f),
mPausedFrame(0),
mTimeStep(0.f),
mTimeStepCount(0),
mLastInterp(0.f)
mLastInterp(0.f),
mIsSelf(FALSE)
{
}
@@ -467,7 +467,7 @@ BOOL LLMotionController::stopMotionLocally(const LLUUID &id, BOOL stop_immediate
{
// if already inactive, return false
LLMotion *motion = findMotion(id);
return stopMotionInstance(motion, stop_immediate);
return stopMotionInstance(motion, stop_immediate||mPaused);
}
BOOL LLMotionController::stopMotionInstance(LLMotion* motion, BOOL stop_immediate)
@@ -1312,6 +1312,7 @@ void LLMotionController::pauseAllMotions()
{
//LL_INFOS() << "Pausing animations..." << LL_ENDL;
mPaused = TRUE;
mPausedFrame = LLFrameTimer::getFrameCount();
}
}

View File

@@ -162,16 +162,20 @@ public:
void pauseAllMotions();
void unpauseAllMotions();
BOOL isPaused() const { return mPaused; }
S32 getPausedFrame() const { return mPausedFrame; }
//<singu>
void requestPause(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
void pauseAllSyncedCharacters(std::vector<LLAnimPauseRequest>& avatar_pause_handles);
//</singu>
void setTimeStep(F32 step);
F32 getTimeStep() const { return mTimeStep; }
void setTimeFactor(F32 time_factor);
F32 getTimeFactor() const { return mTimeFactor; }
F32 getAnimTime() const { return mAnimTime; }
motion_list_t& getActiveMotions() { return mActiveMotions; }
void incMotionCounts(S32& num_motions, S32& num_loading_motions, S32& num_loaded_motions, S32& num_active_motions, S32& num_deprecated_motions);
@@ -248,7 +252,7 @@ protected:
F32 mLastTime;
BOOL mHasRunOnce;
BOOL mPaused;
F32 mPauseTime;
S32 mPausedFrame;
F32 mTimeStep;
S32 mTimeStepCount;
F32 mLastInterp;
@@ -263,7 +267,6 @@ public:
bool syncing_disabled(void) const { return mDisableSyncing >= 100; }
// Accessors needed for synchronization.
F32 getAnimTime(void) const { return mAnimTime; }
bool isHidden(void) const { return mHidden; }
// Called often. Should return false if we still need to keep updating our motions even if we're not visible.

View File

@@ -22,6 +22,7 @@ set(llmath_SOURCE_FILES
llperlin.cpp
llquaternion.cpp
llrect.cpp
llrigginginfo.cpp
llsdutil_math.cpp
llsphere.cpp
llvector4a.cpp
@@ -67,6 +68,7 @@ set(llmath_HEADER_FILES
llquaternion2.h
llquaternion2.inl
llrect.h
llrigginginfo.h
llsdutil_math.h
llsimdmath.h
llsimdtypes.h

View File

@@ -700,4 +700,12 @@ public:
}
} LL_ALIGN_POSTFIX(16);
inline std::ostream& operator<<(std::ostream& s, const LLMatrix4a& m)
{
s << "[" << m.getF32ptr()[0] << ", " << m.getF32ptr()[1] << ", " << m.getF32ptr()[2] << ", " << m.getF32ptr()[3] << "]";
return s;
}
void matMulBoundBox(const LLMatrix4a &a, const LLVector4a *in_extents, LLVector4a *out_extents);
#endif

View File

@@ -336,4 +336,9 @@ inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p
max.setMax(max, p);
}
inline std::ostream& operator<<(std::ostream& s, const LLVector4a& v)
{
s << "(" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ")";
return s;
}
#endif

View File

@@ -1301,7 +1301,7 @@ S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff
void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)
{
// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane.
const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
F32 revolutions = params.getRevolutions();
F32 skew = params.getSkew();
@@ -1599,6 +1599,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
if (is_sculpted)
sides = llmax(sculpt_size, 1);
if (0 < sides)
genNGon(params, sides);
}
break;
@@ -2081,6 +2082,7 @@ void LLVolume::resizePath(S32 length)
{
mPathp->resizePath(length);
mVolumeFaces.clear();
setDirty();
}
void LLVolume::regen()
@@ -2138,19 +2140,22 @@ BOOL LLVolume::generate()
F32 profile_detail = mDetail;
F32 path_detail = mDetail;
U8 path_type = mParams.getPathParams().getCurveType();
U8 profile_type = mParams.getProfileParams().getCurveType();
if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
{ //cylinders don't care about Z-Axis
mLODScaleBias.setVec(0.6f, 0.6f, 0.0f);
if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)
{
U8 path_type = mParams.getPathParams().getCurveType();
U8 profile_type = mParams.getProfileParams().getCurveType();
if (path_type == LL_PCODE_PATH_LINE && profile_type == LL_PCODE_PROFILE_CIRCLE)
{
//cylinders don't care about Z-Axis
mLODScaleBias.setVec(0.6f, 0.6f, 0.0f);
}
else if (path_type == LL_PCODE_PATH_CIRCLE)
{
mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
}
}
else if (path_type == LL_PCODE_PATH_CIRCLE)
{
mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
}
BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);
BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split);
@@ -2906,15 +2911,41 @@ F32 LLVolume::sculptGetSurfaceArea()
return area;
}
// create placeholder shape
void LLVolume::sculptGeneratePlaceholder()
// create empty placeholder shape
void LLVolume::sculptGenerateEmptyPlaceholder()
{
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
S32 line = 0;
for (S32 s = 0; s < sizeS; s++)
{
for (S32 t = 0; t < sizeT; t++)
{
S32 i = t + line;
LLVector4a& pt = mMesh[i];
F32* p = pt.getF32ptr();
p[0] = 0;
p[1] = 0;
p[2] = 0;
llassert(pt.isFinite3());
}
line += sizeT;
}
}
// create sphere placeholder shape
void LLVolume::sculptGenerateSpherePlaceholder()
{
S32 sizeS = mPathp->mPath.size();
S32 sizeT = mProfilep->mProfile.size();
S32 line = 0;
// for now, this is a sphere.
for (S32 s = 0; s < sizeS; s++)
{
for (S32 t = 0; t < sizeT; t++)
@@ -3123,7 +3154,7 @@ bool sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32
}
// sculpt replaces generate() for sculpted surfaces
void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level)
void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder)
{
U8 sculpt_type = mParams.getSculptType();
@@ -3187,13 +3218,22 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA)
{
data_is_empty = TRUE;
visible_placeholder = true;
}
}
}
if (data_is_empty)
{
sculptGeneratePlaceholder();
if (visible_placeholder)
{
// Object should be visible since there will be nothing else to display
sculptGenerateSpherePlaceholder();
}
else
{
sculptGenerateEmptyPlaceholder();
}
}
@@ -3723,10 +3763,46 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
continue;
}
if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) {
if (face.mTypeMask & (LLVolumeFace::CAP_MASK))
{
LLVector4a* v = (LLVector4a*)face.mPositions;
LLVector4a* n = (LLVector4a*)face.mNormals;
for (U32 j = 0; j < (U32)face.mNumIndices / 3; j++)
{
for (S32 k = 0; k < 3; k++)
{
S32 index = face.mEdge[j * 3 + k];
if (index == -1)
{
// silhouette edge, currently only cubes, so no other conditions
S32 v1 = face.mIndices[j * 3 + k];
S32 v2 = face.mIndices[j * 3 + ((k + 1) % 3)];
LLVector4a t;
mat.affineTransform(v[v1], t);
vertices.push_back(LLVector3(t[0], t[1], t[2]));
norm_mat.rotate(n[v1], t);
t.normalize3fast();
normals.push_back(LLVector3(t[0], t[1], t[2]));
mat.affineTransform(v[v2], t);
vertices.push_back(LLVector3(t[0], t[1], t[2]));
norm_mat.rotate(n[v2], t);
t.normalize3fast();
normals.push_back(LLVector3(t[0], t[1], t[2]));
}
}
}
}
else {
else
{
//==============================================
//DEBUG draw edge map instead of silhouette edge
@@ -4709,6 +4785,7 @@ LLVolumeFace::~LLVolumeFace()
{
ll_aligned_free_16(mExtents);
mExtents = NULL;
mCenter = NULL;
freeData();
}
@@ -5556,10 +5633,17 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
if (!partial_build)
{
resizeIndices(grid_size*grid_size*6);
if (!volume->isMeshAssetLoaded())
{
mEdge.resize(grid_size*grid_size * 6);
}
U16* out = mIndices;
S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
int cur_edge = 0;
for(S32 gx = 0;gx<grid_size;gx++)
{
@@ -5570,7 +5654,49 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
for(S32 i=5;i>=0;i--)
{
*out++ = ((gy*(grid_size+1))+gx+idxs[i]);
}
}
S32 edge_value = grid_size * 2 * gy + gx * 2;
if (gx > 0)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1; // Mark face to higlight it
}
if (gy < grid_size - 1)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
mEdge[cur_edge++] = edge_value;
if (gx < grid_size - 1)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
if (gy > 0)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
mEdge[cur_edge++] = edge_value;
}
else
{
@@ -5578,6 +5704,48 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
{
*out++ = ((gy*(grid_size+1))+gx+idxs[i]);
}
S32 edge_value = grid_size * 2 * gy + gx * 2;
if (gy > 0)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
if (gx < grid_size - 1)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
mEdge[cur_edge++] = edge_value;
if (gy < grid_size - 1)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
if (gx > 0)
{
mEdge[cur_edge++] = edge_value;
}
else
{
mEdge[cur_edge++] = -1;
}
mEdge[cur_edge++] = edge_value;
}
}
}
@@ -6056,6 +6224,9 @@ void LLVolumeFace::resizeVertices(S32 num_verts)
allocateTangents(0);
allocateVertices(num_verts);
mNumVertices = num_verts;
// Force update
mJointRiggingInfoTab.clear();
}
void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv)
@@ -6201,78 +6372,6 @@ void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v,
}
}
void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMatrix4& norm_mat_in)
{
U16 offset = mNumVertices;
S32 new_count = face.mNumVertices + mNumVertices;
if (new_count > 65536)
{
LL_ERRS() << "Cannot append face -- 16-bit overflow will occur." << LL_ENDL;
}
if (face.mNumVertices == 0)
{
LL_ERRS() << "Cannot append empty face." << LL_ENDL;
}
allocateVertices(new_count, true);
mNumVertices = new_count;
//get destination address of appended face
LLVector4a* dst_pos = mPositions+offset;
LLVector2* dst_tc = mTexCoords+offset;
LLVector4a* dst_norm = mNormals+offset;
//get source addresses of appended face
const LLVector4a* src_pos = face.mPositions;
const LLVector2* src_tc = face.mTexCoords;
const LLVector4a* src_norm = face.mNormals;
//load aligned matrices
LLMatrix4a mat, norm_mat;
mat.loadu(mat_in);
norm_mat.loadu(norm_mat_in);
for (U32 i = 0; i < (U32)face.mNumVertices; ++i)
{
//transform appended face position and store
mat.affineTransform(src_pos[i], dst_pos[i]);
//transform appended face normal and store
norm_mat.rotate(src_norm[i], dst_norm[i]);
dst_norm[i].normalize3fast();
//copy appended face texture coordinate
dst_tc[i] = src_tc[i];
if (offset == 0 && i == 0)
{ //initialize bounding box
mExtents[0] = mExtents[1] = dst_pos[i];
}
else
{
//stretch bounding box
update_min_max(mExtents[0], mExtents[1], dst_pos[i]);
}
}
new_count = mNumIndices + face.mNumIndices;
allocateIndices(mNumIndices + face.mNumIndices, true);
//get destination address into new index buffer
U16* dst_idx = mIndices+mNumIndices;
mNumIndices = new_count;
for (U32 i = 0; i < (U32)face.mNumIndices; ++i)
{ //copy indices, offsetting by old vertex count
dst_idx[i] = face.mIndices[i]+offset;
}
}
BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
{
BOOL flat = mTypeMask & FLAT_MASK;

View File

@@ -60,6 +60,7 @@ class LLVolumeTriangle;
#include "llpointer.h"
#include "llfile.h"
#include "llalignedarray.h"
#include "llrigginginfo.h"
//============================================================================
@@ -870,8 +871,6 @@ public:
BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
void createTangents();
void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform);
void resizeVertices(S32 num_verts);
void allocateTangents(S32 num_verts);
@@ -961,6 +960,10 @@ public:
mutable BOOL mWeightsScrubbed;
// Which joints are rigged to, and the bounding box of any rigged
// vertices per joint.
LLJointRiggingInfoTab mJointRiggingInfoTab;
LLOctreeNode<LLVolumeTriangle>* mOctree;
//whether or not face has been cache optimized
@@ -1059,7 +1062,7 @@ public:
U32 mFaceMask; // bit array of which faces exist in this volume
LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level, bool visible_placeholder);
void copyVolumeFaces(const LLVolume* volume);
void copyFacesTo(std::vector<LLVolumeFace> &faces) const;
void copyFacesFrom(const std::vector<LLVolumeFace> &faces);
@@ -1068,7 +1071,8 @@ public:
private:
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
F32 sculptGetSurfaceArea();
void sculptGeneratePlaceholder();
void sculptGenerateEmptyPlaceholder();
void sculptGenerateSpherePlaceholder();
void sculptCalcMeshResolution(U16 width, U16 height, U8 type, S32& s, S32& t);

View File

@@ -110,9 +110,9 @@ void LLModel::optimizeVolumeFaces()
{
for (U32 i = 0; i < (U32)getNumVolumeFaces(); ++i)
{
validate_face(mVolumeFaces[i]);
//validate_face(mVolumeFaces[i]);
mVolumeFaces[i].optimize();
validate_face(mVolumeFaces[i]);
//validate_face(mVolumeFaces[i]);
}
}
@@ -161,11 +161,11 @@ void LLModel::sortVolumeFacesByMaterialName()
mVolumeFaces = new_faces;
}
void LLModel::trimVolumeFacesToSize(S32 new_count, LLVolume::face_list_t* remainder)
void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remainder)
{
llassert(new_count <= LL_SCULPT_MESH_MAX_FACES);
if (new_count && (getNumVolumeFaces() > new_count))
if (new_count && ((U32)getNumVolumeFaces() > new_count))
{
// Copy out remaining volume faces for alternative handling, if provided
//
@@ -407,40 +407,6 @@ void LLModel::setVolumeFaceData(
LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size);
}
void LLModel::appendFaces(LLModel *model, LLMatrix4 &transform, LLMatrix4& norm_mat)
{
if (mVolumeFaces.empty())
{
setNumVolumeFaces(1);
}
LLVolumeFace& face = mVolumeFaces[mVolumeFaces.size()-1];
for (S32 i = 0; i < model->getNumFaces(); ++i)
{
face.appendFace(model->getVolumeFace(i), transform, norm_mat);
}
}
void LLModel::appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat)
{
S32 rindex = getNumVolumeFaces()-1;
if (rindex == -1 ||
mVolumeFaces[rindex].mNumVertices + src_face.mNumVertices >= 65536)
{ //empty or overflow will occur, append new face
LLVolumeFace cur_face;
cur_face.appendFace(src_face, mat, norm_mat);
addFace(cur_face);
mMaterialList.push_back(src_material);
}
else
{ //append to existing end face
mVolumeFaces.rbegin()->appendFace(src_face, mat, norm_mat);
}
}
void LLModel::addFace(const LLVolumeFace& face)
{
if (face.mNumVertices == 0)
@@ -523,9 +489,9 @@ void LLModel::generateNormals(F32 angle_cutoff)
}
//weld vertices in temporary face, respecting angle_cutoff (step 2)
validate_face(faceted);
//validate_face(faceted);
faceted.optimize(angle_cutoff);
validate_face(faceted);
//validate_face(faceted);
//generate normals for welded face based on new topology (step 3)
@@ -657,9 +623,9 @@ void LLModel::generateNormals(F32 angle_cutoff)
}
//remove redundant vertices from new face (step 6)
validate_face(new_face);
//validate_face(new_face);
new_face.optimize();
validate_face(new_face);
//validate_face(new_face);
mVolumeFaces[j] = new_face;
}
@@ -1043,12 +1009,14 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
{ //no exact match found, get closest point
const F32 epsilon = 1e-5f;
weight_map::iterator iter_up = mSkinWeights.lower_bound(pos);
weight_map::iterator iter_down = ++iter_up;
weight_map::iterator iter_down = iter_up;
if (iter_up != mSkinWeights.end())
{
iter_down = ++iter_up;
}
weight_map::iterator best = iter_up;
// iter == mSkinWeights.end()...
F32 min_dist = (iter_up->first - pos).magVec();
F32 min_dist = (iter->first - pos).magVec();
bool done = false;
while (!done)
@@ -1399,14 +1367,16 @@ bool LLModel::loadDecomposition(LLSD& header, std::istream& is)
LLMeshSkinInfo::LLMeshSkinInfo():
mPelvisOffset(0.0),
mLockScaleIfJointPosition(false),
mInvalidJointsScrubbed(false)
mInvalidJointsScrubbed(false),
mJointNumsInitialized(false)
{
}
LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin):
mPelvisOffset(0.0),
mLockScaleIfJointPosition(false),
mInvalidJointsScrubbed(false)
mInvalidJointsScrubbed(false),
mJointNumsInitialized(false)
{
fromLLSD(skin);
}

View File

@@ -57,6 +57,7 @@ public:
float mPelvisOffset;
bool mLockScaleIfJointPosition;
bool mInvalidJointsScrubbed;
bool mJointNumsInitialized;
};
class LLModel : public LLVolume
@@ -158,9 +159,6 @@ public:
EModelStatus getStatus() const {return mStatus;}
static std::string getStatusString(U32 status) ;
void appendFaces(LLModel* model, LLMatrix4& transform, LLMatrix4& normal_transform);
void appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat);
void setNumVolumeFaces(S32 count);
void setVolumeFaceData(
S32 f,
@@ -177,7 +175,7 @@ public:
void sortVolumeFacesByMaterialName();
void normalizeVolumeFaces();
void trimVolumeFacesToSize(S32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
void optimizeVolumeFaces();
void offsetMesh( const LLVector3& pivotPoint );
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);

View File

@@ -81,6 +81,7 @@ public:
GENERATING_VERTEX_BUFFERS,
GENERATING_LOD,
DONE,
WARNING_BIND_SHAPE_ORIENTATION,
ERROR_PARSING, //basically loading failed
ERROR_MATERIALS,
ERROR_PASSWORD_REQUIRED,

View File

@@ -175,7 +175,7 @@ LLPrimitive::~LLPrimitive()
{
clearTextureList();
// Cleanup handled by volume manager
if (mVolumep)
if (mVolumep && sVolumeManager)
{
sVolumeManager->unrefVolume(mVolumep);
}
@@ -586,7 +586,7 @@ U8 LLPrimitive::pCodeToLegacy(const LLPCode pcode)
// static
// Don't crash or llerrs here! This function is used for debug strings.
// Don't crash or LL_ERRS() here! This function is used for debug strings.
std::string LLPrimitive::pCodeToString(const LLPCode pcode)
{
std::string pcode_string;
@@ -729,6 +729,16 @@ S32 face_index_from_id(LLFaceID face_ID, const std::vector<LLProfile::Face>& fac
BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume)
{
if (NO_LOD == detail)
{
// build the new object
setChanged(GEOMETRY);
sVolumeManager->unrefVolume(mVolumep);
mVolumep = new LLVolume(volume_params, 1, TRUE, TRUE);
setNumTEs(mVolumep->getNumFaces());
return FALSE;
}
LLVolume *volumep;
if (unique_volume)
{
@@ -1577,6 +1587,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)
return (size == 17);
case PARAMS_LIGHT_IMAGE:
return (size == 28);
case PARAMS_EXTENDED_MESH:
return (size == 4);
}
return FALSE;
@@ -2004,3 +2016,67 @@ bool LLLightImageParams::fromLLSD(LLSD& sd)
return false;
}
//============================================================================
LLExtendedMeshParams::LLExtendedMeshParams()
{
mType = PARAMS_EXTENDED_MESH;
mFlags = 0;
}
BOOL LLExtendedMeshParams::pack(LLDataPacker &dp) const
{
dp.packU32(mFlags, "flags");
return TRUE;
}
BOOL LLExtendedMeshParams::unpack(LLDataPacker &dp)
{
dp.unpackU32(mFlags, "flags");
return TRUE;
}
bool LLExtendedMeshParams::operator==(const LLNetworkData& data) const
{
if (data.mType != PARAMS_EXTENDED_MESH)
{
return false;
}
const LLExtendedMeshParams *param = (const LLExtendedMeshParams*)&data;
if ( (param->mFlags != mFlags) )
{
return false;
}
return true;
}
void LLExtendedMeshParams::copy(const LLNetworkData& data)
{
const LLExtendedMeshParams *param = (LLExtendedMeshParams*)&data;
mFlags = param->mFlags;
}
LLSD LLExtendedMeshParams::asLLSD() const
{
LLSD sd;
sd["flags"] = LLSD::Integer(mFlags);
return sd;
}
bool LLExtendedMeshParams::fromLLSD(LLSD& sd)
{
if (sd.has("flags"))
{
setFlags( sd["flags"].asInteger());
return true;
}
return false;
}

View File

@@ -106,6 +106,7 @@ public:
PARAMS_LIGHT_IMAGE = 0x40,
PARAMS_RESERVED = 0x50, // Used on server-side
PARAMS_MESH = 0x60,
PARAMS_EXTENDED_MESH = 0x70,
};
public:
@@ -288,6 +289,27 @@ public:
};
class LLExtendedMeshParams : public LLNetworkData
{
protected:
U32 mFlags;
public:
static const U32 ANIMATED_MESH_ENABLED_FLAG = 0x1 << 0;
LLExtendedMeshParams();
/*virtual*/ BOOL pack(LLDataPacker &dp) const;
/*virtual*/ BOOL unpack(LLDataPacker &dp);
/*virtual*/ bool operator==(const LLNetworkData& data) const;
/*virtual*/ void copy(const LLNetworkData& data);
LLSD asLLSD() const;
operator LLSD() const { return asLLSD(); }
bool fromLLSD(LLSD& sd);
void setFlags(const U32& flags) { mFlags = flags; }
U32 getFlags() const { return mFlags; }
};
// This code is not naming-standards compliant. Leaving it like this for
// now to make the connection to code in
@@ -308,9 +330,9 @@ struct LLTEContents
S16 image_rot[MAX_TES];
U8 bump[MAX_TES];
U8 media_flags[MAX_TES];
U8 glow[MAX_TES];
U8 glow[MAX_TES];
LLMaterialID material_ids[MAX_TES];
static const U32 MAX_TE_BUFFER = 4096;
U8 packed_buffer[MAX_TE_BUFFER];
@@ -483,6 +505,11 @@ protected:
U32 mMiscFlags; // home for misc bools
static LLVolumeMgr* sVolumeManager;
enum
{
NO_LOD = -1
};
};
inline BOOL LLPrimitive::isAvatar() const

View File

@@ -1554,6 +1554,7 @@ if (WINDOWS)
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
generate_viewer_version
stage_third_party_libs
llcommon
${COPY_INPUT_DEPENDENCIES}
COMMENT "Performing viewer_manifest copy"
)

View File

@@ -653,7 +653,7 @@ void LocalAssetBrowser::PerformSculptUpdates(LocalBitmap& unit)
{
LLImageRaw* rawimage = gTextureList.findImage(unit.getID())->getCachedRawImage();
aobj.object->getVolume()->sculpt(rawimage->getWidth(), rawimage->getHeight(), rawimage->getComponents(), rawimage->getData(), 0);
aobj.object->getVolume()->sculpt(rawimage->getWidth(), rawimage->getHeight(), rawimage->getComponents(), rawimage->getData(), 0, true);
unit.volume_dirty = false;
}

View File

@@ -1403,6 +1403,16 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
}
//LL_INFOS() << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << LL_ENDL;
// Let getGeometryVolume know if a texture matrix is in play
if (face->mTextureMatrix)
{
face->setState(LLFace::TEXTURE_ANIM);
}
else
{
face->clearState(LLFace::TEXTURE_ANIM);
}
face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_inv_trans, offset, true);
buffer->flush();
@@ -1410,16 +1420,24 @@ void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
{
LLVector4a* weight = vol_face.mWeights;
if (!weight)
LLVector4a* weights = vol_face.mWeights;
if (!weights)
{
return;
}
// FIXME ugly const cast
LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
LLDrawable* drawable = face->getDrawable();
U32 data_mask = face->getRiggedVertexBufferDataMask();
if (!vol_face.mWeightsScrubbed)
{
LLSkinningUtil::scrubSkinWeights(weights, vol_face.mNumVertices, skin);
vol_face.mWeightsScrubbed = TRUE;
}
if (buffer.isNull() ||
buffer->getTypeMask() != data_mask ||
@@ -1452,7 +1470,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime())
{
avatar->updateSoftwareSkinnedVertices(skin, weight, vol_face, buffer);
avatar->updateSoftwareSkinnedVertices(skin, weights, vol_face, buffer);
}
}

View File

@@ -352,7 +352,7 @@ BOOL LLFloaterBvhPreview::postBuild()
// pass animation data through memory buffer
loaderp->serialize(dp);
dp.reset();
success = motionp && motionp->deserialize(dp);
success = motionp && motionp->deserialize(dp, mMotionID);
}
else
{
@@ -411,7 +411,7 @@ BOOL LLFloaterBvhPreview::postBuild()
motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID);
LLDataPackerBinaryBuffer dp((U8*)file_buffer, file_size);
dp.reset();
success = motionp && motionp->deserialize(dp);
success = motionp && motionp->deserialize(dp, mMotionID);
}
raw_animatn.close();

View File

@@ -849,7 +849,7 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
if (imagep)
{
mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0);
mVolume->sculpt(imagep->getWidth(), imagep->getHeight(), imagep->getComponents(), imagep->getData(), 0, false);
}
const LLVolumeFace &vf = mVolume->getVolumeFace(0);

View File

@@ -672,6 +672,11 @@ void LLFloaterModelPreview::draw()
childSetTextArg("status", "[STATUS]", getString("status_parse_error"));
toggleCalculateButton(false);
}
else
if (mModelPreview->getLoadState() == LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION)
{
childSetTextArg("status", "[STATUS]", getString("status_bind_shape_orientation"));
}
else
{
childSetTextArg("status", "[STATUS]", getString("status_idle"));
@@ -1588,6 +1593,19 @@ void LLModelPreview::rebuildUploadData()
mFMP->childDisable( "calculate_btn" );
}
}
LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) mFMP;
bool upload_skinweights = fmp && fmp->childGetValue("upload_skin").asBoolean();
if (upload_skinweights && high_lod_model->mSkinInfo.mJointNames.size() > 0)
{
LLQuaternion bind_rot = LLSkinningUtil::getUnscaledQuaternion(high_lod_model->mSkinInfo.mBindShapeMatrix);
LLQuaternion identity;
if (!bind_rot.isEqualEps(identity,0.01))
{
LL_WARNS() << "non-identity bind shape rot. mat is " << high_lod_model->mSkinInfo.mBindShapeMatrix
<< " bind_rot " << bind_rot << LL_ENDL;
setLoadState( LLModelLoader::WARNING_BIND_SHAPE_ORIENTATION );
}
}
}
instance.mTransform = mat;
mUploadData.push_back(instance);

View File

@@ -37,20 +37,17 @@ void LLSkinningUtil::initClass()
{
}
// static
U32 LLSkinningUtil::getMaxJointCount()
{
U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT;
return result;
}
// static
U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin)
{
return llmin((U32)getMaxJointCount(), (U32)skin->mJointNames.size());
}
// static
void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin)
{
if (skin->mInvalidJointsScrubbed)
@@ -64,8 +61,10 @@ void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin
// needed for handling of any legacy bad data.
if (!avatar->getJoint(skin->mJointNames[j]))
{
LL_DEBUGS("Avatar") << "Mesh rigged to invalid joint" << skin->mJointNames[j] << LL_ENDL;
LL_DEBUGS("Avatar") << avatar->getFullname() << " mesh rigged to invalid joint " << skin->mJointNames[j] << LL_ENDL;
LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " mesh rigged to invalid joint" << skin->mJointNames[j] << LL_ENDL;
skin->mJointNames[j] = "mPelvis";
skin->mJointNumsInitialized = false; // force update after names change.
}
}
skin->mInvalidJointsScrubbed = true;
@@ -77,69 +76,43 @@ void LLSkinningUtil::initSkinningMatrixPalette(
S32 count,
const LLMeshSkinInfo* skin,
LLVOAvatar *avatar,
bool relative_to_avatar)
bool relative_to_avatar)
{
for (U32 j = 0; j < (U32)count; ++j)
{
LLJoint *joint = NULL;
if( skin->mJointNums[j] <= -50 )
{
// Give up silently.
mat[j].loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
continue;
}
else if (skin->mJointNums[j] < 0 )
{
joint = avatar->getJoint(skin->mJointNames[j]);
if (!joint)
{
LL_WARNS_ONCE("Avatar") << "Rigged to invalid joint name " << skin->mJointNames[j] << " Using 'root' fallback." << LL_ENDL;
joint = avatar->getJoint("mRoot");
}
if (joint)
{
//LL_INFOS() << "Found joint " << skin->mJointNames[j] << " Id = " << joint->getJointNum() << LL_ENDL;
skin->mJointNums[j] = joint->getJointNum();
}
else
{
--skin->mJointNums[j];
}
}
else
{
joint = avatar->getJoint(skin->mJointNums[j]);
if (!joint)
{
LL_WARNS_ONCE() << "Joint not found: " << skin->mJointNames[j] << " Id = " << skin->mJointNums[j] << LL_ENDL;
}
}
if (joint)
{
LLMatrix4a bind;
bind.loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
if (relative_to_avatar)
{
LLMatrix4a trans = joint->getWorldMatrix();
trans.translate_affine(avatar->getPosition() * -1.f);
mat[j].setMul(trans, bind);
}
else
mat[j].setMul(joint->getWorldMatrix(), bind);
}
else
{
mat[j].loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
// This shouldn't happen - in mesh upload, skinned
// rendering should be disabled unless all joints are
// valid. In other cases of skinned rendering, invalid
// joints should already have been removed during scrubInvalidJoints().
LL_WARNS_ONCE("Avatar") << "Rigged to invalid joint name " << skin->mJointNames[j] << LL_ENDL;
}
}
initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
for (U32 j = 0; j < (U32)count; ++j)
{
LLJoint *joint = avatar->getJoint(skin->mJointNums[j]);
if (joint)
{
LLMatrix4a bind;
bind.loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
if (relative_to_avatar)
{
LLMatrix4a trans = joint->getWorldMatrix();
trans.translate_affine(avatar->getPosition() * -1.f);
mat[j].setMul(trans, bind);
}
else
mat[j].setMul(joint->getWorldMatrix(), bind);
}
else
{
mat[j].loadu((F32*)skin->mInvBindMatrix[j].mMatrix);
// This shouldn't happen - in mesh upload, skinned
// rendering should be disabled unless all joints are
// valid. In other cases of skinned rendering, invalid
// joints should already have been removed during scrubInvalidJoints().
LL_WARNS_ONCE("Avatar") << avatar->getFullname()
<< " rigged to invalid joint name " << skin->mJointNames[j]
<< " num " << skin->mJointNums[j] << LL_ENDL;
LL_WARNS_ONCE("Avatar") << avatar->getFullname()
<< " avatar build state: isBuilt() " << avatar->isBuilt()
<< " mInitFlags " << avatar->mInitFlags << LL_ENDL;
}
}
}
// static
void LLSkinningUtil::checkSkinWeights(const LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
{
#ifndef LL_RELEASE_FOR_DOWNLOAD
@@ -179,7 +152,6 @@ void LLSkinningUtil::scrubSkinWeights(LLVector4a* weights, U32 num_vertices, con
checkSkinWeights(weights, num_vertices, skin);
}
// static
void LLSkinningUtil::getPerVertexSkinMatrix(
const F32* weights,
LLMatrix4a* mat,
@@ -231,3 +203,62 @@ void LLSkinningUtil::getPerVertexSkinMatrix(
llassert(valid_weights);
}
void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar)
{
if (!skin->mJointNumsInitialized)
{
for (U32 j = 0; j < skin->mJointNames.size(); ++j)
{
LLJoint *joint = NULL;
if (skin->mJointNums[j] == -1)
{
joint = avatar->getJoint(skin->mJointNames[j]);
if (joint)
{
skin->mJointNums[j] = joint->getJointNum();
if (skin->mJointNums[j] < 0)
{
LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " joint has unusual number " << skin->mJointNames[j] << ": " << skin->mJointNums[j] << LL_ENDL;
LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL;
}
}
else
{
LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " unable to find joint " << skin->mJointNames[j] << LL_ENDL;
LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL;
#if 0
dump_avatar_and_skin_state("initJointNums joint not found", avatar, skin);
#endif
}
}
}
skin->mJointNumsInitialized = true;
}
}
// This is used for extracting rotation from a bind shape matrix that
// already has scales baked in
LLQuaternion LLSkinningUtil::getUnscaledQuaternion(const LLMatrix4& mat4)
{
LLMatrix3 bind_mat = mat4.getMat3();
for (auto i = 0; i < 3; i++)
{
F32 len = 0.0f;
for (auto j = 0; j < 3; j++)
{
len += bind_mat.mMatrix[i][j] * bind_mat.mMatrix[i][j];
}
if (len > 0.0f)
{
len = sqrt(len);
for (auto j = 0; j < 3; j++)
{
bind_mat.mMatrix[i][j] /= len;
}
}
}
bind_mat.invert();
LLQuaternion bind_rot = bind_mat.quaternion();
bind_rot.normalize();
return bind_rot;
}

View File

@@ -31,17 +31,18 @@ class LLVOAvatar;
class LLMeshSkinInfo;
class LLMatrix4a;
class LLSkinningUtil
namespace LLSkinningUtil
{
public:
static void initClass();
static U32 getMaxJointCount();
static U32 getMeshJointCount(const LLMeshSkinInfo *skin);
static void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin);
static void initSkinningMatrixPalette(LLMatrix4a* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar, bool relative_to_avatar = false);
static void checkSkinWeights(const LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
static void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
static void getPerVertexSkinMatrix(const F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints);
void initClass();
U32 getMaxJointCount();
U32 getMeshJointCount(const LLMeshSkinInfo *skin);
void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin);
void initSkinningMatrixPalette(LLMatrix4a* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar, bool relative_to_avatar = false);
void checkSkinWeights(const LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
void getPerVertexSkinMatrix(const F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints);
void initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar);
LLQuaternion getUnscaledQuaternion(const LLMatrix4& mat4);
};
#endif

View File

@@ -1193,7 +1193,7 @@ void LLVOVolume::sculpt()
sculpt_data = raw_image->getData();
}
getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level);
getVolume()->sculpt(sculpt_width, sculpt_height, sculpt_components, sculpt_data, discard_level, mSculptTexture->isMissingAsset());
//notify rebuild any other VOVolumes that reference this sculpty volume
for (S32 i = 0; i < mSculptTexture->getNumVolumes(); ++i)
@@ -4111,6 +4111,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin);
LLSkinningUtil::initSkinningMatrixPalette(mat, maxJoints, skin, avatar, true);
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
LLVector4a av_pos;
av_pos.load3(avatar->getPosition().mV);
@@ -4127,8 +4130,6 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
continue;
}
LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin);
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
LLVector4a* pos = dst_face.mPositions;
@@ -4143,11 +4144,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints);
LLVector4a& v = vol_face.mPositions[j];
LLVector4a t;
LLVector4a dst;
bind_shape_matrix.affineTransform(v, t);
final_mat.affineTransform(t, dst);
pos[j] = dst;
final_mat.mul(bind_shape_matrix);
final_mat.affineTransform(v, pos[j]);
pos[j].add(av_pos);
}
@@ -6166,7 +6165,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac
if (material_pass)
{
U32 pass[] =
static const U32 pass[] =
{
LLRenderPass::PASS_MATERIAL,
LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA,