V3 mesh, texture, and hover merge.
This commit is contained in:
@@ -576,8 +576,6 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
|
|||||||
info->mRot.mV[VZ], LLQuaternion::XYZ));
|
info->mRot.mV[VZ], LLQuaternion::XYZ));
|
||||||
joint->setScale(info->mScale);
|
joint->setScale(info->mScale);
|
||||||
|
|
||||||
joint->setDefaultFromCurrentXform();
|
|
||||||
|
|
||||||
if (info->mIsJoint)
|
if (info->mIsJoint)
|
||||||
{
|
{
|
||||||
joint->setSkinOffset( info->mPivot );
|
joint->setSkinOffset( info->mPivot );
|
||||||
@@ -677,6 +675,42 @@ void LLAvatarAppearance::clearSkeleton()
|
|||||||
mSkeleton.clear();
|
mSkeleton.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// addPelvisFixup
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void LLAvatarAppearance::addPelvisFixup( F32 fixup, const LLUUID& mesh_id )
|
||||||
|
{
|
||||||
|
LLVector3 pos(0.0,0.0,fixup);
|
||||||
|
mPelvisFixups.add(mesh_id,pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// addPelvisFixup
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
void LLAvatarAppearance::removePelvisFixup( const LLUUID& mesh_id )
|
||||||
|
{
|
||||||
|
mPelvisFixups.remove(mesh_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// hasPelvisFixup
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
bool LLAvatarAppearance::hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const
|
||||||
|
{
|
||||||
|
LLVector3 pos;
|
||||||
|
if (mPelvisFixups.findActiveOverride(mesh_id,pos))
|
||||||
|
{
|
||||||
|
fixup = pos[2];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLAvatarAppearance::hasPelvisFixup( F32& fixup ) const
|
||||||
|
{
|
||||||
|
LLUUID mesh_id;
|
||||||
|
return hasPelvisFixup( fixup, mesh_id );
|
||||||
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// LLAvatarAppearance::buildCharacter()
|
// LLAvatarAppearance::buildCharacter()
|
||||||
// Deferred initialization and rebuild of the avatar.
|
// Deferred initialization and rebuild of the avatar.
|
||||||
|
|||||||
@@ -159,11 +159,17 @@ protected:
|
|||||||
BOOL mIsBuilt; // state of deferred character building
|
BOOL mIsBuilt; // state of deferred character building
|
||||||
typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
|
typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
|
||||||
avatar_joint_list_t mSkeleton;
|
avatar_joint_list_t mSkeleton;
|
||||||
|
LLPosOverrideMap mPelvisFixups;
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// Pelvis height adjustment members.
|
// Pelvis height adjustment members.
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
public:
|
public:
|
||||||
|
void addPelvisFixup( F32 fixup, const LLUUID& mesh_id );
|
||||||
|
void removePelvisFixup( const LLUUID& mesh_id );
|
||||||
|
bool hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const;
|
||||||
|
bool hasPelvisFixup( F32& fixup ) const;
|
||||||
|
|
||||||
LLVector3 mBodySize;
|
LLVector3 mBodySize;
|
||||||
LLVector3 mAvatarOffset;
|
LLVector3 mAvatarOffset;
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -85,8 +85,6 @@ LLSkinJoint::~LLSkinJoint()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void LLSkinJoint::setupSkinJoint( LLJoint *joint)
|
void LLSkinJoint::setupSkinJoint( LLJoint *joint)
|
||||||
{
|
{
|
||||||
mRootToJointSkinOffset.clearVec();
|
|
||||||
mRootToParentJointSkinOffset.clearVec();
|
|
||||||
|
|
||||||
// find the named joint
|
// find the named joint
|
||||||
if (!(mJoint = joint))
|
if (!(mJoint = joint))
|
||||||
@@ -96,6 +94,9 @@ void LLSkinJoint::setupSkinJoint( LLJoint *joint)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute the inverse root skin matrix
|
// compute the inverse root skin matrix
|
||||||
|
mRootToJointSkinOffset.clearVec();
|
||||||
|
mRootToParentJointSkinOffset.clearVec();
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
mRootToJointSkinOffset -= joint->getSkinOffset();
|
mRootToJointSkinOffset -= joint->getSkinOffset();
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ include_directories(
|
|||||||
${LLVFS_INCLUDE_DIRS}
|
${LLVFS_INCLUDE_DIRS}
|
||||||
${LLXML_INCLUDE_DIRS}
|
${LLXML_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
include_directories(SYSTEM
|
||||||
|
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||||
|
${LLXML_SYSTEM_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
set(llcharacter_SOURCE_FILES
|
set(llcharacter_SOURCE_FILES
|
||||||
llanimationstates.cpp
|
llanimationstates.cpp
|
||||||
|
|||||||
@@ -36,6 +36,63 @@
|
|||||||
S32 LLJoint::sNumUpdates = 0;
|
S32 LLJoint::sNumUpdates = 0;
|
||||||
S32 LLJoint::sNumTouches = 0;
|
S32 LLJoint::sNumTouches = 0;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
bool attachment_map_iter_compare_key(const T& a, const T& b)
|
||||||
|
{
|
||||||
|
return a.first < b.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLPosOverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const
|
||||||
|
{
|
||||||
|
pos = LLVector3(0,0,0);
|
||||||
|
mesh_id = LLUUID();
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
map_type::const_iterator it = std::max_element(m_map.begin(),
|
||||||
|
m_map.end(),
|
||||||
|
attachment_map_iter_compare_key<map_type::value_type>);
|
||||||
|
if (it != m_map.end())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
pos = it->second;
|
||||||
|
mesh_id = it->first;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLPosOverrideMap::showJointPosOverrides( std::ostringstream& os ) const
|
||||||
|
{
|
||||||
|
map_type::const_iterator max_it = std::max_element(m_map.begin(),
|
||||||
|
m_map.end(),
|
||||||
|
attachment_map_iter_compare_key<map_type::value_type>);
|
||||||
|
for (map_type::const_iterator it = m_map.begin();
|
||||||
|
it != m_map.end(); ++it)
|
||||||
|
{
|
||||||
|
const LLVector3& pos = it->second;
|
||||||
|
os << " " << "[" << it->first <<": " << pos << "]" << ((it==max_it) ? "*" : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 LLPosOverrideMap::count() const
|
||||||
|
{
|
||||||
|
return m_map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLPosOverrideMap::add(const LLUUID& mesh_id, const LLVector3& pos)
|
||||||
|
{
|
||||||
|
m_map[mesh_id] = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLPosOverrideMap::remove(const LLUUID& mesh_id)
|
||||||
|
{
|
||||||
|
U32 remove_count = m_map.erase(mesh_id);
|
||||||
|
return (remove_count > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLPosOverrideMap::clear()
|
||||||
|
{
|
||||||
|
m_map.clear();
|
||||||
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// LLJoint()
|
// LLJoint()
|
||||||
// Class Constructor
|
// Class Constructor
|
||||||
@@ -57,7 +114,6 @@ LLJoint::LLJoint() :
|
|||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
touch();
|
touch();
|
||||||
mResetAfterRestoreOldXform = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLJoint::LLJoint(S32 joint_num) :
|
LLJoint::LLJoint(S32 joint_num) :
|
||||||
@@ -65,7 +121,6 @@ LLJoint::LLJoint(S32 joint_num) :
|
|||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
touch();
|
touch();
|
||||||
mResetAfterRestoreOldXform = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -233,54 +288,120 @@ const LLVector3& LLJoint::getPosition()
|
|||||||
return mXform.getPosition();
|
return mXform.getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool do_debug_joint(const std::string& name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// setPosition()
|
// setPosition()
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
void LLJoint::setPosition( const LLVector3& pos )
|
void LLJoint::setPosition( const LLVector3& pos )
|
||||||
{
|
{
|
||||||
// if (mXform.getPosition() != pos)
|
if (pos != getPosition())
|
||||||
{
|
{
|
||||||
mXform.setPosition(pos);
|
if (do_debug_joint(getName()))
|
||||||
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
{
|
||||||
|
LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mXform.setPosition(pos);
|
||||||
|
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showJointPosOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info )
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os << joint.m_posBeforeOverrides;
|
||||||
|
joint.m_attachmentOverrides.showJointPosOverrides(os);
|
||||||
|
LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// addAttachmentPosOverride()
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info )
|
||||||
|
{
|
||||||
|
if (mesh_id.isNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!m_attachmentOverrides.count())
|
||||||
|
{
|
||||||
|
if (do_debug_joint(getName()))
|
||||||
|
{
|
||||||
|
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_posBeforeOverrides " << getPosition() << LL_ENDL;
|
||||||
|
}
|
||||||
|
m_posBeforeOverrides = getPosition();
|
||||||
|
}
|
||||||
|
m_attachmentOverrides.add(mesh_id,pos);
|
||||||
|
if (do_debug_joint(getName()))
|
||||||
|
{
|
||||||
|
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentPosOverride for mesh " << mesh_id << " pos " << pos << LL_ENDL;
|
||||||
|
}
|
||||||
|
updatePos(av_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// removeAttachmentPosOverride()
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info )
|
||||||
|
{
|
||||||
|
if (mesh_id.isNull())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_attachmentOverrides.remove(mesh_id))
|
||||||
|
{
|
||||||
|
if (do_debug_joint(getName()))
|
||||||
|
{
|
||||||
|
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
|
||||||
|
<< " removeAttachmentPosOverride for " << mesh_id << LL_ENDL;
|
||||||
|
showJointPosOverrides(*this, "remove", av_info);
|
||||||
|
}
|
||||||
|
updatePos(av_info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// setPosition()
|
// hasAttachmentPosOverride()
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
void LLJoint::setDefaultFromCurrentXform( void )
|
bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const
|
||||||
{
|
{
|
||||||
mDefaultXform = mXform;
|
return m_attachmentOverrides.findActiveOverride(mesh_id,pos);
|
||||||
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// storeCurrentXform()
|
// clearAttachmentPosOverrides()
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
void LLJoint::storeCurrentXform( const LLVector3& pos )
|
void LLJoint::clearAttachmentPosOverrides()
|
||||||
{
|
{
|
||||||
mOldXform = mXform;
|
if (m_attachmentOverrides.count())
|
||||||
mResetAfterRestoreOldXform = true;
|
{
|
||||||
setPosition( pos );
|
m_attachmentOverrides.clear();
|
||||||
|
setPosition(m_posBeforeOverrides);
|
||||||
|
setId( LLUUID::null );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// restoreOldXform()
|
// updatePos()
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
void LLJoint::restoreOldXform( void )
|
void LLJoint::updatePos(const std::string& av_info)
|
||||||
{
|
{
|
||||||
mResetAfterRestoreOldXform = false;
|
LLVector3 pos, found_pos;
|
||||||
mXform = mOldXform;
|
LLUUID mesh_id;
|
||||||
}
|
if (m_attachmentOverrides.findActiveOverride(mesh_id,found_pos))
|
||||||
//--------------------------------------------------------------------
|
{
|
||||||
// restoreOldXform()
|
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL;
|
||||||
//--------------------------------------------------------------------
|
pos = found_pos;
|
||||||
void LLJoint::restoreToDefaultXform( void )
|
}
|
||||||
{
|
else
|
||||||
mXform = mDefaultXform;
|
{
|
||||||
setPosition( mXform.getPosition() );
|
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL;
|
||||||
|
pos = m_posBeforeOverrides;
|
||||||
|
}
|
||||||
|
setPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|||||||
@@ -46,6 +46,20 @@ const U32 LL_FACE_JOINT_NUM = 30;
|
|||||||
const S32 LL_CHARACTER_MAX_PRIORITY = 7;
|
const S32 LL_CHARACTER_MAX_PRIORITY = 7;
|
||||||
const F32 LL_MAX_PELVIS_OFFSET = 5.f;
|
const F32 LL_MAX_PELVIS_OFFSET = 5.f;
|
||||||
|
|
||||||
|
class LLPosOverrideMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLPosOverrideMap() {}
|
||||||
|
bool findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const;
|
||||||
|
void showJointPosOverrides(std::ostringstream& os) const;
|
||||||
|
U32 count() const;
|
||||||
|
void add(const LLUUID& mesh_id, const LLVector3& pos);
|
||||||
|
bool remove(const LLUUID& mesh_id);
|
||||||
|
void clear();
|
||||||
|
private:
|
||||||
|
typedef std::map<LLUUID,LLVector3> map_type;
|
||||||
|
map_type m_map;
|
||||||
|
};
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// class LLJoint
|
// class LLJoint
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -79,8 +93,6 @@ protected:
|
|||||||
|
|
||||||
// explicit transformation members
|
// explicit transformation members
|
||||||
LLXformMatrix mXform;
|
LLXformMatrix mXform;
|
||||||
LLXformMatrix mOldXform;
|
|
||||||
LLXformMatrix mDefaultXform;
|
|
||||||
|
|
||||||
LLUUID mId;
|
LLUUID mId;
|
||||||
|
|
||||||
@@ -88,8 +100,6 @@ public:
|
|||||||
U32 mDirtyFlags;
|
U32 mDirtyFlags;
|
||||||
BOOL mUpdateXform;
|
BOOL mUpdateXform;
|
||||||
|
|
||||||
BOOL mResetAfterRestoreOldXform;
|
|
||||||
|
|
||||||
// describes the skin binding pose
|
// describes the skin binding pose
|
||||||
LLVector3 mSkinOffset;
|
LLVector3 mSkinOffset;
|
||||||
|
|
||||||
@@ -103,6 +113,11 @@ public:
|
|||||||
static S32 sNumTouches;
|
static S32 sNumTouches;
|
||||||
static S32 sNumUpdates;
|
static S32 sNumUpdates;
|
||||||
|
|
||||||
|
LLPosOverrideMap m_attachmentOverrides;
|
||||||
|
LLVector3 m_posBeforeOverrides;
|
||||||
|
|
||||||
|
void updatePos(const std::string& av_info);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LLJoint();
|
LLJoint();
|
||||||
LLJoint(S32 joint_num);
|
LLJoint(S32 joint_num);
|
||||||
@@ -183,22 +198,17 @@ public:
|
|||||||
virtual BOOL isAnimatable() const { return TRUE; }
|
virtual BOOL isAnimatable() const { return TRUE; }
|
||||||
|
|
||||||
S32 getJointNum() const { return mJointNum; }
|
S32 getJointNum() const { return mJointNum; }
|
||||||
|
|
||||||
void restoreOldXform( void );
|
void addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info );
|
||||||
void restoreToDefaultXform( void );
|
void removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info );
|
||||||
void setDefaultFromCurrentXform( void );
|
bool hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const;
|
||||||
void storeCurrentXform( const LLVector3& pos );
|
void clearAttachmentPosOverrides();
|
||||||
|
|
||||||
//Accessor for the joint id
|
//Accessor for the joint id
|
||||||
LLUUID getId( void ) { return mId; }
|
LLUUID getId( void ) { return mId; }
|
||||||
//Setter for the joints id
|
//Setter for the joints id
|
||||||
void setId( const LLUUID& id ) { mId = id;}
|
void setId( const LLUUID& id ) { mId = id;}
|
||||||
|
|
||||||
//If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it
|
|
||||||
const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
|
|
||||||
//Setter for joint reset flag
|
|
||||||
void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; }
|
|
||||||
|
|
||||||
// <edit>
|
// <edit>
|
||||||
std::string exportString(U32 tabs = 0);
|
std::string exportString(U32 tabs = 0);
|
||||||
// </edit>
|
// </edit>
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ set(llcommon_SOURCE_FILES
|
|||||||
llassettype.cpp
|
llassettype.cpp
|
||||||
llbase32.cpp
|
llbase32.cpp
|
||||||
llbase64.cpp
|
llbase64.cpp
|
||||||
|
llcallbacklist.cpp
|
||||||
llcommon.cpp
|
llcommon.cpp
|
||||||
llcommonutils.cpp
|
llcommonutils.cpp
|
||||||
llcoros.cpp
|
llcoros.cpp
|
||||||
@@ -138,6 +139,7 @@ set(llcommon_HEADER_FILES
|
|||||||
llbase32.h
|
llbase32.h
|
||||||
llbase64.h
|
llbase64.h
|
||||||
llboost.h
|
llboost.h
|
||||||
|
llcallbacklist.h
|
||||||
llchat.h
|
llchat.h
|
||||||
llclickaction.h
|
llclickaction.h
|
||||||
llcommon.h
|
llcommon.h
|
||||||
|
|||||||
230
indra/llcommon/llcallbacklist.cpp
Normal file
230
indra/llcommon/llcallbacklist.cpp
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/**
|
||||||
|
* @file llcallbacklist.cpp
|
||||||
|
* @brief A simple list of callback functions to call.
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2010, Linden Research, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 of the License only.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "llcallbacklist.h"
|
||||||
|
#include "lleventtimer.h"
|
||||||
|
#include "llerrorlegacy.h"
|
||||||
|
|
||||||
|
// Globals
|
||||||
|
//
|
||||||
|
LLCallbackList gIdleCallbacks;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Member functions
|
||||||
|
//
|
||||||
|
|
||||||
|
LLCallbackList::LLCallbackList()
|
||||||
|
{
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
LLCallbackList::~LLCallbackList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LLCallbackList::addFunction( callback_t func, void *data)
|
||||||
|
{
|
||||||
|
if (!func)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only add one callback per func/data pair
|
||||||
|
//
|
||||||
|
if (containsFunction(func))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback_pair_t t(func, data);
|
||||||
|
mCallbackList.push_back(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLCallbackList::containsFunction( callback_t func, void *data)
|
||||||
|
{
|
||||||
|
callback_pair_t t(func, data);
|
||||||
|
callback_list_t::iterator iter = find(func,data);
|
||||||
|
if (iter != mCallbackList.end())
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LLCallbackList::deleteFunction( callback_t func, void *data)
|
||||||
|
{
|
||||||
|
callback_list_t::iterator iter = find(func,data);
|
||||||
|
if (iter != mCallbackList.end())
|
||||||
|
{
|
||||||
|
mCallbackList.erase(iter);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
LLCallbackList::callback_list_t::iterator
|
||||||
|
LLCallbackList::find(callback_t func, void *data)
|
||||||
|
{
|
||||||
|
callback_pair_t t(func, data);
|
||||||
|
return std::find(mCallbackList.begin(), mCallbackList.end(), t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLCallbackList::deleteAllFunctions()
|
||||||
|
{
|
||||||
|
mCallbackList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LLCallbackList::callFunctions()
|
||||||
|
{
|
||||||
|
for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); )
|
||||||
|
{
|
||||||
|
callback_list_t::iterator curiter = iter++;
|
||||||
|
curiter->first(curiter->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shim class to allow arbitrary boost::bind
|
||||||
|
// expressions to be run as one-time idle callbacks.
|
||||||
|
class OnIdleCallbackOneTime
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OnIdleCallbackOneTime(nullary_func_t callable):
|
||||||
|
mCallable(callable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static void onIdle(void *data)
|
||||||
|
{
|
||||||
|
gIdleCallbacks.deleteFunction(onIdle, data);
|
||||||
|
OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
|
||||||
|
self->call();
|
||||||
|
delete self;
|
||||||
|
}
|
||||||
|
void call()
|
||||||
|
{
|
||||||
|
mCallable();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
nullary_func_t mCallable;
|
||||||
|
};
|
||||||
|
|
||||||
|
void doOnIdleOneTime(nullary_func_t callable)
|
||||||
|
{
|
||||||
|
OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
|
||||||
|
gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shim class to allow generic boost functions to be run as
|
||||||
|
// recurring idle callbacks. Callable should return true when done,
|
||||||
|
// false to continue getting called.
|
||||||
|
class OnIdleCallbackRepeating
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OnIdleCallbackRepeating(bool_func_t callable):
|
||||||
|
mCallable(callable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
// Will keep getting called until the callable returns true.
|
||||||
|
static void onIdle(void *data)
|
||||||
|
{
|
||||||
|
OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
|
||||||
|
bool done = self->call();
|
||||||
|
if (done)
|
||||||
|
{
|
||||||
|
gIdleCallbacks.deleteFunction(onIdle, data);
|
||||||
|
delete self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool call()
|
||||||
|
{
|
||||||
|
return mCallable();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool_func_t mCallable;
|
||||||
|
};
|
||||||
|
|
||||||
|
void doOnIdleRepeating(bool_func_t callable)
|
||||||
|
{
|
||||||
|
OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
|
||||||
|
gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
|
||||||
|
}
|
||||||
|
|
||||||
|
class NullaryFuncEventTimer: public LLEventTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NullaryFuncEventTimer(nullary_func_t callable, F32 seconds):
|
||||||
|
LLEventTimer(seconds),
|
||||||
|
mCallable(callable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BOOL tick()
|
||||||
|
{
|
||||||
|
mCallable();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nullary_func_t mCallable;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call a given callable once after specified interval.
|
||||||
|
void doAfterInterval(nullary_func_t callable, F32 seconds)
|
||||||
|
{
|
||||||
|
new NullaryFuncEventTimer(callable, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
class BoolFuncEventTimer: public LLEventTimer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BoolFuncEventTimer(bool_func_t callable, F32 seconds):
|
||||||
|
LLEventTimer(seconds),
|
||||||
|
mCallable(callable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
BOOL tick()
|
||||||
|
{
|
||||||
|
return mCallable();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_func_t mCallable;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call a given callable every specified number of seconds, until it returns true.
|
||||||
|
void doPeriodically(bool_func_t callable, F32 seconds)
|
||||||
|
{
|
||||||
|
new BoolFuncEventTimer(callable, seconds);
|
||||||
|
}
|
||||||
@@ -28,27 +28,35 @@
|
|||||||
#define LL_LLCALLBACKLIST_H
|
#define LL_LLCALLBACKLIST_H
|
||||||
|
|
||||||
#include "llstl.h"
|
#include "llstl.h"
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <list>
|
||||||
|
#include "stdtypes.h"
|
||||||
|
|
||||||
class LLCallbackList
|
class LLCallbackList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef void (*callback_t)(void*);
|
typedef void (*callback_t)(void*);
|
||||||
|
|
||||||
|
typedef std::pair< callback_t,void* > callback_pair_t;
|
||||||
|
// NOTE: It is confirmed that we DEPEND on the order provided by using a list :(
|
||||||
|
//
|
||||||
|
typedef std::list< callback_pair_t > callback_list_t;
|
||||||
|
|
||||||
LLCallbackList();
|
LLCallbackList();
|
||||||
~LLCallbackList();
|
~LLCallbackList();
|
||||||
|
|
||||||
void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
|
void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
|
||||||
BOOL containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
|
bool containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
|
||||||
BOOL deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
|
bool deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
|
||||||
void callFunctions(); // calls all functions
|
void callFunctions(); // calls all functions
|
||||||
void deleteAllFunctions();
|
void deleteAllFunctions();
|
||||||
|
|
||||||
static void test();
|
static void test();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Use a list so that the callbacks are ordered in case that matters
|
|
||||||
typedef std::pair<callback_t,void*> callback_pair_t;
|
inline callback_list_t::iterator find(callback_t func, void *data);
|
||||||
typedef std::list<callback_pair_t > callback_list_t;
|
|
||||||
callback_list_t mCallbackList;
|
callback_list_t mCallbackList;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -35,7 +35,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Specific error codes
|
// Specific error codes
|
||||||
const int LL_ERR_NOERR = 0;
|
|
||||||
const int LL_ERR_ASSET_REQUEST_FAILED = -1;
|
const int LL_ERR_ASSET_REQUEST_FAILED = -1;
|
||||||
//const int LL_ERR_ASSET_REQUEST_INVALID = -2;
|
//const int LL_ERR_ASSET_REQUEST_INVALID = -2;
|
||||||
const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
|
const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
|
||||||
@@ -108,7 +107,7 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
|
|||||||
: liru_slashpos2 == std::string::npos ? std::string(__FILE__)/*Apparently, we're in / or perhaps the top of the drive, print as is*/\
|
: liru_slashpos2 == std::string::npos ? std::string(__FILE__)/*Apparently, we're in / or perhaps the top of the drive, print as is*/\
|
||||||
: std::string(__FILE__).substr(1+liru_slashpos2))/*print foo/bar.cpp or perhaps foo\bar.cpp*/
|
: std::string(__FILE__).substr(1+liru_slashpos2))/*print foo/bar.cpp or perhaps foo\bar.cpp*/
|
||||||
|
|
||||||
#define llassert_always(func) do { if (LL_UNLIKELY(!(func))) LL_ERRS() << "\nASSERT(" #func ")\nfile:" << liru_assert_strip << " line:" << std::dec << __LINE__ << LL_ENDL; } while(0)
|
//#define llassert_always(func) do { if (LL_UNLIKELY(!(func))) LL_ERRS() << "\nASSERT(" #func ")\nfile:" << liru_assert_strip << " line:" << std::dec << __LINE__ << LL_ENDL; } while(0)
|
||||||
|
|
||||||
#ifdef SHOW_ASSERT
|
#ifdef SHOW_ASSERT
|
||||||
#define llassert(func) llassert_always(func)
|
#define llassert(func) llassert_always(func)
|
||||||
|
|||||||
@@ -37,7 +37,11 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
#include "stdtypes.h"
|
||||||
|
|
||||||
// Use to compare the first element only of a pair
|
// Use to compare the first element only of a pair
|
||||||
// e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t;
|
// e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t;
|
||||||
|
|||||||
@@ -2691,6 +2691,17 @@ void LLVolume::setMeshAssetLoaded(BOOL loaded)
|
|||||||
mIsMeshAssetLoaded = loaded;
|
mIsMeshAssetLoaded = loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLVolume::copyFacesTo(std::vector<LLVolumeFace> &faces) const
|
||||||
|
{
|
||||||
|
faces = mVolumeFaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLVolume::copyFacesFrom(const std::vector<LLVolumeFace> &faces)
|
||||||
|
{
|
||||||
|
mVolumeFaces = faces;
|
||||||
|
mSculptLevel = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void LLVolume::copyVolumeFaces(const LLVolume* volume)
|
void LLVolume::copyVolumeFaces(const LLVolume* volume)
|
||||||
{
|
{
|
||||||
mVolumeFaces = volume->mVolumeFaces;
|
mVolumeFaces = volume->mVolumeFaces;
|
||||||
@@ -4657,7 +4668,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
|
|||||||
|
|
||||||
if (src.mNormals)
|
if (src.mNormals)
|
||||||
{
|
{
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
|
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(src.mTexCoords)
|
if(src.mTexCoords)
|
||||||
@@ -4665,27 +4676,17 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
|
|||||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
|
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allocateTangents(src.mTangents ? src.mNumVertices : 0);
|
||||||
if (src.mTangents)
|
if (src.mTangents)
|
||||||
{
|
{
|
||||||
allocateTangents(src.mNumVertices);
|
LLVector4a::memcpyNonAliased16((F32*)mTangents, (F32*)src.mTangents, vert_size);
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mTangents, (F32*) src.mTangents, vert_size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ll_aligned_free_16(mTangents);
|
|
||||||
mTangents = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allocateWeights(src.mWeights ? src.mNumVertices : 0);
|
||||||
if (src.mWeights)
|
if (src.mWeights)
|
||||||
{
|
{
|
||||||
allocateWeights(src.mNumVertices);
|
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size);
|
LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ll_aligned_free_16(mWeights);
|
|
||||||
mWeights = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mNumIndices)
|
if (mNumIndices)
|
||||||
@@ -4711,19 +4712,10 @@ LLVolumeFace::~LLVolumeFace()
|
|||||||
|
|
||||||
void LLVolumeFace::freeData()
|
void LLVolumeFace::freeData()
|
||||||
{
|
{
|
||||||
ll_aligned_free<64>(mPositions);
|
allocateVertices(0);
|
||||||
mPositions = NULL;
|
allocateTangents(0);
|
||||||
|
allocateWeights(0);
|
||||||
//normals and texture coordinates are part of the same buffer as mPositions, do not free them separately
|
allocateIndices(0);
|
||||||
mNormals = NULL;
|
|
||||||
mTexCoords = NULL;
|
|
||||||
|
|
||||||
ll_aligned_free_16(mIndices);
|
|
||||||
mIndices = NULL;
|
|
||||||
ll_aligned_free_16(mTangents);
|
|
||||||
mTangents = NULL;
|
|
||||||
ll_aligned_free_16(mWeights);
|
|
||||||
mWeights = NULL;
|
|
||||||
|
|
||||||
delete mOctree;
|
delete mOctree;
|
||||||
mOctree = NULL;
|
mOctree = NULL;
|
||||||
@@ -4883,7 +4875,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
|
|||||||
//
|
//
|
||||||
if (new_face.mNumVertices <= mNumVertices)
|
if (new_face.mNumVertices <= mNumVertices)
|
||||||
{
|
{
|
||||||
llassert(new_face.mNumIndices == mNumIndices);
|
llassert(new_face.mNumIndices == mNumIndices);
|
||||||
swapData(new_face);
|
swapData(new_face);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5158,12 +5150,12 @@ public:
|
|||||||
void LLVolumeFace::cacheOptimize()
|
void LLVolumeFace::cacheOptimize()
|
||||||
{ //optimize for vertex cache according to Forsyth method:
|
{ //optimize for vertex cache according to Forsyth method:
|
||||||
// http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
|
// http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
|
||||||
|
|
||||||
llassert(!mOptimized);
|
llassert(!mOptimized);
|
||||||
mOptimized = TRUE;
|
mOptimized = TRUE;
|
||||||
|
|
||||||
LLVCacheLRU cache;
|
LLVCacheLRU cache;
|
||||||
|
|
||||||
if (mNumVertices < 3)
|
if (mNumVertices < 3)
|
||||||
{ //nothing to do
|
{ //nothing to do
|
||||||
return;
|
return;
|
||||||
@@ -5175,17 +5167,17 @@ void LLVolumeFace::cacheOptimize()
|
|||||||
//mapping of triangles do vertices
|
//mapping of triangles do vertices
|
||||||
std::vector<LLVCacheTriangleData> triangle_data;
|
std::vector<LLVCacheTriangleData> triangle_data;
|
||||||
|
|
||||||
triangle_data.resize(mNumIndices/3);
|
triangle_data.resize(mNumIndices / 3);
|
||||||
vertex_data.resize(mNumVertices);
|
vertex_data.resize(mNumVertices);
|
||||||
|
|
||||||
for (U32 i = 0; i < (U32)mNumIndices; i++)
|
for (U32 i = 0; i < (U32)mNumIndices; i++)
|
||||||
{ //populate vertex data and triangle data arrays
|
{ //populate vertex data and triangle data arrays
|
||||||
U16 idx = mIndices[i];
|
U16 idx = mIndices[i];
|
||||||
U32 tri_idx = i/3;
|
U32 tri_idx = i / 3;
|
||||||
|
|
||||||
vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
|
vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
|
||||||
vertex_data[idx].mIdx = idx;
|
vertex_data[idx].mIdx = idx;
|
||||||
triangle_data[tri_idx].mVertex[i%3] = &(vertex_data[idx]);
|
triangle_data[tri_idx].mVertex[i % 3] = &(vertex_data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*F32 pre_acmr = 1.f;
|
/*F32 pre_acmr = 1.f;
|
||||||
@@ -5234,7 +5226,7 @@ void LLVolumeFace::cacheOptimize()
|
|||||||
tri->complete();
|
tri->complete();
|
||||||
|
|
||||||
U32 breaks = 0;
|
U32 breaks = 0;
|
||||||
for (U32 i = 1; i < (U32)mNumIndices/3; ++i)
|
for (U32 i = 1; i < (U32)mNumIndices / 3; ++i)
|
||||||
{
|
{
|
||||||
cache.updateScores();
|
cache.updateScores();
|
||||||
tri = cache.mBestTriangle;
|
tri = cache.mBestTriangle;
|
||||||
@@ -5249,8 +5241,8 @@ void LLVolumeFace::cacheOptimize()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.addTriangle(tri);
|
cache.addTriangle(tri);
|
||||||
new_indices.push_back(tri->mVertex[0]->mIdx);
|
new_indices.push_back(tri->mVertex[0]->mIdx);
|
||||||
new_indices.push_back(tri->mVertex[1]->mIdx);
|
new_indices.push_back(tri->mVertex[1]->mIdx);
|
||||||
@@ -5276,29 +5268,36 @@ void LLVolumeFace::cacheOptimize()
|
|||||||
{
|
{
|
||||||
test_cache.addVertex(&vertex_data[mIndices[i]]);
|
test_cache.addVertex(&vertex_data[mIndices[i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
post_acmr = (F32) test_cache.mMisses/(mNumIndices/3);
|
post_acmr = (F32) test_cache.mMisses/(mNumIndices/3);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
//optimize for pre-TnL cache
|
//optimize for pre-TnL cache
|
||||||
|
|
||||||
//allocate space for new buffer
|
//allocate space for new buffer
|
||||||
S32 num_verts = mNumVertices;
|
S32 num_verts = mNumVertices;
|
||||||
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
|
|
||||||
LLVector4a* pos = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+size);
|
|
||||||
LLVector4a* norm = pos + num_verts;
|
|
||||||
LLVector2* tc = (LLVector2*) (norm + num_verts);
|
|
||||||
|
|
||||||
LLVector4a* wght = NULL;
|
LLVector4a* old_pos = mPositions;
|
||||||
if (mWeights)
|
LLVector4a* old_norm = old_pos + num_verts;
|
||||||
|
LLVector2* old_tc = (LLVector2*)(old_norm + num_verts);
|
||||||
|
mPositions = NULL;
|
||||||
|
if (old_pos)
|
||||||
{
|
{
|
||||||
wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
allocateVertices(num_verts);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVector4a* binorm = NULL;
|
LLVector4a* old_wght = mWeights;
|
||||||
if (mTangents)
|
mWeights = NULL;
|
||||||
|
if (old_wght)
|
||||||
{
|
{
|
||||||
binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
allocateWeights(num_verts);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVector4a* old_binorm = mTangents;
|
||||||
|
mTangents = NULL;
|
||||||
|
if (old_binorm)
|
||||||
|
{
|
||||||
|
allocateTangents(num_verts);
|
||||||
}
|
}
|
||||||
|
|
||||||
//allocate mapping of old indices to new indices
|
//allocate mapping of old indices to new indices
|
||||||
@@ -5314,16 +5313,16 @@ void LLVolumeFace::cacheOptimize()
|
|||||||
new_idx[idx] = cur_idx;
|
new_idx[idx] = cur_idx;
|
||||||
|
|
||||||
//copy vertex data
|
//copy vertex data
|
||||||
pos[cur_idx] = mPositions[idx];
|
mPositions[cur_idx] = old_pos[idx];
|
||||||
norm[cur_idx] = mNormals[idx];
|
mNormals[cur_idx] = old_norm[idx];
|
||||||
tc[cur_idx] = mTexCoords[idx];
|
mTexCoords[cur_idx] = old_tc[idx];
|
||||||
if (mWeights)
|
if (mWeights)
|
||||||
{
|
{
|
||||||
wght[cur_idx] = mWeights[idx];
|
mWeights[cur_idx] = old_wght[idx];
|
||||||
}
|
}
|
||||||
if (mTangents)
|
if (mTangents)
|
||||||
{
|
{
|
||||||
binorm[cur_idx] = mTangents[idx];
|
mTangents[cur_idx] = old_binorm[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
cur_idx++;
|
cur_idx++;
|
||||||
@@ -5335,16 +5334,11 @@ void LLVolumeFace::cacheOptimize()
|
|||||||
mIndices[i] = new_idx[mIndices[i]];
|
mIndices[i] = new_idx[mIndices[i]];
|
||||||
}
|
}
|
||||||
|
|
||||||
ll_aligned_free<64>(mPositions);
|
ll_aligned_free<64>(old_pos);
|
||||||
// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
ll_aligned_free_16(old_binorm);
|
||||||
ll_aligned_free_16(mWeights);
|
ll_aligned_free_16(old_wght);
|
||||||
ll_aligned_free_16(mTangents);
|
|
||||||
|
|
||||||
mPositions = pos;
|
// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||||
mNormals = norm;
|
|
||||||
mTexCoords = tc;
|
|
||||||
mWeights = wght;
|
|
||||||
mTangents = binorm;
|
|
||||||
|
|
||||||
//std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
|
//std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
|
||||||
//LL_INFOS() << result << LL_ENDL;
|
//LL_INFOS() << result << LL_ENDL;
|
||||||
@@ -6053,32 +6047,9 @@ void LLVolumeFace::createTangents()
|
|||||||
|
|
||||||
void LLVolumeFace::resizeVertices(S32 num_verts)
|
void LLVolumeFace::resizeVertices(S32 num_verts)
|
||||||
{
|
{
|
||||||
ll_aligned_free<64>(mPositions);
|
allocateTangents(0);
|
||||||
//DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
allocateVertices(num_verts);
|
||||||
ll_aligned_free_16(mTangents);
|
|
||||||
|
|
||||||
mTangents = NULL;
|
|
||||||
|
|
||||||
if (num_verts)
|
|
||||||
{
|
|
||||||
//pad texture coordinate block end to allow for QWORD reads
|
|
||||||
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
|
|
||||||
|
|
||||||
mPositions = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+size);
|
|
||||||
mNormals = mPositions+num_verts;
|
|
||||||
mTexCoords = (LLVector2*) (mNormals+num_verts);
|
|
||||||
|
|
||||||
ll_assert_aligned(mPositions, 64);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mPositions = NULL;
|
|
||||||
mNormals = NULL;
|
|
||||||
mTexCoords = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mNumVertices = num_verts;
|
mNumVertices = num_verts;
|
||||||
mNumAllocatedVertices = num_verts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv)
|
void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv)
|
||||||
@@ -6093,49 +6064,10 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
|||||||
if (new_verts > mNumAllocatedVertices)
|
if (new_verts > mNumAllocatedVertices)
|
||||||
{
|
{
|
||||||
//double buffer size on expansion
|
//double buffer size on expansion
|
||||||
new_verts *= 2;
|
allocateVertices(new_verts * 2, true);
|
||||||
|
|
||||||
S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF;
|
|
||||||
S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF;
|
|
||||||
|
|
||||||
S32 old_vsize = mNumVertices*16;
|
|
||||||
|
|
||||||
S32 new_size = new_verts*16*2+new_tc_size;
|
|
||||||
|
|
||||||
LLVector4a* old_buf = mPositions;
|
|
||||||
|
|
||||||
mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size);
|
|
||||||
mNormals = mPositions+new_verts;
|
|
||||||
mTexCoords = (LLVector2*) (mNormals+new_verts);
|
|
||||||
|
|
||||||
//<singu>
|
|
||||||
llassert(mNumVertices || (old_buf == NULL && mTangents == NULL));
|
|
||||||
if (mNumVertices) // It turns out this can be zero, in which case old_buf (and mTangents) is NULL.
|
|
||||||
{
|
|
||||||
//</singu>
|
|
||||||
|
|
||||||
//positions
|
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize);
|
|
||||||
|
|
||||||
//normals
|
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize);
|
|
||||||
|
|
||||||
//tex coords
|
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size);
|
|
||||||
|
|
||||||
ll_aligned_free<64>(old_buf);
|
|
||||||
|
|
||||||
//<singu>
|
|
||||||
}
|
|
||||||
//</singu>
|
|
||||||
|
|
||||||
//just clear tangents
|
//just clear tangents
|
||||||
ll_aligned_free_16(mTangents);
|
allocateTangents(0);
|
||||||
mTangents = NULL;
|
|
||||||
ll_aligned_free<64>(old_buf);
|
|
||||||
|
|
||||||
mNumAllocatedVertices = new_verts;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mPositions[mNumVertices] = pos;
|
mPositions[mNumVertices] = pos;
|
||||||
@@ -6148,47 +6080,101 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
|||||||
void LLVolumeFace::allocateTangents(S32 num_verts)
|
void LLVolumeFace::allocateTangents(S32 num_verts)
|
||||||
{
|
{
|
||||||
ll_aligned_free_16(mTangents);
|
ll_aligned_free_16(mTangents);
|
||||||
mTangents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
mTangents = NULL;
|
||||||
|
if (num_verts)
|
||||||
|
{
|
||||||
|
mTangents = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLVolumeFace::allocateWeights(S32 num_verts)
|
void LLVolumeFace::allocateWeights(S32 num_verts)
|
||||||
{
|
{
|
||||||
ll_aligned_free_16(mWeights);
|
ll_aligned_free_16(mWeights);
|
||||||
mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
mWeights = NULL;
|
||||||
|
if (num_verts)
|
||||||
|
{
|
||||||
|
mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLVolumeFace::resizeIndices(S32 num_indices)
|
void LLVolumeFace::allocateVertices(S32 num_verts, bool copy)
|
||||||
{
|
{
|
||||||
|
if (!copy || !num_verts)
|
||||||
|
{
|
||||||
|
ll_aligned_free<64>(mPositions);
|
||||||
|
mPositions = NULL;
|
||||||
|
mNormals = NULL;
|
||||||
|
mTexCoords = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_verts)
|
||||||
|
{
|
||||||
|
const U32 new_vsize = num_verts * sizeof(LLVector4a);
|
||||||
|
const U32 new_nsize = new_vsize;
|
||||||
|
const U32 new_tcsize = (num_verts * sizeof(LLVector2) + 0xF) & ~0xF;
|
||||||
|
const U32 new_size = new_vsize + new_nsize + new_tcsize;
|
||||||
|
|
||||||
|
//allocate new buffer space
|
||||||
|
LLVector4a* old_buf = mPositions;
|
||||||
|
mPositions = (LLVector4a*)ll_aligned_malloc<64>(new_size);
|
||||||
|
mNormals = mPositions + num_verts;
|
||||||
|
mTexCoords = (LLVector2*)(mNormals + num_verts);
|
||||||
|
|
||||||
|
if (copy && old_buf)
|
||||||
|
{
|
||||||
|
U32 verts_to_copy = std::min(mNumVertices, num_verts);
|
||||||
|
if (verts_to_copy)
|
||||||
|
{
|
||||||
|
const U32 old_vsize = verts_to_copy * sizeof(LLVector4a);
|
||||||
|
const U32 old_nsize = old_vsize;
|
||||||
|
const U32 old_tcsize = (verts_to_copy * sizeof(LLVector2) + 0xF) & ~0xF;
|
||||||
|
|
||||||
|
LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize);
|
||||||
|
LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_nsize);
|
||||||
|
LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tcsize);
|
||||||
|
}
|
||||||
|
ll_aligned_free<64>(old_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mNumAllocatedVertices = num_verts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLVolumeFace::allocateIndices(S32 num_indices, bool copy)
|
||||||
|
{
|
||||||
|
if (num_indices == mNumIndices)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
S32 new_size = ((num_indices * sizeof(U16)) + 0xF) & ~0xF;
|
||||||
|
if (copy && num_indices && mIndices && mNumIndices)
|
||||||
|
{
|
||||||
|
S32 old_size = ((mNumIndices * sizeof(U16)) + 0xF) & ~0xF;
|
||||||
|
|
||||||
|
mIndices = (U16*)ll_aligned_realloc_16(mIndices, new_size, old_size);
|
||||||
|
|
||||||
|
mNumIndices = num_indices;
|
||||||
|
return;
|
||||||
|
}
|
||||||
ll_aligned_free_16(mIndices);
|
ll_aligned_free_16(mIndices);
|
||||||
|
mIndices = NULL;
|
||||||
if (num_indices)
|
if (num_indices)
|
||||||
{
|
{
|
||||||
//pad index block end to allow for QWORD reads
|
mIndices = (U16*)ll_aligned_malloc_16(new_size);
|
||||||
S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF;
|
|
||||||
|
|
||||||
mIndices = (U16*) ll_aligned_malloc_16(size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mIndices = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mNumIndices = num_indices;
|
mNumIndices = num_indices;
|
||||||
}
|
}
|
||||||
|
void LLVolumeFace::resizeIndices(S32 num_indices)
|
||||||
|
{
|
||||||
|
allocateIndices(num_indices);
|
||||||
|
}
|
||||||
|
|
||||||
void LLVolumeFace::pushIndex(const U16& idx)
|
void LLVolumeFace::pushIndex(const U16& idx)
|
||||||
{
|
{
|
||||||
S32 new_count = mNumIndices + 1;
|
allocateIndices(mNumIndices + 1, true);
|
||||||
S32 new_size = ((new_count*2)+0xF) & ~0xF;
|
|
||||||
|
|
||||||
S32 old_size = ((mNumIndices*2)+0xF) & ~0xF;
|
mIndices[mNumIndices-1] = idx;
|
||||||
if (new_size != old_size)
|
|
||||||
{
|
|
||||||
mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size);
|
|
||||||
ll_assert_aligned(mIndices,16);
|
|
||||||
}
|
|
||||||
|
|
||||||
mIndices[mNumIndices++] = idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx)
|
void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx)
|
||||||
@@ -6225,24 +6211,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
|
|||||||
LL_ERRS() << "Cannot append empty face." << LL_ENDL;
|
LL_ERRS() << "Cannot append empty face." << LL_ENDL;
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 old_vsize = mNumVertices*16;
|
allocateVertices(new_count, true);
|
||||||
U32 new_vsize = new_count * 16;
|
|
||||||
U32 old_tcsize = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF;
|
|
||||||
U32 new_tcsize = (new_count*sizeof(LLVector2)+0xF) & ~0xF;
|
|
||||||
U32 new_size = new_vsize * 2 + new_tcsize;
|
|
||||||
|
|
||||||
//allocate new buffer space
|
|
||||||
LLVector4a* old_buf = mPositions;
|
|
||||||
mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size);
|
|
||||||
mNormals = mPositions + new_count;
|
|
||||||
mTexCoords = (LLVector2*) (mNormals+new_count);
|
|
||||||
|
|
||||||
mNumAllocatedVertices = new_count;
|
|
||||||
|
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize);
|
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize);
|
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tcsize);
|
|
||||||
|
|
||||||
mNumVertices = new_count;
|
mNumVertices = new_count;
|
||||||
|
|
||||||
//get destination address of appended face
|
//get destination address of appended face
|
||||||
@@ -6286,9 +6255,8 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
|
|||||||
|
|
||||||
new_count = mNumIndices + face.mNumIndices;
|
new_count = mNumIndices + face.mNumIndices;
|
||||||
|
|
||||||
//allocate new index buffer
|
allocateIndices(mNumIndices + face.mNumIndices, true);
|
||||||
mIndices = (U16*) ll_aligned_realloc_16(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF, (mNumIndices*sizeof(U16)+0xF) & ~0xF);
|
|
||||||
|
|
||||||
//get destination address into new index buffer
|
//get destination address into new index buffer
|
||||||
U16* dst_idx = mIndices+mNumIndices;
|
U16* dst_idx = mIndices+mNumIndices;
|
||||||
mNumIndices = new_count;
|
mNumIndices = new_count;
|
||||||
|
|||||||
@@ -876,6 +876,8 @@ public:
|
|||||||
void resizeVertices(S32 num_verts);
|
void resizeVertices(S32 num_verts);
|
||||||
void allocateTangents(S32 num_verts);
|
void allocateTangents(S32 num_verts);
|
||||||
void allocateWeights(S32 num_verts);
|
void allocateWeights(S32 num_verts);
|
||||||
|
void allocateVertices(S32 num_verts, bool copy = false);
|
||||||
|
void allocateIndices(S32 num_indices, bool copy = false);
|
||||||
void resizeIndices(S32 num_indices);
|
void resizeIndices(S32 num_indices);
|
||||||
void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
|
void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
|
||||||
|
|
||||||
@@ -976,6 +978,7 @@ protected:
|
|||||||
~LLVolume(); // use unref
|
~LLVolume(); // use unref
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef std::vector<LLVolumeFace> face_list_t;
|
||||||
|
|
||||||
struct FaceParams
|
struct FaceParams
|
||||||
{
|
{
|
||||||
@@ -1048,11 +1051,16 @@ public:
|
|||||||
// conversion if *(LLVolume*) to LLVolume&
|
// conversion if *(LLVolume*) to LLVolume&
|
||||||
const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
|
const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
|
||||||
|
|
||||||
|
LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
|
||||||
|
|
||||||
|
face_list_t& getVolumeFaces() { return mVolumeFaces; }
|
||||||
U32 mFaceMask; // bit array of which faces exist in this volume
|
U32 mFaceMask; // bit array of which faces exist in this volume
|
||||||
LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
|
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);
|
||||||
void copyVolumeFaces(const LLVolume* volume);
|
void copyVolumeFaces(const LLVolume* volume);
|
||||||
|
void copyFacesTo(std::vector<LLVolumeFace> &faces) const;
|
||||||
|
void copyFacesFrom(const std::vector<LLVolumeFace> &faces);
|
||||||
void cacheOptimize();
|
void cacheOptimize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -9,22 +9,30 @@ include(LLMessage)
|
|||||||
include(LLXML)
|
include(LLXML)
|
||||||
include(LLPhysicsExtensions)
|
include(LLPhysicsExtensions)
|
||||||
include(Colladadom)
|
include(Colladadom)
|
||||||
|
include(LLCharacter)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${LLCOMMON_INCLUDE_DIRS}
|
${LLCOMMON_INCLUDE_DIRS}
|
||||||
${LLMATH_INCLUDE_DIRS}
|
${LLMATH_INCLUDE_DIRS}
|
||||||
${LLMESSAGE_INCLUDE_DIRS}
|
${LLMESSAGE_INCLUDE_DIRS}
|
||||||
${LLXML_INCLUDE_DIRS}
|
${LLXML_INCLUDE_DIRS}
|
||||||
${LLPHYSICSEXTENSIONS_INCLUDE_DIRS}
|
|
||||||
${COLLADADOM_INCLUDE_DIRS}
|
${COLLADADOM_INCLUDE_DIRS}
|
||||||
|
${LLCHARACTER_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
include_directories(SYSTEM
|
||||||
|
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||||
|
${LLXML_SYSTEM_INCLUDE_DIRS}
|
||||||
|
${LLPHYSICSEXTENSIONS_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(llprimitive_SOURCE_FILES
|
set(llprimitive_SOURCE_FILES
|
||||||
|
lldaeloader.cpp
|
||||||
llmaterialid.cpp
|
llmaterialid.cpp
|
||||||
llmaterial.cpp
|
llmaterial.cpp
|
||||||
llmaterialtable.cpp
|
llmaterialtable.cpp
|
||||||
llmediaentry.cpp
|
llmediaentry.cpp
|
||||||
llmodel.cpp
|
llmodel.cpp
|
||||||
|
llmodelloader.cpp
|
||||||
llprimitive.cpp
|
llprimitive.cpp
|
||||||
llprimtexturelist.cpp
|
llprimtexturelist.cpp
|
||||||
lltextureanim.cpp
|
lltextureanim.cpp
|
||||||
@@ -37,13 +45,14 @@ set(llprimitive_SOURCE_FILES
|
|||||||
|
|
||||||
set(llprimitive_HEADER_FILES
|
set(llprimitive_HEADER_FILES
|
||||||
CMakeLists.txt
|
CMakeLists.txt
|
||||||
|
lldaeloader.h
|
||||||
legacy_object_types.h
|
legacy_object_types.h
|
||||||
llmaterial.h
|
llmaterial.h
|
||||||
llmaterialid.h
|
llmaterialid.h
|
||||||
llmaterialtable.h
|
llmaterialtable.h
|
||||||
llmediaentry.h
|
llmediaentry.h
|
||||||
llmodel.h
|
llmodel.h
|
||||||
|
llmodelloader.h
|
||||||
llprimitive.h
|
llprimitive.h
|
||||||
llprimtexturelist.h
|
llprimtexturelist.h
|
||||||
lltextureanim.h
|
lltextureanim.h
|
||||||
|
|||||||
2605
indra/llprimitive/lldaeloader.cpp
Normal file
2605
indra/llprimitive/lldaeloader.cpp
Normal file
File diff suppressed because it is too large
Load Diff
111
indra/llprimitive/lldaeloader.h
Normal file
111
indra/llprimitive/lldaeloader.h
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* @file lldaeloader.h
|
||||||
|
* @brief LLDAELoader class definition
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2013, Linden Research, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 of the License only.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LL_LLDAELOADER_H
|
||||||
|
#define LL_LLDAELOADER_H
|
||||||
|
|
||||||
|
#include "llmodelloader.h"
|
||||||
|
|
||||||
|
class DAE;
|
||||||
|
class daeElement;
|
||||||
|
class domProfile_COMMON;
|
||||||
|
class domInstance_geometry;
|
||||||
|
class domNode;
|
||||||
|
class domTranslate;
|
||||||
|
class domController;
|
||||||
|
class domSkin;
|
||||||
|
class domMesh;
|
||||||
|
|
||||||
|
class LLDAELoader : public LLModelLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::map<std::string, LLImportMaterial> material_map;
|
||||||
|
typedef std::map<daeElement*, std::vector<LLPointer<LLModel> > > dae_model_map;
|
||||||
|
dae_model_map mModelsMap;
|
||||||
|
|
||||||
|
LLDAELoader(
|
||||||
|
std::string filename,
|
||||||
|
S32 lod,
|
||||||
|
LLModelLoader::load_callback_t load_cb,
|
||||||
|
LLModelLoader::joint_lookup_func_t joint_lookup_func,
|
||||||
|
LLModelLoader::texture_load_func_t texture_load_func,
|
||||||
|
LLModelLoader::state_callback_t state_cb,
|
||||||
|
void* opaque_userdata,
|
||||||
|
JointTransformMap& jointMap,
|
||||||
|
JointSet& jointsFromNodes,
|
||||||
|
U32 modelLimit,
|
||||||
|
bool preprocess);
|
||||||
|
virtual ~LLDAELoader() ;
|
||||||
|
|
||||||
|
virtual bool OpenFile(const std::string& filename);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void processElement(daeElement* element, bool& badElement, DAE* dae);
|
||||||
|
void processDomModel(LLModel* model, DAE* dae, daeElement* pRoot, domMesh* mesh, domSkin* skin);
|
||||||
|
|
||||||
|
material_map getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae);
|
||||||
|
LLImportMaterial profileToMaterial(domProfile_COMMON* material, DAE* dae);
|
||||||
|
LLColor4 getDaeColor(daeElement* element);
|
||||||
|
|
||||||
|
daeElement* getChildFromElement( daeElement* pElement, std::string const & name );
|
||||||
|
|
||||||
|
bool isNodeAJoint( domNode* pNode );
|
||||||
|
void processJointNode( domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms );
|
||||||
|
void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform );
|
||||||
|
void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform );
|
||||||
|
void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform );
|
||||||
|
void buildJointToNodeMappingFromScene( daeElement* pRoot );
|
||||||
|
void processJointToNodeMapping( domNode* pNode );
|
||||||
|
void processChildJoints( domNode* pParentNode );
|
||||||
|
|
||||||
|
bool verifyCount( int expected, int result );
|
||||||
|
|
||||||
|
//Verify that a controller matches vertex counts
|
||||||
|
bool verifyController( domController* pController );
|
||||||
|
|
||||||
|
static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh);
|
||||||
|
static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh);
|
||||||
|
|
||||||
|
static LLModel* loadModelFromDomMesh(domMesh* mesh);
|
||||||
|
|
||||||
|
// Loads a mesh breaking it into one or more models as necessary
|
||||||
|
// to get around volume face limitations while retaining >8 materials
|
||||||
|
//
|
||||||
|
bool loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& models_out, U32 submodel_limit);
|
||||||
|
|
||||||
|
static std::string getElementLabel(daeElement *element);
|
||||||
|
static size_t getSuffixPosition(std::string label);
|
||||||
|
static std::string getLodlessLabel(daeElement *element);
|
||||||
|
|
||||||
|
static std::string preprocessDAE(std::string filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels
|
||||||
|
bool mPreprocessDAE;
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif // LL_LLDAELLOADER_H
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@
|
|||||||
#include "llvolume.h"
|
#include "llvolume.h"
|
||||||
#include "v4math.h"
|
#include "v4math.h"
|
||||||
#include "m4math.h"
|
#include "m4math.h"
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
class daeElement;
|
class daeElement;
|
||||||
class domMesh;
|
class domMesh;
|
||||||
@@ -138,15 +139,16 @@ public:
|
|||||||
BOOL upload_skin,
|
BOOL upload_skin,
|
||||||
BOOL upload_joints,
|
BOOL upload_joints,
|
||||||
BOOL nowrite = FALSE,
|
BOOL nowrite = FALSE,
|
||||||
BOOL as_slm = FALSE);
|
BOOL as_slm = FALSE,
|
||||||
|
int submodel_id = 0);
|
||||||
|
|
||||||
static LLSD writeModelToStream(
|
static LLSD writeModelToStream(
|
||||||
std::ostream& ostr,
|
std::ostream& ostr,
|
||||||
LLSD& mdl,
|
LLSD& mdl,
|
||||||
BOOL nowrite = FALSE, BOOL as_slm = FALSE);
|
BOOL nowrite = FALSE, BOOL as_slm = FALSE);
|
||||||
|
|
||||||
|
void ClearFacesAndMaterials() { mVolumeFaces.clear(); mMaterialList.clear(); }
|
||||||
|
|
||||||
static LLModel* loadModelFromDomMesh(domMesh* mesh);
|
|
||||||
static std::string getElementLabel(daeElement* element);
|
|
||||||
std::string getName() const;
|
std::string getName() const;
|
||||||
std::string getMetric() const {return mMetric;}
|
std::string getMetric() const {return mMetric;}
|
||||||
EModelStatus getStatus() const {return mStatus;}
|
EModelStatus getStatus() const {return mStatus;}
|
||||||
@@ -169,7 +171,9 @@ public:
|
|||||||
|
|
||||||
void addFace(const LLVolumeFace& face);
|
void addFace(const LLVolumeFace& face);
|
||||||
|
|
||||||
|
void sortVolumeFacesByMaterialName();
|
||||||
void normalizeVolumeFaces();
|
void normalizeVolumeFaces();
|
||||||
|
void trimVolumeFacesToSize(S32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
|
||||||
void optimizeVolumeFaces();
|
void optimizeVolumeFaces();
|
||||||
void offsetMesh( const LLVector3& pivotPoint );
|
void offsetMesh( const LLVector3& pivotPoint );
|
||||||
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
|
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
|
||||||
@@ -280,9 +284,113 @@ public:
|
|||||||
EModelStatus mStatus ;
|
EModelStatus mStatus ;
|
||||||
|
|
||||||
int mSubmodelID;
|
int mSubmodelID;
|
||||||
protected:
|
|
||||||
void addVolumeFacesFromDomMesh(domMesh* mesh);
|
|
||||||
virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::vector<LLPointer<LLModel> > model_list;
|
||||||
|
typedef std::queue<LLPointer<LLModel> > model_queue;
|
||||||
|
|
||||||
|
class LLModelMaterialBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string mDiffuseMapFilename;
|
||||||
|
std::string mDiffuseMapLabel;
|
||||||
|
std::string mBinding;
|
||||||
|
LLColor4 mDiffuseColor;
|
||||||
|
bool mFullbright;
|
||||||
|
|
||||||
|
LLModelMaterialBase()
|
||||||
|
: mFullbright(false)
|
||||||
|
{
|
||||||
|
mDiffuseColor.set(1,1,1,1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LLImportMaterial : public LLModelMaterialBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend class LLMeshUploadThread;
|
||||||
|
friend class LLModelPreview;
|
||||||
|
|
||||||
|
bool operator<(const LLImportMaterial ¶ms) const;
|
||||||
|
|
||||||
|
LLImportMaterial() : LLModelMaterialBase()
|
||||||
|
{
|
||||||
|
mDiffuseColor.set(1,1,1,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLImportMaterial(LLSD& data);
|
||||||
|
virtual ~LLImportMaterial();
|
||||||
|
|
||||||
|
LLSD asLLSD();
|
||||||
|
|
||||||
|
const LLUUID& getDiffuseMap() const { return mDiffuseMapID; }
|
||||||
|
void setDiffuseMap(const LLUUID& texId) { mDiffuseMapID = texId; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
LLUUID mDiffuseMapID;
|
||||||
|
void* mOpaqueData; // allow refs to viewer/platform-specific structs for each material
|
||||||
|
// currently only stores an LLPointer< LLViewerFetchedTexture > > to
|
||||||
|
// maintain refs to textures associated with each material for free
|
||||||
|
// ref counting.
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, LLImportMaterial> material_map;
|
||||||
|
|
||||||
|
class LLModelInstanceBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLPointer<LLModel> mModel;
|
||||||
|
LLPointer<LLModel> mLOD[5];
|
||||||
|
LLUUID mMeshID;
|
||||||
|
|
||||||
|
LLMatrix4 mTransform;
|
||||||
|
material_map mMaterial;
|
||||||
|
|
||||||
|
LLModelInstanceBase(LLModel* model, LLMatrix4& transform, material_map& materials)
|
||||||
|
: mModel(model), mTransform(transform), mMaterial(materials)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
LLModelInstanceBase()
|
||||||
|
: mModel(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<LLModelInstanceBase> model_instance_list;
|
||||||
|
|
||||||
|
class LLModelInstance : public LLModelInstanceBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string mLabel;
|
||||||
|
LLUUID mMeshID;
|
||||||
|
S32 mLocalMeshID;
|
||||||
|
|
||||||
|
LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, material_map& materials)
|
||||||
|
: LLModelInstanceBase(model, transform, materials), mLabel(label)
|
||||||
|
{
|
||||||
|
mLocalMeshID = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLModelInstance(LLSD& data);
|
||||||
|
|
||||||
|
LLSD asLLSD();
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LL_DEGENERACY_TOLERANCE 1e-7f
|
||||||
|
|
||||||
|
inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b)
|
||||||
|
{
|
||||||
|
volatile F32 p0 = a[0] * b[0];
|
||||||
|
volatile F32 p1 = a[1] * b[1];
|
||||||
|
volatile F32 p2 = a[2] * b[2];
|
||||||
|
return p0 + p1 + p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE);
|
||||||
|
|
||||||
|
bool validate_face(const LLVolumeFace& face);
|
||||||
|
bool validate_model(const LLModel* mdl);
|
||||||
|
|
||||||
#endif //LL_LLMODEL_H
|
#endif //LL_LLMODEL_H
|
||||||
|
|||||||
644
indra/llprimitive/llmodelloader.cpp
Normal file
644
indra/llprimitive/llmodelloader.cpp
Normal file
@@ -0,0 +1,644 @@
|
|||||||
|
/**
|
||||||
|
* @file llmodelloader.cpp
|
||||||
|
* @brief LLModelLoader class implementation
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2010, Linden Research, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 of the License only.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "llmodelloader.h"
|
||||||
|
#include "llsdserialize.h"
|
||||||
|
#include "lljoint.h"
|
||||||
|
#include "llcallbacklist.h"
|
||||||
|
|
||||||
|
#include "llmatrix4a.h"
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/thread/thread.hpp>
|
||||||
|
|
||||||
|
std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList;
|
||||||
|
|
||||||
|
void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform)
|
||||||
|
{
|
||||||
|
LLVector4a box[] =
|
||||||
|
{
|
||||||
|
LLVector4a(-1, 1,-1),
|
||||||
|
LLVector4a(-1, 1, 1),
|
||||||
|
LLVector4a(-1,-1,-1),
|
||||||
|
LLVector4a(-1,-1, 1),
|
||||||
|
LLVector4a( 1, 1,-1),
|
||||||
|
LLVector4a( 1, 1, 1),
|
||||||
|
LLVector4a( 1,-1,-1),
|
||||||
|
LLVector4a( 1,-1, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (S32 j = 0; j < model->getNumVolumeFaces(); ++j)
|
||||||
|
{
|
||||||
|
const LLVolumeFace& face = model->getVolumeFace(j);
|
||||||
|
|
||||||
|
LLVector4a center;
|
||||||
|
center.setAdd(face.mExtents[0], face.mExtents[1]);
|
||||||
|
center.mul(0.5f);
|
||||||
|
LLVector4a size;
|
||||||
|
size.setSub(face.mExtents[1],face.mExtents[0]);
|
||||||
|
size.mul(0.5f);
|
||||||
|
|
||||||
|
for (U32 i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
LLVector4a t;
|
||||||
|
t.setMul(size, box[i]);
|
||||||
|
t.add(center);
|
||||||
|
|
||||||
|
LLVector4a v;
|
||||||
|
|
||||||
|
mat.affineTransform(t, v);
|
||||||
|
|
||||||
|
if (first_transform)
|
||||||
|
{
|
||||||
|
first_transform = FALSE;
|
||||||
|
min = max = v;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
update_min_max(min, max, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform)
|
||||||
|
{
|
||||||
|
LLVector4a mina, maxa;
|
||||||
|
LLMatrix4a mata;
|
||||||
|
|
||||||
|
mata.loadu(mat);
|
||||||
|
mina.load3(min.mV);
|
||||||
|
maxa.load3(max.mV);
|
||||||
|
|
||||||
|
stretch_extents(model, mata, mina, maxa, first_transform);
|
||||||
|
|
||||||
|
min.set(mina.getF32ptr());
|
||||||
|
max.set(maxa.getF32ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// LLModelLoader
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
LLModelLoader::LLModelLoader(
|
||||||
|
std::string filename,
|
||||||
|
S32 lod,
|
||||||
|
load_callback_t load_cb,
|
||||||
|
joint_lookup_func_t joint_lookup_func,
|
||||||
|
texture_load_func_t texture_load_func,
|
||||||
|
state_callback_t state_cb,
|
||||||
|
void* opaque_userdata,
|
||||||
|
JointTransformMap& jointMap,
|
||||||
|
JointSet& jointsFromNodes )
|
||||||
|
: mJointList( jointMap )
|
||||||
|
, mJointsFromNode( jointsFromNodes )
|
||||||
|
, LLThread("Model Loader")
|
||||||
|
, mFilename(filename)
|
||||||
|
, mLod(lod)
|
||||||
|
, mTrySLM(false)
|
||||||
|
, mFirstTransform(TRUE)
|
||||||
|
, mNumOfFetchingTextures(0)
|
||||||
|
, mLoadCallback(load_cb)
|
||||||
|
, mJointLookupFunc(joint_lookup_func)
|
||||||
|
, mTextureLoadFunc(texture_load_func)
|
||||||
|
, mStateCallback(state_cb)
|
||||||
|
, mOpaqueData(opaque_userdata)
|
||||||
|
, mRigParityWithScene(false)
|
||||||
|
, mRigValidJointUpload(false)
|
||||||
|
, mLegacyRigValid(false)
|
||||||
|
, mNoNormalize(false)
|
||||||
|
, mNoOptimize(false)
|
||||||
|
, mCacheOnlyHitIfRigged(false)
|
||||||
|
{
|
||||||
|
mJointMap["mPelvis"] = "mPelvis";
|
||||||
|
mJointMap["mTorso"] = "mTorso";
|
||||||
|
mJointMap["mChest"] = "mChest";
|
||||||
|
mJointMap["mNeck"] = "mNeck";
|
||||||
|
mJointMap["mHead"] = "mHead";
|
||||||
|
mJointMap["mSkull"] = "mSkull";
|
||||||
|
mJointMap["mEyeRight"] = "mEyeRight";
|
||||||
|
mJointMap["mEyeLeft"] = "mEyeLeft";
|
||||||
|
mJointMap["mCollarLeft"] = "mCollarLeft";
|
||||||
|
mJointMap["mShoulderLeft"] = "mShoulderLeft";
|
||||||
|
mJointMap["mElbowLeft"] = "mElbowLeft";
|
||||||
|
mJointMap["mWristLeft"] = "mWristLeft";
|
||||||
|
mJointMap["mCollarRight"] = "mCollarRight";
|
||||||
|
mJointMap["mShoulderRight"] = "mShoulderRight";
|
||||||
|
mJointMap["mElbowRight"] = "mElbowRight";
|
||||||
|
mJointMap["mWristRight"] = "mWristRight";
|
||||||
|
mJointMap["mHipRight"] = "mHipRight";
|
||||||
|
mJointMap["mKneeRight"] = "mKneeRight";
|
||||||
|
mJointMap["mAnkleRight"] = "mAnkleRight";
|
||||||
|
mJointMap["mFootRight"] = "mFootRight";
|
||||||
|
mJointMap["mToeRight"] = "mToeRight";
|
||||||
|
mJointMap["mHipLeft"] = "mHipLeft";
|
||||||
|
mJointMap["mKneeLeft"] = "mKneeLeft";
|
||||||
|
mJointMap["mAnkleLeft"] = "mAnkleLeft";
|
||||||
|
mJointMap["mFootLeft"] = "mFootLeft";
|
||||||
|
mJointMap["mToeLeft"] = "mToeLeft";
|
||||||
|
|
||||||
|
mJointMap["avatar_mPelvis"] = "mPelvis";
|
||||||
|
mJointMap["avatar_mTorso"] = "mTorso";
|
||||||
|
mJointMap["avatar_mChest"] = "mChest";
|
||||||
|
mJointMap["avatar_mNeck"] = "mNeck";
|
||||||
|
mJointMap["avatar_mHead"] = "mHead";
|
||||||
|
mJointMap["avatar_mSkull"] = "mSkull";
|
||||||
|
mJointMap["avatar_mEyeRight"] = "mEyeRight";
|
||||||
|
mJointMap["avatar_mEyeLeft"] = "mEyeLeft";
|
||||||
|
mJointMap["avatar_mCollarLeft"] = "mCollarLeft";
|
||||||
|
mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft";
|
||||||
|
mJointMap["avatar_mElbowLeft"] = "mElbowLeft";
|
||||||
|
mJointMap["avatar_mWristLeft"] = "mWristLeft";
|
||||||
|
mJointMap["avatar_mCollarRight"] = "mCollarRight";
|
||||||
|
mJointMap["avatar_mShoulderRight"] = "mShoulderRight";
|
||||||
|
mJointMap["avatar_mElbowRight"] = "mElbowRight";
|
||||||
|
mJointMap["avatar_mWristRight"] = "mWristRight";
|
||||||
|
mJointMap["avatar_mHipRight"] = "mHipRight";
|
||||||
|
mJointMap["avatar_mKneeRight"] = "mKneeRight";
|
||||||
|
mJointMap["avatar_mAnkleRight"] = "mAnkleRight";
|
||||||
|
mJointMap["avatar_mFootRight"] = "mFootRight";
|
||||||
|
mJointMap["avatar_mToeRight"] = "mToeRight";
|
||||||
|
mJointMap["avatar_mHipLeft"] = "mHipLeft";
|
||||||
|
mJointMap["avatar_mKneeLeft"] = "mKneeLeft";
|
||||||
|
mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft";
|
||||||
|
mJointMap["avatar_mFootLeft"] = "mFootLeft";
|
||||||
|
mJointMap["avatar_mToeLeft"] = "mToeLeft";
|
||||||
|
|
||||||
|
|
||||||
|
mJointMap["hip"] = "mPelvis";
|
||||||
|
mJointMap["abdomen"] = "mTorso";
|
||||||
|
mJointMap["chest"] = "mChest";
|
||||||
|
mJointMap["neck"] = "mNeck";
|
||||||
|
mJointMap["head"] = "mHead";
|
||||||
|
mJointMap["figureHair"] = "mSkull";
|
||||||
|
mJointMap["lCollar"] = "mCollarLeft";
|
||||||
|
mJointMap["lShldr"] = "mShoulderLeft";
|
||||||
|
mJointMap["lForeArm"] = "mElbowLeft";
|
||||||
|
mJointMap["lHand"] = "mWristLeft";
|
||||||
|
mJointMap["rCollar"] = "mCollarRight";
|
||||||
|
mJointMap["rShldr"] = "mShoulderRight";
|
||||||
|
mJointMap["rForeArm"] = "mElbowRight";
|
||||||
|
mJointMap["rHand"] = "mWristRight";
|
||||||
|
mJointMap["rThigh"] = "mHipRight";
|
||||||
|
mJointMap["rShin"] = "mKneeRight";
|
||||||
|
mJointMap["rFoot"] = "mFootRight";
|
||||||
|
mJointMap["lThigh"] = "mHipLeft";
|
||||||
|
mJointMap["lShin"] = "mKneeLeft";
|
||||||
|
mJointMap["lFoot"] = "mFootLeft";
|
||||||
|
|
||||||
|
//move into joint mapper class
|
||||||
|
//1. joints for joint offset verification
|
||||||
|
mMasterJointList.push_front("mPelvis");
|
||||||
|
mMasterJointList.push_front("mTorso");
|
||||||
|
mMasterJointList.push_front("mChest");
|
||||||
|
mMasterJointList.push_front("mNeck");
|
||||||
|
mMasterJointList.push_front("mHead");
|
||||||
|
mMasterJointList.push_front("mCollarLeft");
|
||||||
|
mMasterJointList.push_front("mShoulderLeft");
|
||||||
|
mMasterJointList.push_front("mElbowLeft");
|
||||||
|
mMasterJointList.push_front("mWristLeft");
|
||||||
|
mMasterJointList.push_front("mCollarRight");
|
||||||
|
mMasterJointList.push_front("mShoulderRight");
|
||||||
|
mMasterJointList.push_front("mElbowRight");
|
||||||
|
mMasterJointList.push_front("mWristRight");
|
||||||
|
mMasterJointList.push_front("mHipRight");
|
||||||
|
mMasterJointList.push_front("mKneeRight");
|
||||||
|
mMasterJointList.push_front("mFootRight");
|
||||||
|
mMasterJointList.push_front("mHipLeft");
|
||||||
|
mMasterJointList.push_front("mKneeLeft");
|
||||||
|
mMasterJointList.push_front("mFootLeft");
|
||||||
|
|
||||||
|
//2. legacy joint list - used to verify rigs that will not be using joint offsets
|
||||||
|
mMasterLegacyJointList.push_front("mPelvis");
|
||||||
|
mMasterLegacyJointList.push_front("mTorso");
|
||||||
|
mMasterLegacyJointList.push_front("mChest");
|
||||||
|
mMasterLegacyJointList.push_front("mNeck");
|
||||||
|
mMasterLegacyJointList.push_front("mHead");
|
||||||
|
mMasterLegacyJointList.push_front("mHipRight");
|
||||||
|
mMasterLegacyJointList.push_front("mKneeRight");
|
||||||
|
mMasterLegacyJointList.push_front("mFootRight");
|
||||||
|
mMasterLegacyJointList.push_front("mHipLeft");
|
||||||
|
mMasterLegacyJointList.push_front("mKneeLeft");
|
||||||
|
mMasterLegacyJointList.push_front("mFootLeft");
|
||||||
|
|
||||||
|
assert_main_thread();
|
||||||
|
sActiveLoaderList.push_back(this) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLModelLoader::~LLModelLoader()
|
||||||
|
{
|
||||||
|
assert_main_thread();
|
||||||
|
sActiveLoaderList.remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLModelLoader::run()
|
||||||
|
{
|
||||||
|
doLoadModel();
|
||||||
|
doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLModelLoader::doLoadModel()
|
||||||
|
{
|
||||||
|
//first, look for a .slm file of the same name that was modified later
|
||||||
|
//than the .dae
|
||||||
|
|
||||||
|
if (mTrySLM)
|
||||||
|
{
|
||||||
|
std::string filename = mFilename;
|
||||||
|
|
||||||
|
std::string::size_type i = filename.rfind(".");
|
||||||
|
if (i != std::string::npos)
|
||||||
|
{
|
||||||
|
filename.replace(i, filename.size()-1, ".slm");
|
||||||
|
llstat slm_status;
|
||||||
|
if (LLFile::stat(filename, &slm_status) == 0)
|
||||||
|
{ //slm file exists
|
||||||
|
llstat dae_status;
|
||||||
|
if (LLFile::stat(mFilename, &dae_status) != 0 ||
|
||||||
|
dae_status.st_mtime < slm_status.st_mtime)
|
||||||
|
{
|
||||||
|
if (loadFromSLM(filename))
|
||||||
|
{ //slm successfully loaded, if this fails, fall through and
|
||||||
|
//try loading from dae
|
||||||
|
|
||||||
|
mLod = -1; //successfully loading from an slm implicitly sets all
|
||||||
|
//LoDs
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpenFile(mFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLModelLoader::setLoadState(U32 state)
|
||||||
|
{
|
||||||
|
mStateCallback(state, mOpaqueData);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLModelLoader::loadFromSLM(const std::string& filename)
|
||||||
|
{
|
||||||
|
//only need to populate mScene with data from slm
|
||||||
|
llstat stat;
|
||||||
|
|
||||||
|
if (LLFile::stat(filename, &stat))
|
||||||
|
{ //file does not exist
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
S32 file_size = (S32) stat.st_size;
|
||||||
|
|
||||||
|
llifstream ifstream(filename.c_str(), std::ifstream::in | std::ifstream::binary);
|
||||||
|
LLSD data;
|
||||||
|
LLSDSerialize::fromBinary(data, ifstream, file_size);
|
||||||
|
ifstream.close();
|
||||||
|
|
||||||
|
//build model list for each LoD
|
||||||
|
model_list model[LLModel::NUM_LODS];
|
||||||
|
|
||||||
|
if (data["version"].asInteger() != SLM_SUPPORTED_VERSION)
|
||||||
|
{ //unsupported version
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLSD& mesh = data["mesh"];
|
||||||
|
|
||||||
|
LLVolumeParams volume_params;
|
||||||
|
volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
|
||||||
|
|
||||||
|
for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
|
||||||
|
{
|
||||||
|
for (U32 i = 0; i < (U32)mesh.size(); ++i)
|
||||||
|
{
|
||||||
|
std::stringstream str(mesh[i].asString());
|
||||||
|
LLPointer<LLModel> loaded_model = new LLModel(volume_params, (F32) lod);
|
||||||
|
if (loaded_model->loadModel(str))
|
||||||
|
{
|
||||||
|
loaded_model->mLocalID = i;
|
||||||
|
model[lod].push_back(loaded_model);
|
||||||
|
|
||||||
|
if (lod == LLModel::LOD_HIGH)
|
||||||
|
{
|
||||||
|
if (!loaded_model->mSkinInfo.mJointNames.empty())
|
||||||
|
{
|
||||||
|
//check to see if rig is valid
|
||||||
|
critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames );
|
||||||
|
}
|
||||||
|
else if (mCacheOnlyHitIfRigged)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model[LLModel::LOD_HIGH].empty())
|
||||||
|
{ //failed to load high lod
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//load instance list
|
||||||
|
model_instance_list instance_list;
|
||||||
|
|
||||||
|
LLSD& instance = data["instance"];
|
||||||
|
|
||||||
|
for (U32 i = 0; i < (U32)instance.size(); ++i)
|
||||||
|
{
|
||||||
|
//deserialize instance list
|
||||||
|
instance_list.push_back(LLModelInstance(instance[i]));
|
||||||
|
|
||||||
|
//match up model instance pointers
|
||||||
|
S32 idx = instance_list[i].mLocalMeshID;
|
||||||
|
std::string instance_label = instance_list[i].mLabel;
|
||||||
|
|
||||||
|
for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
|
||||||
|
{
|
||||||
|
if (!model[lod].empty())
|
||||||
|
{
|
||||||
|
if (idx >= model[lod].size())
|
||||||
|
{
|
||||||
|
if (model[lod].size())
|
||||||
|
{
|
||||||
|
instance_list[i].mLOD[lod] = model[lod][0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instance_list[i].mLOD[lod] = NULL;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model[lod][idx]
|
||||||
|
&& model[lod][idx]->mLabel.empty()
|
||||||
|
&& !instance_label.empty())
|
||||||
|
{
|
||||||
|
// restore model names
|
||||||
|
std::string name = instance_label;
|
||||||
|
switch (lod)
|
||||||
|
{
|
||||||
|
case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break;
|
||||||
|
case LLModel::LOD_LOW: name += "_LOD1"; break;
|
||||||
|
case LLModel::LOD_MEDIUM: name += "_LOD2"; break;
|
||||||
|
case LLModel::LOD_PHYSICS: name += "_PHYS"; break;
|
||||||
|
case LLModel::LOD_HIGH: break;
|
||||||
|
}
|
||||||
|
model[lod][idx]->mLabel = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance_list[i].mLOD[lod] = model[lod][idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!instance_list[i].mModel)
|
||||||
|
instance_list[i].mModel = model[LLModel::LOD_HIGH][idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set name for UI to use
|
||||||
|
std::string name = data["name"];
|
||||||
|
if (!name.empty())
|
||||||
|
{
|
||||||
|
model[LLModel::LOD_HIGH][0]->mRequestedLabel = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//convert instance_list to mScene
|
||||||
|
mFirstTransform = TRUE;
|
||||||
|
for (U32 i = 0; i < instance_list.size(); ++i)
|
||||||
|
{
|
||||||
|
LLModelInstance& cur_instance = instance_list[i];
|
||||||
|
mScene[cur_instance.mTransform].push_back(cur_instance);
|
||||||
|
stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoadState( DONE );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
bool LLModelLoader::isAlive(LLModelLoader* loader)
|
||||||
|
{
|
||||||
|
if(!loader)
|
||||||
|
{
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<LLModelLoader*>::iterator iter = sActiveLoaderList.begin() ;
|
||||||
|
for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ;
|
||||||
|
|
||||||
|
return *iter == loader ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLModelLoader::loadModelCallback()
|
||||||
|
{
|
||||||
|
mLoadCallback(mScene,mModelList,mLod, mOpaqueData);
|
||||||
|
|
||||||
|
while (!isStopped())
|
||||||
|
{ //wait until this thread is stopped before deleting self
|
||||||
|
boost::this_thread::sleep_for(boost::chrono::microseconds(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
//double check if "this" is valid before deleting it, in case it is aborted during running.
|
||||||
|
if(!isAlive(this))
|
||||||
|
{
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// critiqueRigForUploadApplicability()
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void LLModelLoader::critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset )
|
||||||
|
{
|
||||||
|
critiqueJointToNodeMappingFromScene();
|
||||||
|
|
||||||
|
//Determines the following use cases for a rig:
|
||||||
|
//1. It is suitable for upload with skin weights & joint positions, or
|
||||||
|
//2. It is suitable for upload as standard av with just skin weights
|
||||||
|
|
||||||
|
bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset );
|
||||||
|
bool isRigLegacyOK = isRigLegacy( jointListFromAsset );
|
||||||
|
|
||||||
|
//It's OK that both could end up being true, both default to false
|
||||||
|
if ( isJointPositionUploadOK )
|
||||||
|
{
|
||||||
|
setRigValidForJointPositionUpload( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isRigLegacyOK)
|
||||||
|
{
|
||||||
|
setLegacyRigValid( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// critiqueJointToNodeMappingFromScene()
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void LLModelLoader::critiqueJointToNodeMappingFromScene( void )
|
||||||
|
{
|
||||||
|
//Do the actual nodes back the joint listing from the dae?
|
||||||
|
//if yes then this is a fully rigged asset, otherwise it's just a partial rig
|
||||||
|
|
||||||
|
JointSet::iterator jointsFromNodeIt = mJointsFromNode.begin();
|
||||||
|
JointSet::iterator jointsFromNodeEndIt = mJointsFromNode.end();
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
if ( !mJointsFromNode.empty() )
|
||||||
|
{
|
||||||
|
for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt )
|
||||||
|
{
|
||||||
|
std::string name = *jointsFromNodeIt;
|
||||||
|
if ( mJointTransformMap.find( name ) != mJointTransformMap.end() )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LL_INFOS() <<"critiqueJointToNodeMappingFromScene is missing a: " << name << LL_ENDL;
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Determines the following use cases for a rig:
|
||||||
|
//1. Full av rig w/1-1 mapping from the scene and joint array
|
||||||
|
//2. Partial rig but w/o parity between the scene and joint array
|
||||||
|
if ( result )
|
||||||
|
{
|
||||||
|
setRigWithSceneParity( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// isRigLegacy()
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool LLModelLoader::isRigLegacy( const std::vector<std::string> &jointListFromAsset )
|
||||||
|
{
|
||||||
|
//No joints in asset
|
||||||
|
if ( jointListFromAsset.size() == 0 )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
JointSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin();
|
||||||
|
JointSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end();
|
||||||
|
|
||||||
|
std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
|
||||||
|
std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
|
||||||
|
|
||||||
|
for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
modelJointIt = jointListFromAsset.begin();
|
||||||
|
|
||||||
|
for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
|
||||||
|
{
|
||||||
|
if ( *masterJointIt == *modelJointIt )
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !result )
|
||||||
|
{
|
||||||
|
LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// isRigSuitableForJointPositionUpload()
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset )
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
JointSet :: const_iterator masterJointIt = mMasterJointList.begin();
|
||||||
|
JointSet :: const_iterator masterJointEndIt = mMasterJointList.end();
|
||||||
|
|
||||||
|
std::vector<std::string> :: const_iterator modelJointIt = jointListFromAsset.begin();
|
||||||
|
std::vector<std::string> :: const_iterator modelJointItEnd = jointListFromAsset.end();
|
||||||
|
|
||||||
|
for ( ;masterJointIt!=masterJointEndIt;++masterJointIt )
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
modelJointIt = jointListFromAsset.begin();
|
||||||
|
|
||||||
|
for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt )
|
||||||
|
{
|
||||||
|
if ( *masterJointIt == *modelJointIt )
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !result )
|
||||||
|
{
|
||||||
|
LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//called in the main thread
|
||||||
|
void LLModelLoader::loadTextures()
|
||||||
|
{
|
||||||
|
BOOL is_paused = isPaused() ;
|
||||||
|
pause() ; //pause the loader
|
||||||
|
|
||||||
|
for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter)
|
||||||
|
{
|
||||||
|
for(U32 i = 0 ; i < iter->second.size(); i++)
|
||||||
|
{
|
||||||
|
for(std::map<std::string, LLImportMaterial>::iterator j = iter->second[i].mMaterial.begin();
|
||||||
|
j != iter->second[i].mMaterial.end(); ++j)
|
||||||
|
{
|
||||||
|
LLImportMaterial& material = j->second;
|
||||||
|
|
||||||
|
if(!material.mDiffuseMapFilename.empty())
|
||||||
|
{
|
||||||
|
mNumOfFetchingTextures += mTextureLoadFunc(material, mOpaqueData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!is_paused)
|
||||||
|
{
|
||||||
|
unpause() ;
|
||||||
|
}
|
||||||
|
}
|
||||||
212
indra/llprimitive/llmodelloader.h
Normal file
212
indra/llprimitive/llmodelloader.h
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/**
|
||||||
|
* @file llmodelloader.h
|
||||||
|
* @brief LLModelLoader class definition
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2010, Linden Research, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation;
|
||||||
|
* version 2.1 of the License only.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LL_LLMODELLOADER_H
|
||||||
|
#define LL_LLMODELLOADER_H
|
||||||
|
|
||||||
|
#include "llmodel.h"
|
||||||
|
#include "llthread.h"
|
||||||
|
#include <boost/function.hpp>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
class LLJoint;
|
||||||
|
|
||||||
|
typedef std::map<std::string, LLMatrix4> JointTransformMap;
|
||||||
|
typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
|
||||||
|
typedef std::map<std::string, std::string> JointMap;
|
||||||
|
typedef std::deque<std::string> JointSet;
|
||||||
|
|
||||||
|
const S32 SLM_SUPPORTED_VERSION = 3;
|
||||||
|
const S32 NUM_LOD = 4;
|
||||||
|
|
||||||
|
class LLModelLoader : public LLThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::map<std::string, LLImportMaterial> material_map;
|
||||||
|
typedef std::vector<LLPointer<LLModel > > model_list;
|
||||||
|
typedef std::vector<LLModelInstance> model_instance_list;
|
||||||
|
typedef std::map<LLMatrix4, model_instance_list > scene;
|
||||||
|
|
||||||
|
// Callback with loaded model data and loaded LoD
|
||||||
|
//
|
||||||
|
typedef boost::function<void (scene&,model_list&,S32,void*) > load_callback_t;
|
||||||
|
|
||||||
|
// Function to provide joint lookup by name
|
||||||
|
// (within preview avi skeleton, for example)
|
||||||
|
//
|
||||||
|
typedef boost::function<LLJoint* (const std::string&,void*) > joint_lookup_func_t;
|
||||||
|
|
||||||
|
// Func to load and associate material with all it's textures,
|
||||||
|
// returned value is the number of textures loaded
|
||||||
|
// intentionally non-const so func can modify material to
|
||||||
|
// store platform-specific data
|
||||||
|
//
|
||||||
|
typedef boost::function<U32 (LLImportMaterial&,void*) > texture_load_func_t;
|
||||||
|
|
||||||
|
// Callback to inform client of state changes
|
||||||
|
// during loading process (errors will be reported
|
||||||
|
// as state changes here as well)
|
||||||
|
//
|
||||||
|
typedef boost::function<void (U32,void*) > state_callback_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STARTING = 0,
|
||||||
|
READING_FILE,
|
||||||
|
CREATING_FACES,
|
||||||
|
GENERATING_VERTEX_BUFFERS,
|
||||||
|
GENERATING_LOD,
|
||||||
|
DONE,
|
||||||
|
ERROR_PARSING, //basically loading failed
|
||||||
|
ERROR_MATERIALS,
|
||||||
|
ERROR_PASSWORD_REQUIRED,
|
||||||
|
ERROR_NEED_MORE_MEMORY,
|
||||||
|
ERROR_INVALID_FILE,
|
||||||
|
ERROR_LOADER_SETUP,
|
||||||
|
ERROR_INVALID_PARAMETERS,
|
||||||
|
ERROR_OUT_OF_RANGE,
|
||||||
|
ERROR_FILE_VERSION_INVALID,
|
||||||
|
ERROR_MODEL // this error should always be last in this list, error code is passed as ERROR_MODEL+error_code
|
||||||
|
} eLoadState;
|
||||||
|
|
||||||
|
U32 mState;
|
||||||
|
std::string mFilename;
|
||||||
|
|
||||||
|
S32 mLod;
|
||||||
|
|
||||||
|
LLMatrix4 mTransform;
|
||||||
|
BOOL mFirstTransform;
|
||||||
|
LLVector3 mExtents[2];
|
||||||
|
|
||||||
|
bool mTrySLM;
|
||||||
|
bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info)
|
||||||
|
|
||||||
|
model_list mModelList;
|
||||||
|
scene mScene;
|
||||||
|
|
||||||
|
typedef std::queue<LLPointer<LLModel> > model_queue;
|
||||||
|
|
||||||
|
//queue of models that need a physics rep
|
||||||
|
model_queue mPhysicsQ;
|
||||||
|
|
||||||
|
//map of avatar joints as named in COLLADA assets to internal joint names
|
||||||
|
JointMap mJointMap;
|
||||||
|
JointTransformMap& mJointList;
|
||||||
|
JointSet& mJointsFromNode;
|
||||||
|
|
||||||
|
LLModelLoader(
|
||||||
|
std::string filename,
|
||||||
|
S32 lod,
|
||||||
|
LLModelLoader::load_callback_t load_cb,
|
||||||
|
LLModelLoader::joint_lookup_func_t joint_lookup_func,
|
||||||
|
LLModelLoader::texture_load_func_t texture_load_func,
|
||||||
|
LLModelLoader::state_callback_t state_cb,
|
||||||
|
void* opaque_userdata,
|
||||||
|
JointTransformMap& jointMap,
|
||||||
|
JointSet& jointsFromNodes);
|
||||||
|
virtual ~LLModelLoader() ;
|
||||||
|
|
||||||
|
virtual void setNoNormalize() { mNoNormalize = true; }
|
||||||
|
virtual void setNoOptimize() { mNoOptimize = true; }
|
||||||
|
|
||||||
|
virtual void run();
|
||||||
|
|
||||||
|
// Will try SLM or derived class OpenFile as appropriate
|
||||||
|
//
|
||||||
|
virtual bool doLoadModel();
|
||||||
|
|
||||||
|
// Derived classes need to provide their parsing of files here
|
||||||
|
//
|
||||||
|
virtual bool OpenFile(const std::string& filename) = 0;
|
||||||
|
|
||||||
|
bool loadFromSLM(const std::string& filename);
|
||||||
|
|
||||||
|
void loadModelCallback();
|
||||||
|
void loadTextures() ; //called in the main thread.
|
||||||
|
void setLoadState(U32 state);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
S32 mNumOfFetchingTextures ; //updated in the main thread
|
||||||
|
bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
|
||||||
|
|
||||||
|
bool verifyCount( int expected, int result );
|
||||||
|
|
||||||
|
//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
|
||||||
|
void critiqueRigForUploadApplicability( const std::vector<std::string> &jointListFromAsset );
|
||||||
|
void critiqueJointToNodeMappingFromScene( void );
|
||||||
|
|
||||||
|
//Determines if a rig is a legacy from the joint list
|
||||||
|
bool isRigLegacy( const std::vector<std::string> &jointListFromAsset );
|
||||||
|
|
||||||
|
//Determines if a rig is suitable for upload
|
||||||
|
bool isRigSuitableForJointPositionUpload( const std::vector<std::string> &jointListFromAsset );
|
||||||
|
|
||||||
|
void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
|
||||||
|
const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
|
||||||
|
|
||||||
|
const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
|
||||||
|
void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
|
||||||
|
|
||||||
|
const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
|
||||||
|
void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// isNodeAJoint()
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
bool isNodeAJoint(const char* name)
|
||||||
|
{
|
||||||
|
return mJointMap.find(name) != mJointMap.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
LLModelLoader::load_callback_t mLoadCallback;
|
||||||
|
LLModelLoader::joint_lookup_func_t mJointLookupFunc;
|
||||||
|
LLModelLoader::texture_load_func_t mTextureLoadFunc;
|
||||||
|
LLModelLoader::state_callback_t mStateCallback;
|
||||||
|
void* mOpaqueData;
|
||||||
|
|
||||||
|
bool mRigParityWithScene;
|
||||||
|
bool mRigValidJointUpload;
|
||||||
|
bool mLegacyRigValid;
|
||||||
|
|
||||||
|
bool mNoNormalize;
|
||||||
|
bool mNoOptimize;
|
||||||
|
|
||||||
|
JointSet mMasterJointList;
|
||||||
|
JointSet mMasterLegacyJointList;
|
||||||
|
JointTransformMap mJointTransformMap;
|
||||||
|
|
||||||
|
static std::list<LLModelLoader*> sActiveLoaderList;
|
||||||
|
static bool isAlive(LLModelLoader* loader) ;
|
||||||
|
};
|
||||||
|
class LLMatrix4a;
|
||||||
|
void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform);
|
||||||
|
void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform);
|
||||||
|
|
||||||
|
#endif // LL_LLMODELLOADER_H
|
||||||
@@ -655,7 +655,6 @@ set(viewer_HEADER_FILES
|
|||||||
llavataractions.h
|
llavataractions.h
|
||||||
llavatarpropertiesprocessor.h
|
llavatarpropertiesprocessor.h
|
||||||
llbox.h
|
llbox.h
|
||||||
llcallbacklist.h
|
|
||||||
llcallingcard.h
|
llcallingcard.h
|
||||||
llcapabilitylistener.h
|
llcapabilitylistener.h
|
||||||
llcaphttpsender.h
|
llcaphttpsender.h
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ void LLCallbackList::addFunction( callback_t func, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOL LLCallbackList::containsFunction( callback_t func, void *data)
|
bool LLCallbackList::containsFunction( callback_t func, void *data)
|
||||||
{
|
{
|
||||||
callback_pair_t t(func, data);
|
callback_pair_t t(func, data);
|
||||||
callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
|
callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
|
||||||
@@ -85,7 +85,7 @@ BOOL LLCallbackList::containsFunction( callback_t func, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOL LLCallbackList::deleteFunction( callback_t func, void *data)
|
bool LLCallbackList::deleteFunction( callback_t func, void *data)
|
||||||
{
|
{
|
||||||
callback_pair_t t(func, data);
|
callback_pair_t t(func, data);
|
||||||
callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
|
callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
|
||||||
|
|||||||
@@ -339,6 +339,34 @@ void LLFace::dirtyTexture()
|
|||||||
gPipeline.markTextured(drawablep);
|
gPipeline.markTextured(drawablep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLFace::notifyAboutCreatingTexture(LLViewerTexture *texture)
|
||||||
|
{
|
||||||
|
LLDrawable* drawablep = getDrawable();
|
||||||
|
if(mVObjp.notNull() && mVObjp->getVolume())
|
||||||
|
{
|
||||||
|
LLVOVolume *vobj = drawablep->getVOVolume();
|
||||||
|
if(vobj && vobj->notifyAboutCreatingTexture(texture))
|
||||||
|
{
|
||||||
|
gPipeline.markTextured(drawablep);
|
||||||
|
gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLFace::notifyAboutMissingAsset(LLViewerTexture *texture)
|
||||||
|
{
|
||||||
|
LLDrawable* drawablep = getDrawable();
|
||||||
|
if(mVObjp.notNull() && mVObjp->getVolume())
|
||||||
|
{
|
||||||
|
LLVOVolume *vobj = drawablep->getVOVolume();
|
||||||
|
if(vobj && vobj->notifyAboutMissingAsset(texture))
|
||||||
|
{
|
||||||
|
gPipeline.markTextured(drawablep);
|
||||||
|
gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture)
|
void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture)
|
||||||
{
|
{
|
||||||
llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
|
llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
|
||||||
@@ -989,6 +1017,10 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po
|
|||||||
const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
|
const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
|
||||||
const LLVector4a& normal = vf.mNormals[0];
|
const LLVector4a& normal = vf.mNormals[0];
|
||||||
const LLVector4a& tangent = vf.mTangents[0];
|
const LLVector4a& tangent = vf.mTangents[0];
|
||||||
|
if (!&tangent)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LLVector4a binormal;
|
LLVector4a binormal;
|
||||||
binormal.setCross3(normal, tangent);
|
binormal.setCross3(normal, tangent);
|
||||||
@@ -1648,7 +1680,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||||||
do_xform = false;
|
do_xform = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getVirtualSize() >= MIN_TEX_ANIM_SIZE)
|
if (getVirtualSize() >= MIN_TEX_ANIM_SIZE || isState(LLFace::RIGGED))
|
||||||
{ //don't override texture transform during tc bake
|
{ //don't override texture transform during tc bake
|
||||||
tex_mode = 0;
|
tex_mode = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -237,6 +237,9 @@ public:
|
|||||||
|
|
||||||
static U32 getRiggedDataMask(U32 type);
|
static U32 getRiggedDataMask(U32 type);
|
||||||
|
|
||||||
|
void notifyAboutCreatingTexture(LLViewerTexture *texture);
|
||||||
|
void notifyAboutMissingAsset(LLViewerTexture *texture);
|
||||||
|
|
||||||
public: //aligned members
|
public: //aligned members
|
||||||
LL_ALIGN_16(LLVector4a mExtents[2]);
|
LL_ALIGN_16(LLVector4a mExtents[2]);
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,31 +2,25 @@
|
|||||||
* @file llfloatermodelpreview.h
|
* @file llfloatermodelpreview.h
|
||||||
* @brief LLFloaterModelPreview class definition
|
* @brief LLFloaterModelPreview class definition
|
||||||
*
|
*
|
||||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||||
*
|
|
||||||
* Copyright (c) 2010, Linden Research, Inc.
|
|
||||||
*
|
|
||||||
* Second Life Viewer Source Code
|
* Second Life Viewer Source Code
|
||||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
* Copyright (C) 2010, Linden Research, Inc.
|
||||||
* 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
|
* This library is free software; you can redistribute it and/or
|
||||||
* it is applied to this Source Code. View the full text of the exception
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
* License as published by the Free Software Foundation;
|
||||||
* online at
|
* version 2.1 of the License only.
|
||||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
||||||
*
|
*
|
||||||
* By copying, modifying or distributing this software, you acknowledge
|
* This library is distributed in the hope that it will be useful,
|
||||||
* that you have read and understood your obligations described above,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* and agree to abide by those obligations.
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
*
|
*
|
||||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
* License along with this library; if not, write to the Free Software
|
||||||
* COMPLETENESS OR PERFORMANCE.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||||
* $/LicenseInfo$
|
* $/LicenseInfo$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -42,105 +36,24 @@
|
|||||||
#include "llviewermenufile.h"
|
#include "llviewermenufile.h"
|
||||||
#include "llfloatermodeluploadbase.h"
|
#include "llfloatermodeluploadbase.h"
|
||||||
|
|
||||||
|
#include "lldaeloader.h"
|
||||||
|
|
||||||
class LLComboBox;
|
class LLComboBox;
|
||||||
|
class LLJoint;
|
||||||
|
class LLViewerJointMesh;
|
||||||
class LLVOAvatar;
|
class LLVOAvatar;
|
||||||
class LLVertexBuffer;
|
class LLVertexBuffer;
|
||||||
class LLModelPreview;
|
class LLModelPreview;
|
||||||
class LLFloaterModelPreview;
|
class LLFloaterModelPreview;
|
||||||
|
class DAE;
|
||||||
class daeElement;
|
class daeElement;
|
||||||
class domProfile_COMMON;
|
class domProfile_COMMON;
|
||||||
class domInstance_geometry;
|
class domInstance_geometry;
|
||||||
class domNode;
|
class domNode;
|
||||||
class domTranslate;
|
class domTranslate;
|
||||||
class domController;
|
class domController;
|
||||||
|
class domSkin;
|
||||||
typedef std::map<std::string, LLMatrix4> JointTransformMap;
|
class domMesh;
|
||||||
typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
|
|
||||||
|
|
||||||
const S32 NUM_LOD = 4;
|
|
||||||
|
|
||||||
class LLModelLoader : public LLThread
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
STARTING = 0,
|
|
||||||
READING_FILE,
|
|
||||||
CREATING_FACES,
|
|
||||||
GENERATING_VERTEX_BUFFERS,
|
|
||||||
GENERATING_LOD,
|
|
||||||
DONE,
|
|
||||||
ERROR_PARSING, //basically loading failed
|
|
||||||
ERROR_MATERIALS,
|
|
||||||
} eLoadState;
|
|
||||||
|
|
||||||
U32 mState;
|
|
||||||
std::string mFilename;
|
|
||||||
S32 mLod;
|
|
||||||
LLModelPreview* mPreview;
|
|
||||||
LLMatrix4 mTransform;
|
|
||||||
BOOL mFirstTransform;
|
|
||||||
LLVector3 mExtents[2];
|
|
||||||
bool mTrySLM;
|
|
||||||
|
|
||||||
std::map<daeElement*, LLPointer<LLModel> > mModel;
|
|
||||||
|
|
||||||
typedef std::vector<LLPointer<LLModel> > model_list;
|
|
||||||
model_list mModelList;
|
|
||||||
|
|
||||||
typedef std::vector<LLModelInstance> model_instance_list;
|
|
||||||
|
|
||||||
typedef std::map<LLMatrix4, model_instance_list > scene;
|
|
||||||
|
|
||||||
scene mScene;
|
|
||||||
|
|
||||||
typedef std::queue<LLPointer<LLModel> > model_queue;
|
|
||||||
|
|
||||||
//queue of models that need a physics rep
|
|
||||||
model_queue mPhysicsQ;
|
|
||||||
|
|
||||||
LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,
|
|
||||||
std::deque<std::string>& jointsFromNodes);
|
|
||||||
~LLModelLoader() ;
|
|
||||||
|
|
||||||
virtual void run();
|
|
||||||
bool doLoadModel();
|
|
||||||
bool loadFromSLM(const std::string& filename);
|
|
||||||
void loadModelCallback();
|
|
||||||
|
|
||||||
void loadTextures() ; //called in the main thread.
|
|
||||||
void processElement(daeElement* element, bool& badElement);
|
|
||||||
std::map<std::string, LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);
|
|
||||||
LLImportMaterial profileToMaterial(domProfile_COMMON* material);
|
|
||||||
std::string getElementLabel(daeElement *element);
|
|
||||||
LLColor4 getDaeColor(daeElement* element);
|
|
||||||
|
|
||||||
daeElement* getChildFromElement(daeElement* pElement, std::string const & name);
|
|
||||||
|
|
||||||
bool isNodeAJoint(domNode* pNode);
|
|
||||||
void processJointNode(domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms);
|
|
||||||
void extractTranslation(domTranslate* pTranslate, LLMatrix4& transform);
|
|
||||||
void extractTranslationViaElement(daeElement* pTranslateElement, LLMatrix4& transform);
|
|
||||||
void extractTranslationViaSID(daeElement* pElement, LLMatrix4& transform);
|
|
||||||
|
|
||||||
void setLoadState(U32 state);
|
|
||||||
|
|
||||||
void buildJointToNodeMappingFromScene(daeElement* pRoot);
|
|
||||||
void processJointToNodeMapping(domNode* pNode);
|
|
||||||
void processChildJoints(domNode* pParentNode);
|
|
||||||
|
|
||||||
//map of avatar joints as named in COLLADA assets to internal joint names
|
|
||||||
std::map<std::string, std::string> mJointMap;
|
|
||||||
JointTransformMap& mJointList;
|
|
||||||
std::deque<std::string>& mJointsFromNode;
|
|
||||||
|
|
||||||
S32 mNumOfFetchingTextures ; //updated in the main thread
|
|
||||||
bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::list<LLModelLoader*> sActiveLoaderList;
|
|
||||||
static bool isAlive(LLModelLoader* loader) ;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LLFloaterModelPreview : public LLFloaterModelUploadBase
|
class LLFloaterModelPreview : public LLFloaterModelUploadBase
|
||||||
{
|
{
|
||||||
@@ -171,7 +84,8 @@ public:
|
|||||||
BOOL handleHover(S32 x, S32 y, MASK mask);
|
BOOL handleHover(S32 x, S32 y, MASK mask);
|
||||||
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
|
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
|
||||||
|
|
||||||
/*virtual*/ void onOpen(/*const LLSD& key*/);
|
/*virtual*/ void onOpen();
|
||||||
|
/*virtual*/ void onClose(bool app_quitting);
|
||||||
|
|
||||||
static void onMouseCaptureLostModelPreview(LLMouseHandler*);
|
static void onMouseCaptureLostModelPreview(LLMouseHandler*);
|
||||||
static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
|
static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
|
||||||
@@ -211,6 +125,8 @@ public:
|
|||||||
|
|
||||||
/*virtual*/ void onModelUploadFailure();
|
/*virtual*/ void onModelUploadFailure();
|
||||||
|
|
||||||
|
bool isModelUploadAllowed();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class LLModelPreview;
|
friend class LLModelPreview;
|
||||||
friend class LLPhysicsDecomp;
|
friend class LLPhysicsDecomp;
|
||||||
@@ -339,8 +255,12 @@ public:
|
|||||||
void clearModel(S32 lod);
|
void clearModel(S32 lod);
|
||||||
void loadModel(std::string filename, S32 lod, bool force_disable_slm = false);
|
void loadModel(std::string filename, S32 lod, bool force_disable_slm = false);
|
||||||
void loadModelCallback(S32 lod);
|
void loadModelCallback(S32 lod);
|
||||||
|
bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); }
|
||||||
|
void queryLODs() { mGenLOD = true; };
|
||||||
void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
|
void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
|
||||||
|
void genModelBBox(); // Generate just a model BBox if we can't generate proper LOD
|
||||||
void generateNormals();
|
void generateNormals();
|
||||||
|
void restoreNormals();
|
||||||
U32 calcResourceCost();
|
U32 calcResourceCost();
|
||||||
void rebuildUploadData();
|
void rebuildUploadData();
|
||||||
void saveUploadData(bool save_skinweights, bool save_joint_poisitions);
|
void saveUploadData(bool save_skinweights, bool save_joint_poisitions);
|
||||||
@@ -354,44 +274,51 @@ public:
|
|||||||
|
|
||||||
const bool getModelPivot(void) const { return mHasPivot; }
|
const bool getModelPivot(void) const { return mHasPivot; }
|
||||||
void setHasPivot(bool val) { mHasPivot = val; }
|
void setHasPivot(bool val) { mHasPivot = val; }
|
||||||
void setModelPivot(const LLVector3& pivot) { mModelPivot = pivot; }
|
void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
|
||||||
|
|
||||||
//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
|
|
||||||
void critiqueRigForUploadApplicability(const std::vector<std::string> &jointListFromAsset);
|
|
||||||
void critiqueJointToNodeMappingFromScene(void);
|
|
||||||
//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
|
//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
|
||||||
//Accessors for joint position upload friendly rigs
|
//Accessors for joint position upload friendly rigs
|
||||||
const bool isRigValidForJointPositionUpload(void) const { return mRigValidJointUpload; }
|
const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
|
||||||
void setRigValidForJointPositionUpload(bool rigValid) { mRigValidJointUpload = rigValid; }
|
void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
|
||||||
bool isRigSuitableForJointPositionUpload(const std::vector<std::string> &jointListFromAsset);
|
|
||||||
//Determines if a rig is a legacy from the joint list
|
|
||||||
bool isRigLegacy(const std::vector<std::string> &jointListFromAsset);
|
|
||||||
//Accessors for the legacy rigs
|
//Accessors for the legacy rigs
|
||||||
const bool isLegacyRigValid(void) const { return mLegacyRigValid; }
|
const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
|
||||||
void setLegacyRigValid(bool rigValid) { mLegacyRigValid = rigValid; }
|
void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
|
||||||
//Verify that a controller matches vertex counts
|
|
||||||
bool verifyController(domController* pController);
|
|
||||||
|
|
||||||
static void textureLoadedCallback(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata);
|
static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
|
||||||
|
static bool lodQueryCallback();
|
||||||
boost::signals2::connection setDetailsCallback(const details_signal_t::slot_type& cb){ return mDetailsSignal.connect(cb); }
|
|
||||||
boost::signals2::connection setModelLoadedCallback(const model_loaded_signal_t::slot_type& cb){ return mModelLoadedSignal.connect(cb); }
|
boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){ return mDetailsSignal.connect(cb); }
|
||||||
boost::signals2::connection setModelUpdatedCallback(const model_updated_signal_t::slot_type& cb){ return mModelUpdatedSignal.connect(cb); }
|
boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){ return mModelLoadedSignal.connect(cb); }
|
||||||
|
boost::signals2::connection setModelUpdatedCallback( const model_updated_signal_t::slot_type& cb ){ return mModelUpdatedSignal.connect(cb); }
|
||||||
void setLoadState(U32 state) { mLoadState = state; }
|
|
||||||
|
void setLoadState( U32 state ) { mLoadState = state; }
|
||||||
U32 getLoadState() { return mLoadState; }
|
U32 getLoadState() { return mLoadState; }
|
||||||
void setRigWithSceneParity(bool state) { mRigParityWithScene = state; }
|
void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
|
||||||
const bool getRigWithSceneParity(void) const { return mRigParityWithScene; }
|
const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
|
||||||
|
|
||||||
|
LLVector3 getTranslationForJointOffset( std::string joint );
|
||||||
|
|
||||||
LLVector3 getTranslationForJointOffset(std::string joint);
|
static bool sIgnoreLoadedCallback;
|
||||||
|
std::vector<S32> mLodsQuery;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
static void loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque);
|
||||||
|
static void stateChangedCallback(U32 state, void* opaque);
|
||||||
|
|
||||||
|
static LLJoint* lookupJointByName(const std::string&, void* opaque);
|
||||||
|
static U32 loadTextures(LLImportMaterial& material, void* opaque);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//Utility function for controller vertex compare
|
//Utility function for controller vertex compare
|
||||||
bool verifyCount(int expected, int result);
|
bool verifyCount( int expected, int result );
|
||||||
//Creates the dummy avatar for the preview window
|
//Creates the dummy avatar for the preview window
|
||||||
void createPreviewAvatar(void);
|
void createPreviewAvatar( void );
|
||||||
//Accessor for the dummy avatar
|
//Accessor for the dummy avatar
|
||||||
LLVOAvatar* getPreviewAvatar(void) { return mPreviewAvatar; }
|
LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; }
|
||||||
|
// Count amount of original models, excluding sub-models
|
||||||
|
static U32 countRootModels(LLModelLoader::model_list models);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class LLModelLoader;
|
friend class LLModelLoader;
|
||||||
@@ -413,12 +340,14 @@ private:
|
|||||||
LLVector3 mPreviewTarget;
|
LLVector3 mPreviewTarget;
|
||||||
LLVector3 mPreviewScale;
|
LLVector3 mPreviewScale;
|
||||||
S32 mPreviewLOD;
|
S32 mPreviewLOD;
|
||||||
|
S32 mPhysicsSearchLOD;
|
||||||
U32 mResourceCost;
|
U32 mResourceCost;
|
||||||
std::string mLODFile[LLModel::NUM_LODS];
|
std::string mLODFile[LLModel::NUM_LODS];
|
||||||
bool mLoading;
|
bool mLoading;
|
||||||
U32 mLoadState;
|
U32 mLoadState;
|
||||||
bool mResetJoints;
|
bool mResetJoints;
|
||||||
bool mRigParityWithScene;
|
bool mRigParityWithScene;
|
||||||
|
bool mModelNoErrors;
|
||||||
|
|
||||||
std::map<std::string, bool> mViewOption;
|
std::map<std::string, bool> mViewOption;
|
||||||
|
|
||||||
@@ -445,6 +374,12 @@ private:
|
|||||||
LLModelLoader::model_list mModel[LLModel::NUM_LODS];
|
LLModelLoader::model_list mModel[LLModel::NUM_LODS];
|
||||||
LLModelLoader::model_list mBaseModel;
|
LLModelLoader::model_list mBaseModel;
|
||||||
|
|
||||||
|
typedef std::vector<LLVolumeFace> v_LLVolumeFace_t;
|
||||||
|
typedef std::vector<v_LLVolumeFace_t> vv_LLVolumeFace_t;
|
||||||
|
|
||||||
|
vv_LLVolumeFace_t mModelFacesCopy[LLModel::NUM_LODS];
|
||||||
|
vv_LLVolumeFace_t mBaseModelFacesCopy;
|
||||||
|
|
||||||
U32 mGroup;
|
U32 mGroup;
|
||||||
std::map<LLPointer<LLModel>, U32> mObject;
|
std::map<LLPointer<LLModel>, U32> mObject;
|
||||||
U32 mMaxTriangleLimit;
|
U32 mMaxTriangleLimit;
|
||||||
@@ -463,16 +398,15 @@ private:
|
|||||||
bool mHasPivot;
|
bool mHasPivot;
|
||||||
|
|
||||||
float mPelvisZOffset;
|
float mPelvisZOffset;
|
||||||
|
|
||||||
bool mRigValidJointUpload;
|
bool mRigValidJointUpload;
|
||||||
bool mLegacyRigValid;
|
bool mLegacyRigValid;
|
||||||
|
|
||||||
bool mLastJointUpdate;
|
bool mLastJointUpdate;
|
||||||
|
|
||||||
std::deque<std::string> mMasterJointList;
|
JointSet mJointsFromNode;
|
||||||
std::deque<std::string> mMasterLegacyJointList;
|
JointTransformMap mJointTransformMap;
|
||||||
std::deque<std::string> mJointsFromNode;
|
|
||||||
JointTransformMap mJointTransformMap;
|
|
||||||
LLPointer<LLVOAvatar> mPreviewAvatar;
|
LLPointer<LLVOAvatar> mPreviewAvatar;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ std::string header_lod[] =
|
|||||||
"medium_lod",
|
"medium_lod",
|
||||||
"high_lod"
|
"high_lod"
|
||||||
};
|
};
|
||||||
|
const char * const LOG_MESH = "Mesh";
|
||||||
|
|
||||||
|
|
||||||
//get the number of bytes resident in memory for given volume
|
//get the number of bytes resident in memory for given volume
|
||||||
@@ -206,6 +207,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material)
|
||||||
|
{
|
||||||
|
LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData);
|
||||||
|
return ppTex ? (*ppTex).get() : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
|
S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
|
||||||
S32 LLMeshRepoThread::sActiveLODRequests = 0;
|
S32 LLMeshRepoThread::sActiveLODRequests = 0;
|
||||||
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
|
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
|
||||||
@@ -1429,6 +1436,13 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
|
|||||||
{
|
{
|
||||||
LLMeshUploadData data;
|
LLMeshUploadData data;
|
||||||
data.mBaseModel = iter->first;
|
data.mBaseModel = iter->first;
|
||||||
|
|
||||||
|
if (data.mBaseModel->mSubmodelID)
|
||||||
|
{
|
||||||
|
// These are handled below to insure correct parenting order on creation
|
||||||
|
// due to map walking being based on model address (aka random)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
LLModelInstance& first_instance = *(iter->second.begin());
|
LLModelInstance& first_instance = *(iter->second.begin());
|
||||||
for (S32 i = 0; i < 5; i++)
|
for (S32 i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
@@ -1466,7 +1480,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
|
|||||||
data.mModel[LLModel::LOD_IMPOSTOR],
|
data.mModel[LLModel::LOD_IMPOSTOR],
|
||||||
decomp,
|
decomp,
|
||||||
mUploadSkin,
|
mUploadSkin,
|
||||||
mUploadJoints);
|
mUploadJoints,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
data.mBaseModel->mSubmodelID);
|
||||||
|
|
||||||
data.mAssetData = ostr.str();
|
data.mAssetData = ostr.str();
|
||||||
std::string str = ostr.str();
|
std::string str = ostr.str();
|
||||||
@@ -1500,17 +1517,26 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
|
|||||||
instance_entry["scale"] = ll_sd_from_vector3(scale);
|
instance_entry["scale"] = ll_sd_from_vector3(scale);
|
||||||
|
|
||||||
instance_entry["material"] = LL_MCODE_WOOD;
|
instance_entry["material"] = LL_MCODE_WOOD;
|
||||||
instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
|
instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
|
||||||
instance_entry["mesh"] = mesh_index[data.mBaseModel];
|
instance_entry["mesh"] = mesh_index[data.mBaseModel];
|
||||||
|
|
||||||
instance_entry["face_list"] = LLSD::emptyArray();
|
instance_entry["face_list"] = LLSD::emptyArray();
|
||||||
|
|
||||||
S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ;
|
// We want to be able to allow more than 8 materials...
|
||||||
|
//
|
||||||
|
S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
|
||||||
|
|
||||||
for (S32 face_num = 0; face_num < end; face_num++)
|
for (S32 face_num = 0; face_num < end; face_num++)
|
||||||
{
|
{
|
||||||
LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
|
LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
|
||||||
LLSD face_entry = LLSD::emptyMap();
|
LLSD face_entry = LLSD::emptyMap();
|
||||||
LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
|
|
||||||
|
LLViewerFetchedTexture *texture = NULL;
|
||||||
|
|
||||||
|
if (material.mDiffuseMapFilename.size())
|
||||||
|
{
|
||||||
|
texture = FindViewerTexture(material);
|
||||||
|
}
|
||||||
|
|
||||||
if ((texture != NULL) &&
|
if ((texture != NULL) &&
|
||||||
(textures.find(texture) == textures.end()))
|
(textures.find(texture) == textures.end()))
|
||||||
@@ -1525,9 +1551,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
|
|||||||
{
|
{
|
||||||
LLPointer<LLImageJ2C> upload_file =
|
LLPointer<LLImageJ2C> upload_file =
|
||||||
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
|
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
|
||||||
|
|
||||||
|
if (!upload_file.isNull() && upload_file->getDataSize())
|
||||||
|
{
|
||||||
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
|
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture != NULL &&
|
||||||
|
mUploadTextures &&
|
||||||
|
texture_index.find(texture) == texture_index.end())
|
||||||
|
{
|
||||||
|
texture_index[texture] = texture_num;
|
||||||
|
std::string str = texture_str.str();
|
||||||
|
res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
|
||||||
|
texture_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subset of TextureEntry fields.
|
||||||
|
if (texture != NULL && mUploadTextures)
|
||||||
|
{
|
||||||
|
face_entry["image"] = texture_index[texture];
|
||||||
|
face_entry["scales"] = 1.0;
|
||||||
|
face_entry["scalet"] = 1.0;
|
||||||
|
face_entry["offsets"] = 0.0;
|
||||||
|
face_entry["offsett"] = 0.0;
|
||||||
|
face_entry["imagerot"] = 0.0;
|
||||||
|
}
|
||||||
|
face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
|
||||||
|
face_entry["fullbright"] = material.mFullbright;
|
||||||
|
instance_entry["face_list"][face_num] = face_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
res["instance_list"][instance_num] = instance_entry;
|
||||||
|
instance_num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
|
||||||
|
{
|
||||||
|
LLMeshUploadData data;
|
||||||
|
data.mBaseModel = iter->first;
|
||||||
|
|
||||||
|
if (!data.mBaseModel->mSubmodelID)
|
||||||
|
{
|
||||||
|
// These were handled above already...
|
||||||
|
//
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLModelInstance& first_instance = *(iter->second.begin());
|
||||||
|
for (S32 i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
data.mModel[i] = first_instance.mLOD[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh_index.find(data.mBaseModel) == mesh_index.end())
|
||||||
|
{
|
||||||
|
// Have not seen this model before - create a new mesh_list entry for it.
|
||||||
|
if (model_name.empty())
|
||||||
|
{
|
||||||
|
model_name = data.mBaseModel->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model_metric.empty())
|
||||||
|
{
|
||||||
|
model_metric = data.mBaseModel->getMetric();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ostr;
|
||||||
|
|
||||||
|
LLModel::Decomposition& decomp =
|
||||||
|
data.mModel[LLModel::LOD_PHYSICS].notNull() ?
|
||||||
|
data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
|
||||||
|
data.mBaseModel->mPhysics;
|
||||||
|
|
||||||
|
decomp.mBaseHull = mHullMap[data.mBaseModel];
|
||||||
|
|
||||||
|
LLSD mesh_header = LLModel::writeModel(
|
||||||
|
ostr,
|
||||||
|
data.mModel[LLModel::LOD_PHYSICS],
|
||||||
|
data.mModel[LLModel::LOD_HIGH],
|
||||||
|
data.mModel[LLModel::LOD_MEDIUM],
|
||||||
|
data.mModel[LLModel::LOD_LOW],
|
||||||
|
data.mModel[LLModel::LOD_IMPOSTOR],
|
||||||
|
decomp,
|
||||||
|
mUploadSkin,
|
||||||
|
mUploadJoints,
|
||||||
|
FALSE,
|
||||||
|
FALSE,
|
||||||
|
data.mBaseModel->mSubmodelID);
|
||||||
|
|
||||||
|
data.mAssetData = ostr.str();
|
||||||
|
std::string str = ostr.str();
|
||||||
|
|
||||||
|
res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
|
||||||
|
mesh_index[data.mBaseModel] = mesh_num;
|
||||||
|
mesh_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all instances that use this model
|
||||||
|
for (instance_list::iterator instance_iter = iter->second.begin();
|
||||||
|
instance_iter != iter->second.end();
|
||||||
|
++instance_iter)
|
||||||
|
{
|
||||||
|
|
||||||
|
LLModelInstance& instance = *instance_iter;
|
||||||
|
|
||||||
|
LLSD instance_entry;
|
||||||
|
|
||||||
|
for (S32 i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
data.mModel[i] = instance.mLOD[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVector3 pos, scale;
|
||||||
|
LLQuaternion rot;
|
||||||
|
LLMatrix4 transformation = instance.mTransform;
|
||||||
|
decomposeMeshMatrix(transformation,pos,rot,scale);
|
||||||
|
instance_entry["position"] = ll_sd_from_vector3(pos);
|
||||||
|
instance_entry["rotation"] = ll_sd_from_quaternion(rot);
|
||||||
|
instance_entry["scale"] = ll_sd_from_vector3(scale);
|
||||||
|
|
||||||
|
instance_entry["material"] = LL_MCODE_WOOD;
|
||||||
|
instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE);
|
||||||
|
instance_entry["mesh"] = mesh_index[data.mBaseModel];
|
||||||
|
|
||||||
|
instance_entry["face_list"] = LLSD::emptyArray();
|
||||||
|
|
||||||
|
// We want to be able to allow more than 8 materials...
|
||||||
|
//
|
||||||
|
S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
|
||||||
|
|
||||||
|
for (S32 face_num = 0; face_num < end; face_num++)
|
||||||
|
{
|
||||||
|
LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
|
||||||
|
LLSD face_entry = LLSD::emptyMap();
|
||||||
|
|
||||||
|
LLViewerFetchedTexture *texture = NULL;
|
||||||
|
|
||||||
|
if (material.mDiffuseMapFilename.size())
|
||||||
|
{
|
||||||
|
texture = FindViewerTexture(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((texture != NULL) &&
|
||||||
|
(textures.find(texture) == textures.end()))
|
||||||
|
{
|
||||||
|
textures.insert(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream texture_str;
|
||||||
|
if (texture != NULL && include_textures && mUploadTextures)
|
||||||
|
{
|
||||||
|
if(texture->hasSavedRawImage())
|
||||||
|
{
|
||||||
|
LLPointer<LLImageJ2C> upload_file =
|
||||||
|
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
|
||||||
|
|
||||||
|
if (!upload_file.isNull() && upload_file->getDataSize())
|
||||||
|
{
|
||||||
|
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (texture != NULL &&
|
if (texture != NULL &&
|
||||||
mUploadTextures &&
|
mUploadTextures &&
|
||||||
@@ -2165,7 +2353,7 @@ void LLMeshRepository::init()
|
|||||||
|
|
||||||
void LLMeshRepository::shutdown()
|
void LLMeshRepository::shutdown()
|
||||||
{
|
{
|
||||||
LL_INFOS() << "Shutting down mesh repository." << LL_ENDL;
|
LL_INFOS(LOG_MESH) << "Shutting down mesh repository." << LL_ENDL;
|
||||||
|
|
||||||
mThread->mSignal->signal();
|
mThread->mSignal->signal();
|
||||||
|
|
||||||
@@ -2179,7 +2367,7 @@ void LLMeshRepository::shutdown()
|
|||||||
delete mMeshMutex;
|
delete mMeshMutex;
|
||||||
mMeshMutex = NULL;
|
mMeshMutex = NULL;
|
||||||
|
|
||||||
LL_INFOS() << "Shutting down decomposition system." << LL_ENDL;
|
LL_INFOS(LOG_MESH) << "Shutting down decomposition system." << LL_ENDL;
|
||||||
|
|
||||||
if (mDecompThread)
|
if (mDecompThread)
|
||||||
{
|
{
|
||||||
@@ -2407,7 +2595,8 @@ void LLMeshRepository::notifyLoadedMeshes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//sort by "score"
|
//sort by "score"
|
||||||
std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
|
std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count,
|
||||||
|
mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
|
||||||
|
|
||||||
while (!mPendingRequests.empty() && push_count > 0)
|
while (!mPendingRequests.empty() && push_count > 0)
|
||||||
{
|
{
|
||||||
@@ -2461,9 +2650,8 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info)
|
|||||||
vobj->notifyMeshLoaded();
|
vobj->notifyMeshLoaded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mLoadingSkins.erase(info.mMeshID);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLoadingSkins.erase(info.mMeshID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp)
|
void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp)
|
||||||
@@ -2472,18 +2660,18 @@ void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decom
|
|||||||
if (iter == mDecompositionMap.end())
|
if (iter == mDecompositionMap.end())
|
||||||
{ //just insert decomp into map
|
{ //just insert decomp into map
|
||||||
mDecompositionMap[decomp->mMeshID] = decomp;
|
mDecompositionMap[decomp->mMeshID] = decomp;
|
||||||
|
mLoadingDecompositions.erase(decomp->mMeshID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //merge decomp with existing entry
|
{ //merge decomp with existing entry
|
||||||
iter->second->merge(decomp);
|
iter->second->merge(decomp);
|
||||||
|
mLoadingDecompositions.erase(decomp->mMeshID);
|
||||||
delete decomp;
|
delete decomp;
|
||||||
}
|
}
|
||||||
|
|
||||||
mLoadingDecompositions.erase(decomp->mMeshID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume)
|
void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume)
|
||||||
{ //called from main thread
|
{ //called from main thread
|
||||||
S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail());
|
S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail());
|
||||||
|
|
||||||
//get list of objects waiting to be notified this mesh is loaded
|
//get list of objects waiting to be notified this mesh is loaded
|
||||||
@@ -2494,7 +2682,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
|
|||||||
//make sure target volume is still valid
|
//make sure target volume is still valid
|
||||||
if (volume->getNumVolumeFaces() <= 0)
|
if (volume->getNumVolumeFaces() <= 0)
|
||||||
{
|
{
|
||||||
LL_WARNS() << "Mesh loading returned empty volume." << LL_ENDL;
|
LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_params.getSculptID()
|
||||||
|
<< LL_ENDL;
|
||||||
}
|
}
|
||||||
|
|
||||||
{ //update system volume
|
{ //update system volume
|
||||||
@@ -2507,7 +2696,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LL_WARNS() << "Couldn't find system volume for given mesh." << LL_ENDL;
|
LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID()
|
||||||
|
<< LL_ENDL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2774,37 +2964,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,
|
|||||||
result_rot = quat_rotation;
|
result_rot = quat_rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
|
|
||||||
{
|
|
||||||
if (mDiffuseMap != rhs.mDiffuseMap)
|
|
||||||
{
|
|
||||||
return mDiffuseMap < rhs.mDiffuseMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDiffuseMapFilename != rhs.mDiffuseMapFilename)
|
|
||||||
{
|
|
||||||
return mDiffuseMapFilename < rhs.mDiffuseMapFilename;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDiffuseMapLabel != rhs.mDiffuseMapLabel)
|
|
||||||
{
|
|
||||||
return mDiffuseMapLabel < rhs.mDiffuseMapLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mDiffuseColor != rhs.mDiffuseColor)
|
|
||||||
{
|
|
||||||
return mDiffuseColor < rhs.mDiffuseColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mBinding != rhs.mBinding)
|
|
||||||
{
|
|
||||||
return mBinding < rhs.mBinding;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mFullbright < rhs.mFullbright;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LLMeshRepository::updateInventory(inventory_data data)
|
void LLMeshRepository::updateInventory(inventory_data data)
|
||||||
{
|
{
|
||||||
LLMutexLock lock(mMeshMutex);
|
LLMutexLock lock(mMeshMutex);
|
||||||
@@ -3036,7 +3195,7 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh, bool vertex_based)
|
|||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
LL_ERRS() << "Convex Decomposition thread valid but could not set mesh data" << LL_ENDL;
|
LL_ERRS(LOG_MESH) << "Convex Decomposition thread valid but could not set mesh data." << LL_ENDL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3112,7 +3271,8 @@ void LLPhysicsDecomp::doDecomposition()
|
|||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
LL_WARNS() << "Convex Decomposition thread valid but could not execute stage " << stage << LL_ENDL;
|
LL_WARNS(LOG_MESH) << "Convex Decomposition thread valid but could not execute stage " << stage << "."
|
||||||
|
<< LL_ENDL;
|
||||||
LLMutexLock lock(mMutex);
|
LLMutexLock lock(mMutex);
|
||||||
|
|
||||||
mCurRequest->mHull.clear();
|
mCurRequest->mHull.clear();
|
||||||
@@ -3243,7 +3403,7 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
|
|||||||
LLCDResult ret = decomp->buildSingleHull() ;
|
LLCDResult ret = decomp->buildSingleHull() ;
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
LL_WARNS() << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL;
|
LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL;
|
||||||
make_box(mCurRequest);
|
make_box(mCurRequest);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -3491,60 +3651,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg)
|
|||||||
mStatusMessage = msg;
|
mStatusMessage = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLModelInstance::LLModelInstance(LLSD& data)
|
|
||||||
{
|
|
||||||
mLocalMeshID = data["mesh_id"].asInteger();
|
|
||||||
mLabel = data["label"].asString();
|
|
||||||
mTransform.setValue(data["transform"]);
|
|
||||||
|
|
||||||
for (U32 i = 0; i < (U32)data["material"].size(); ++i)
|
|
||||||
{
|
|
||||||
LLImportMaterial mat(data["material"][i]);
|
|
||||||
mMaterial[mat.mBinding] = mat;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LLSD LLModelInstance::asLLSD()
|
|
||||||
{
|
|
||||||
LLSD ret;
|
|
||||||
|
|
||||||
ret["mesh_id"] = mModel->mLocalID;
|
|
||||||
ret["label"] = mLabel;
|
|
||||||
ret["transform"] = mTransform.getValue();
|
|
||||||
|
|
||||||
U32 i = 0;
|
|
||||||
for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter)
|
|
||||||
{
|
|
||||||
ret["material"][i++] = iter->second.asLLSD();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLImportMaterial::LLImportMaterial(LLSD& data)
|
|
||||||
{
|
|
||||||
mDiffuseMapFilename = data["diffuse"]["filename"].asString();
|
|
||||||
mDiffuseMapLabel = data["diffuse"]["label"].asString();
|
|
||||||
mDiffuseColor.setValue(data["diffuse"]["color"]);
|
|
||||||
mFullbright = data["fullbright"].asBoolean();
|
|
||||||
mBinding = data["binding"].asString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LLSD LLImportMaterial::asLLSD()
|
|
||||||
{
|
|
||||||
LLSD ret;
|
|
||||||
|
|
||||||
ret["diffuse"]["filename"] = mDiffuseMapFilename;
|
|
||||||
ret["diffuse"]["label"] = mDiffuseMapLabel;
|
|
||||||
ret["diffuse"]["color"] = mDiffuseColor.getValue();
|
|
||||||
ret["fullbright"] = mFullbright;
|
|
||||||
ret["binding"] = mBinding;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
|
void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
|
||||||
{
|
{
|
||||||
decomp.mMesh.resize(decomp.mHull.size());
|
decomp.mMesh.resize(decomp.mHull.size());
|
||||||
|
|||||||
@@ -92,54 +92,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LLImportMaterial
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLPointer<LLViewerFetchedTexture> mDiffuseMap;
|
|
||||||
std::string mDiffuseMapFilename;
|
|
||||||
std::string mDiffuseMapLabel;
|
|
||||||
std::string mBinding;
|
|
||||||
LLColor4 mDiffuseColor;
|
|
||||||
bool mFullbright;
|
|
||||||
|
|
||||||
bool operator<(const LLImportMaterial ¶ms) const;
|
|
||||||
|
|
||||||
LLImportMaterial()
|
|
||||||
: mFullbright(false)
|
|
||||||
{
|
|
||||||
mDiffuseColor.set(1, 1, 1, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLImportMaterial(LLSD& data);
|
|
||||||
|
|
||||||
LLSD asLLSD();
|
|
||||||
};
|
|
||||||
|
|
||||||
class LLModelInstance
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLPointer<LLModel> mModel;
|
|
||||||
LLPointer<LLModel> mLOD[5];
|
|
||||||
|
|
||||||
std::string mLabel;
|
|
||||||
|
|
||||||
LLUUID mMeshID;
|
|
||||||
S32 mLocalMeshID;
|
|
||||||
|
|
||||||
LLMatrix4 mTransform;
|
|
||||||
std::map<std::string, LLImportMaterial> mMaterial;
|
|
||||||
|
|
||||||
LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials)
|
|
||||||
: mModel(model), mLabel(label), mTransform(transform), mMaterial(materials)
|
|
||||||
{
|
|
||||||
mLocalMeshID = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLModelInstance(LLSD& data);
|
|
||||||
|
|
||||||
LLSD asLLSD();
|
|
||||||
};
|
|
||||||
|
|
||||||
class LLPhysicsDecomp : public LLThread
|
class LLPhysicsDecomp : public LLThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -441,6 +393,7 @@ public:
|
|||||||
void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
|
void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
|
||||||
void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
|
void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
|
||||||
|
|
||||||
|
LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material);
|
||||||
private:
|
private:
|
||||||
LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
|
LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
|
||||||
LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
|
LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
|
||||||
|
|||||||
@@ -372,10 +372,17 @@ void LLViewerObject::markDead()
|
|||||||
//</singu>
|
//</singu>
|
||||||
|
|
||||||
// Root object of this hierarchy unlinks itself.
|
// Root object of this hierarchy unlinks itself.
|
||||||
|
LLVOAvatar *av = getAvatarAncestor();
|
||||||
if (getParent())
|
if (getParent())
|
||||||
{
|
{
|
||||||
((LLViewerObject *)getParent())->removeChild(this);
|
((LLViewerObject *)getParent())->removeChild(this);
|
||||||
}
|
}
|
||||||
|
LLUUID mesh_id;
|
||||||
|
if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id))
|
||||||
|
{
|
||||||
|
// This case is needed for indirectly attached mesh objects.
|
||||||
|
av->resetJointPositionsOnDetach(mesh_id);
|
||||||
|
}
|
||||||
|
|
||||||
// Mark itself as dead
|
// Mark itself as dead
|
||||||
mDead = TRUE;
|
mDead = TRUE;
|
||||||
@@ -4798,6 +4805,22 @@ LLVOAvatar* LLViewerObject::asAvatar()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this object is directly or indirectly parented by an avatar, return it.
|
||||||
|
LLVOAvatar* LLViewerObject::getAvatarAncestor()
|
||||||
|
{
|
||||||
|
LLViewerObject *pobj = (LLViewerObject*) getParent();
|
||||||
|
while (pobj)
|
||||||
|
{
|
||||||
|
LLVOAvatar *av = pobj->asAvatar();
|
||||||
|
if (av)
|
||||||
|
{
|
||||||
|
return av;
|
||||||
|
}
|
||||||
|
pobj = (LLViewerObject*) pobj->getParent();
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL LLViewerObject::isParticleSource() const
|
BOOL LLViewerObject::isParticleSource() const
|
||||||
{
|
{
|
||||||
return !mPartSourcep.isNull() && !mPartSourcep->isDead();
|
return !mPartSourcep.isNull() && !mPartSourcep->isDead();
|
||||||
|
|||||||
@@ -141,6 +141,8 @@ public:
|
|||||||
|
|
||||||
virtual LLVOAvatar* asAvatar();
|
virtual LLVOAvatar* asAvatar();
|
||||||
|
|
||||||
|
LLVOAvatar* getAvatarAncestor();
|
||||||
|
|
||||||
static void initVOClasses();
|
static void initVOClasses();
|
||||||
static void cleanupVOClasses();
|
static void cleanupVOClasses();
|
||||||
|
|
||||||
|
|||||||
@@ -536,7 +536,6 @@ void output_statistics(void*)
|
|||||||
LL_INFOS() << "--------------------------------" << LL_ENDL;
|
LL_INFOS() << "--------------------------------" << LL_ENDL;
|
||||||
LL_INFOS() << "Avatar Memory (partly overlaps with above stats):" << LL_ENDL;
|
LL_INFOS() << "Avatar Memory (partly overlaps with above stats):" << LL_ENDL;
|
||||||
LLTexLayerStaticImageList::getInstance()->dumpByteCount();
|
LLTexLayerStaticImageList::getInstance()->dumpByteCount();
|
||||||
LLVOAvatarSelf::dumpScratchTextureByteCount();
|
|
||||||
LLViewerTexLayerSetBuffer::dumpTotalByteCount();
|
LLViewerTexLayerSetBuffer::dumpTotalByteCount();
|
||||||
LLVOAvatarSelf::dumpTotalLocalTextureByteCount();
|
LLVOAvatarSelf::dumpTotalLocalTextureByteCount();
|
||||||
LLTexLayerParamAlpha::dumpCacheByteCount();
|
LLTexLayerParamAlpha::dumpCacheByteCount();
|
||||||
|
|||||||
@@ -614,6 +614,7 @@ LLViewerTexture::~LLViewerTexture()
|
|||||||
// virtual
|
// virtual
|
||||||
void LLViewerTexture::init(bool firstinit)
|
void LLViewerTexture::init(bool firstinit)
|
||||||
{
|
{
|
||||||
|
mSelectedTime = 0.f;
|
||||||
mMaxVirtualSize = 0.f;
|
mMaxVirtualSize = 0.f;
|
||||||
mNeedsGLTexture = FALSE ;
|
mNeedsGLTexture = FALSE ;
|
||||||
mMaxVirtualSizeResetInterval = 1;
|
mMaxVirtualSizeResetInterval = 1;
|
||||||
@@ -639,12 +640,37 @@ S8 LLViewerTexture::getType() const
|
|||||||
|
|
||||||
void LLViewerTexture::cleanup()
|
void LLViewerTexture::cleanup()
|
||||||
{
|
{
|
||||||
mFaceList[LLRender::DIFFUSE_MAP].clear() ;
|
notifyAboutMissingAsset();
|
||||||
mFaceList[LLRender::NORMAL_MAP].clear() ;
|
|
||||||
|
mFaceList[LLRender::DIFFUSE_MAP].clear();
|
||||||
|
mFaceList[LLRender::NORMAL_MAP].clear();
|
||||||
mFaceList[LLRender::SPECULAR_MAP].clear() ;
|
mFaceList[LLRender::SPECULAR_MAP].clear() ;
|
||||||
mVolumeList.clear();
|
mVolumeList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLViewerTexture::notifyAboutCreatingTexture()
|
||||||
|
{
|
||||||
|
for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
|
||||||
|
{
|
||||||
|
for(U32 f = 0; f < mNumFaces[ch]; f++)
|
||||||
|
{
|
||||||
|
mFaceList[ch][f]->notifyAboutCreatingTexture(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLViewerTexture::notifyAboutMissingAsset()
|
||||||
|
{
|
||||||
|
for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
|
||||||
|
{
|
||||||
|
for(U32 f = 0; f < mNumFaces[ch]; f++)
|
||||||
|
{
|
||||||
|
mFaceList[ch][f]->notifyAboutMissingAsset(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// virtual
|
||||||
void LLViewerTexture::dump()
|
void LLViewerTexture::dump()
|
||||||
{
|
{
|
||||||
LLGLTexture::dump();
|
LLGLTexture::dump();
|
||||||
@@ -654,6 +680,30 @@ void LLViewerTexture::dump()
|
|||||||
<< LL_ENDL;
|
<< LL_ENDL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLViewerTexture::setBoostLevel(S32 level)
|
||||||
|
{
|
||||||
|
if(mBoostLevel != level)
|
||||||
|
{
|
||||||
|
mBoostLevel = level;
|
||||||
|
if(mBoostLevel != LLViewerTexture::BOOST_NONE &&
|
||||||
|
mBoostLevel != LLViewerTexture::BOOST_SELECTED)
|
||||||
|
{
|
||||||
|
setNoDelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBoostLevel == LLViewerTexture::BOOST_SELECTED)
|
||||||
|
{
|
||||||
|
mSelectedTime = gFrameTimeSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLViewerTexture::isActiveFetching()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool LLViewerTexture::bindDefaultImage(S32 stage)
|
bool LLViewerTexture::bindDefaultImage(S32 stage)
|
||||||
{
|
{
|
||||||
if (stage < 0) return false;
|
if (stage < 0) return false;
|
||||||
@@ -945,6 +995,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
|
|||||||
{
|
{
|
||||||
mOrigWidth = 0;
|
mOrigWidth = 0;
|
||||||
mOrigHeight = 0;
|
mOrigHeight = 0;
|
||||||
|
mHasAux = FALSE;
|
||||||
mNeedsAux = FALSE;
|
mNeedsAux = FALSE;
|
||||||
mRequestedDiscardLevel = -1;
|
mRequestedDiscardLevel = -1;
|
||||||
mRequestedDownloadPriority = 0.f;
|
mRequestedDownloadPriority = 0.f;
|
||||||
@@ -1002,6 +1053,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
|
|||||||
mLastReferencedSavedRawImageTime = 0.0f ;
|
mLastReferencedSavedRawImageTime = 0.0f ;
|
||||||
mKeptSavedRawImageTime = 0.f ;
|
mKeptSavedRawImageTime = 0.f ;
|
||||||
mLastCallBackActiveTime = 0.f;
|
mLastCallBackActiveTime = 0.f;
|
||||||
|
mForceCallbackFetch = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLViewerFetchedTexture::~LLViewerFetchedTexture()
|
LLViewerFetchedTexture::~LLViewerFetchedTexture()
|
||||||
@@ -1348,6 +1400,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
|
|||||||
//{
|
//{
|
||||||
res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel);
|
res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel);
|
||||||
//resetFaceAtlas() ;
|
//resetFaceAtlas() ;
|
||||||
|
notifyAboutCreatingTexture();
|
||||||
//}
|
//}
|
||||||
setActive() ;
|
setActive() ;
|
||||||
}
|
}
|
||||||
@@ -1666,6 +1719,14 @@ void LLViewerFetchedTexture::updateVirtualSize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//reset whether or not a face was selected after 10 seconds
|
||||||
|
const F32 SELECTION_RESET_TIME = 10.f;
|
||||||
|
|
||||||
|
if (getBoostLevel() == LLViewerTexture::BOOST_SELECTED &&
|
||||||
|
gFrameTimeSeconds - mSelectedTime > SELECTION_RESET_TIME)
|
||||||
|
{
|
||||||
|
setBoostLevel(LLViewerTexture::BOOST_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
if(mMaxVirtualSizeResetCounter > 0)
|
if(mMaxVirtualSizeResetCounter > 0)
|
||||||
{
|
{
|
||||||
@@ -1693,6 +1754,27 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching()
|
|||||||
return current_discard ;
|
return current_discard ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level)
|
||||||
|
{
|
||||||
|
if(debug_level < 0)
|
||||||
|
{
|
||||||
|
mInDebug = FALSE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mInDebug = TRUE;
|
||||||
|
|
||||||
|
mDesiredDiscardLevel = debug_level;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLViewerFetchedTexture::isActiveFetching()
|
||||||
|
{
|
||||||
|
static LLCachedControl<bool> monitor_enabled(gSavedSettings,"DebugShowTextureInfo");
|
||||||
|
|
||||||
|
return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE.
|
||||||
|
}
|
||||||
|
|
||||||
bool LLViewerFetchedTexture::updateFetch()
|
bool LLViewerFetchedTexture::updateFetch()
|
||||||
{
|
{
|
||||||
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
|
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
|
||||||
@@ -1745,7 +1827,11 @@ bool LLViewerFetchedTexture::updateFetch()
|
|||||||
if (mAuxRawImage.notNull()) sAuxCount--;
|
if (mAuxRawImage.notNull()) sAuxCount--;
|
||||||
bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
|
bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
|
||||||
if (mRawImage.notNull()) sRawCount++;
|
if (mRawImage.notNull()) sRawCount++;
|
||||||
if (mAuxRawImage.notNull()) sAuxCount++;
|
if (mAuxRawImage.notNull())
|
||||||
|
{
|
||||||
|
mHasAux = TRUE;
|
||||||
|
sAuxCount++;
|
||||||
|
}
|
||||||
if (finished)
|
if (finished)
|
||||||
{
|
{
|
||||||
mIsFetching = FALSE;
|
mIsFetching = FALSE;
|
||||||
@@ -1808,7 +1894,7 @@ bool LLViewerFetchedTexture::updateFetch()
|
|||||||
if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
|
if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
|
||||||
{
|
{
|
||||||
// We finished but received no data
|
// We finished but received no data
|
||||||
if (current_discard < 0)
|
if (getDiscardLevel() < 0)
|
||||||
{
|
{
|
||||||
LL_WARNS() << "!mIsFetching, setting as missing, decode_priority " << decode_priority
|
LL_WARNS() << "!mIsFetching, setting as missing, decode_priority " << decode_priority
|
||||||
<< " mRawDiscardLevel " << mRawDiscardLevel
|
<< " mRawDiscardLevel " << mRawDiscardLevel
|
||||||
@@ -1820,8 +1906,17 @@ bool LLViewerFetchedTexture::updateFetch()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL;
|
//LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL;
|
||||||
mMinDiscardLevel = current_discard;
|
if(current_discard >= 0)
|
||||||
desired_discard = current_discard;
|
{
|
||||||
|
mMinDiscardLevel = current_discard;
|
||||||
|
desired_discard = current_discard;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
S32 dis_level = getDiscardLevel();
|
||||||
|
mMinDiscardLevel = dis_level;
|
||||||
|
desired_discard = dis_level;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
destroyRawImage();
|
destroyRawImage();
|
||||||
}
|
}
|
||||||
@@ -1959,6 +2054,22 @@ bool LLViewerFetchedTexture::updateFetch()
|
|||||||
return mIsFetching ? true : false;
|
return mIsFetching ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLViewerFetchedTexture::clearFetchedResults()
|
||||||
|
{
|
||||||
|
if(mNeedsCreateTexture || mIsFetching)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup();
|
||||||
|
destroyGLTexture();
|
||||||
|
|
||||||
|
if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate
|
||||||
|
{
|
||||||
|
mGLTexturep->forceToInvalidateGLTexture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LLViewerFetchedTexture::forceToDeleteRequest()
|
void LLViewerFetchedTexture::forceToDeleteRequest()
|
||||||
{
|
{
|
||||||
if (mHasFetcher)
|
if (mHasFetcher)
|
||||||
@@ -1973,26 +2084,42 @@ void LLViewerFetchedTexture::forceToDeleteRequest()
|
|||||||
mDesiredDiscardLevel = getMaxDiscardLevel() + 1; //defer LLAppViewer::getTextureFetch()->deleteRequest to updateFetch?
|
mDesiredDiscardLevel = getMaxDiscardLevel() + 1; //defer LLAppViewer::getTextureFetch()->deleteRequest to updateFetch?
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLViewerFetchedTexture::setIsMissingAsset()
|
void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
|
||||||
{
|
{
|
||||||
if (mUrl.empty())
|
if (is_missing == mIsMissingAsset)
|
||||||
{
|
{
|
||||||
LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL;
|
return;
|
||||||
|
}
|
||||||
|
if (is_missing)
|
||||||
|
{
|
||||||
|
notifyAboutMissingAsset();
|
||||||
|
|
||||||
|
if (mUrl.empty())
|
||||||
|
{
|
||||||
|
LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This may or may not be an error - it is normal to have no
|
||||||
|
// map tile on an empty region, but bad if we're failing on a
|
||||||
|
// server bake texture.
|
||||||
|
LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL;
|
||||||
|
}
|
||||||
|
if (mHasFetcher)
|
||||||
|
{
|
||||||
|
LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
|
||||||
|
mHasFetcher = FALSE;
|
||||||
|
mIsFetching = FALSE;
|
||||||
|
mLastPacketTimer.reset();
|
||||||
|
mFetchState = 0;
|
||||||
|
mFetchPriority = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL;
|
LL_INFOS() << mID << ": un-flagging missing asset" << LL_ENDL;
|
||||||
}
|
}
|
||||||
if (mHasFetcher)
|
mIsMissingAsset = is_missing;
|
||||||
{
|
|
||||||
LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
|
|
||||||
mHasFetcher = FALSE;
|
|
||||||
mIsFetching = FALSE;
|
|
||||||
mLastPacketTimer.reset();
|
|
||||||
mFetchState = 0;
|
|
||||||
mFetchPriority = 0;
|
|
||||||
}
|
|
||||||
mIsMissingAsset = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback,
|
void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback,
|
||||||
@@ -2035,10 +2162,19 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
|
|||||||
}
|
}
|
||||||
if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
|
if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
|
||||||
{
|
{
|
||||||
// We need aux data, but we've already loaded the image, and it didn't have any
|
if(mHasAux)
|
||||||
LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL;
|
{
|
||||||
|
//trigger a refetch
|
||||||
|
forceToRefetchTexture();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We need aux data, but we've already loaded the image, and it didn't have any
|
||||||
|
LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mLastCallBackActiveTime = sCurrentTime ;
|
mLastCallBackActiveTime = sCurrentTime ;
|
||||||
|
mLastReferencedSavedRawImageTime = sCurrentTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLViewerFetchedTexture::clearCallbackEntryList()
|
void LLViewerFetchedTexture::clearCallbackEntryList()
|
||||||
@@ -2151,6 +2287,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:
|
|||||||
}
|
}
|
||||||
mPauseLoadedCallBacks = FALSE ;
|
mPauseLoadedCallBacks = FALSE ;
|
||||||
mLastCallBackActiveTime = sCurrentTime ;
|
mLastCallBackActiveTime = sCurrentTime ;
|
||||||
|
mForceCallbackFetch = TRUE;
|
||||||
if(need_raw)
|
if(need_raw)
|
||||||
{
|
{
|
||||||
mSaveRawImage = TRUE ;
|
mSaveRawImage = TRUE ;
|
||||||
@@ -2191,6 +2328,7 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s
|
|||||||
bool LLViewerFetchedTexture::doLoadedCallbacks()
|
bool LLViewerFetchedTexture::doLoadedCallbacks()
|
||||||
{
|
{
|
||||||
static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds
|
static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds
|
||||||
|
static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds
|
||||||
|
|
||||||
if (mNeedsCreateTexture)
|
if (mNeedsCreateTexture)
|
||||||
{
|
{
|
||||||
@@ -2395,6 +2533,9 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Done with any raw image data at this point (will be re-created if we still have callbacks)
|
||||||
|
destroyRawImage();
|
||||||
|
|
||||||
//
|
//
|
||||||
// If we have no callbacks, take us off of the image callback list.
|
// If we have no callbacks, take us off of the image callback list.
|
||||||
//
|
//
|
||||||
@@ -2402,10 +2543,12 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
|
|||||||
{
|
{
|
||||||
gTextureList.mCallbackList.erase(this);
|
gTextureList.mCallbackList.erase(this);
|
||||||
}
|
}
|
||||||
|
else if(!res && mForceCallbackFetch && sCurrentTime - mLastCallBackActiveTime > MAX_IDLE_WAIT_TIME && !mIsFetching)
|
||||||
// Done with any raw image data at this point (will be re-created if we still have callbacks)
|
{
|
||||||
destroyRawImage();
|
//wait for long enough but no fetching request issued, force one.
|
||||||
|
forceToRefetchTexture(mLoadedCallbackDesiredDiscardLevel, 5.f);
|
||||||
|
mForceCallbackFetch = FALSE; //fire once.
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2487,7 +2630,7 @@ bool LLViewerFetchedTexture::needsToSaveRawImage()
|
|||||||
|
|
||||||
void LLViewerFetchedTexture::destroyRawImage()
|
void LLViewerFetchedTexture::destroyRawImage()
|
||||||
{
|
{
|
||||||
if (mAuxRawImage.notNull())
|
if (mAuxRawImage.notNull() && !needsToSaveRawImage())
|
||||||
{
|
{
|
||||||
sAuxCount--;
|
sAuxCount--;
|
||||||
mAuxRawImage = NULL;
|
mAuxRawImage = NULL;
|
||||||
@@ -2660,7 +2803,25 @@ void LLViewerFetchedTexture::saveRawImage()
|
|||||||
mForceToSaveRawImage = FALSE ;
|
mForceToSaveRawImage = FALSE ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLastReferencedSavedRawImageTime = sCurrentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
//force to refetch the texture to the discard level
|
||||||
|
void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard, F32 kept_time)
|
||||||
|
{
|
||||||
|
if(mForceToSaveRawImage)
|
||||||
|
{
|
||||||
|
desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel);
|
||||||
|
kept_time = llmax(kept_time, mKeptSavedRawImageTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
//trigger a new fetch.
|
||||||
|
mForceToSaveRawImage = TRUE ;
|
||||||
|
mDesiredSavedRawDiscardLevel = desired_discard ;
|
||||||
|
mKeptSavedRawImageTime = kept_time ;
|
||||||
mLastReferencedSavedRawImageTime = sCurrentTime ;
|
mLastReferencedSavedRawImageTime = sCurrentTime ;
|
||||||
|
mSavedRawImage = NULL ;
|
||||||
|
mSavedRawDiscardLevel = -1 ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time)
|
void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time)
|
||||||
@@ -2710,6 +2871,12 @@ void LLViewerFetchedTexture::destroySavedRawImage()
|
|||||||
mDesiredSavedRawDiscardLevel = -1 ;
|
mDesiredSavedRawDiscardLevel = -1 ;
|
||||||
mLastReferencedSavedRawImageTime = 0.0f ;
|
mLastReferencedSavedRawImageTime = 0.0f ;
|
||||||
mKeptSavedRawImageTime = 0.f ;
|
mKeptSavedRawImageTime = 0.f ;
|
||||||
|
|
||||||
|
if(mAuxRawImage.notNull())
|
||||||
|
{
|
||||||
|
sAuxCount--;
|
||||||
|
mAuxRawImage = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LLImageRaw* LLViewerFetchedTexture::getSavedRawImage()
|
LLImageRaw* LLViewerFetchedTexture::getSavedRawImage()
|
||||||
|
|||||||
@@ -132,9 +132,10 @@ public:
|
|||||||
|
|
||||||
/*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
|
/*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
|
||||||
/*virtual*/ void forceImmediateUpdate() ;
|
/*virtual*/ void forceImmediateUpdate() ;
|
||||||
|
/*virtual*/ bool isActiveFetching();
|
||||||
|
|
||||||
/*virtual*/ const LLUUID& getID() const { return mID; }
|
/*virtual*/ const LLUUID& getID() const { return mID; }
|
||||||
//void setBoostLevel(S32 level);
|
void setBoostLevel(S32 level);
|
||||||
S32 getBoostLevel() { return mBoostLevel; }
|
S32 getBoostLevel() { return mBoostLevel; }
|
||||||
|
|
||||||
void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;
|
void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;
|
||||||
@@ -147,6 +148,8 @@ public:
|
|||||||
|
|
||||||
LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
|
LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
|
||||||
|
|
||||||
|
S32 getFullWidth() const { return mFullWidth; }
|
||||||
|
S32 getFullHeight() const { return mFullHeight; }
|
||||||
/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
|
/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
|
||||||
|
|
||||||
virtual void addFace(U32 channel, LLFace* facep) ;
|
virtual void addFace(U32 channel, LLFace* facep) ;
|
||||||
@@ -174,6 +177,10 @@ protected:
|
|||||||
void init(bool firstinit) ;
|
void init(bool firstinit) ;
|
||||||
void reorganizeFaceList() ;
|
void reorganizeFaceList() ;
|
||||||
void reorganizeVolumeList() ;
|
void reorganizeVolumeList() ;
|
||||||
|
|
||||||
|
void notifyAboutMissingAsset();
|
||||||
|
void notifyAboutCreatingTexture();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class LLBumpImageList;
|
friend class LLBumpImageList;
|
||||||
friend class LLUIImageList;
|
friend class LLUIImageList;
|
||||||
@@ -184,7 +191,7 @@ private:
|
|||||||
static bool isMemoryForTextureLow() ;
|
static bool isMemoryForTextureLow() ;
|
||||||
protected:
|
protected:
|
||||||
LLUUID mID;
|
LLUUID mID;
|
||||||
|
F32 mSelectedTime; // time texture was last selected
|
||||||
mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
|
mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
|
||||||
mutable S32 mMaxVirtualSizeResetCounter ;
|
mutable S32 mMaxVirtualSizeResetCounter ;
|
||||||
mutable S32 mMaxVirtualSizeResetInterval;
|
mutable S32 mMaxVirtualSizeResetInterval;
|
||||||
@@ -325,13 +332,17 @@ public:
|
|||||||
void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }
|
void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }
|
||||||
|
|
||||||
bool updateFetch();
|
bool updateFetch();
|
||||||
|
bool setDebugFetching(S32 debug_level);
|
||||||
|
bool isInDebug() {return mInDebug;}
|
||||||
|
|
||||||
|
void clearFetchedResults(); //clear all fetched results, for debug use.
|
||||||
|
|
||||||
// Override the computation of discard levels if we know the exact output
|
// Override the computation of discard levels if we know the exact output
|
||||||
// size of the image. Used for UI textures to not decode, even if we have
|
// size of the image. Used for UI textures to not decode, even if we have
|
||||||
// more data.
|
// more data.
|
||||||
/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
|
/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
|
||||||
|
|
||||||
void setIsMissingAsset();
|
void setIsMissingAsset(BOOL is_missing = true);
|
||||||
/*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
|
/*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
|
||||||
|
|
||||||
// returns dimensions of original image for local files (before power of two scaling)
|
// returns dimensions of original image for local files (before power of two scaling)
|
||||||
@@ -374,6 +385,7 @@ public:
|
|||||||
BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
|
BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
|
||||||
BOOL isRawImageValid()const { return mIsRawImageValid ; }
|
BOOL isRawImageValid()const { return mIsRawImageValid ; }
|
||||||
void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
|
void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
|
||||||
|
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
|
||||||
/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
|
/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
|
||||||
void destroySavedRawImage() ;
|
void destroySavedRawImage() ;
|
||||||
LLImageRaw* getSavedRawImage() ;
|
LLImageRaw* getSavedRawImage() ;
|
||||||
@@ -386,6 +398,7 @@ public:
|
|||||||
|
|
||||||
void forceToDeleteRequest();
|
void forceToDeleteRequest();
|
||||||
void forceRefetch();
|
void forceRefetch();
|
||||||
|
/*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*virtual*/ void switchToCachedImage();
|
/*virtual*/ void switchToCachedImage();
|
||||||
@@ -406,6 +419,8 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BOOL mFullyLoaded;
|
BOOL mFullyLoaded;
|
||||||
|
BOOL mInDebug;
|
||||||
|
BOOL mForceCallbackFetch;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string mLocalFileName;
|
std::string mLocalFileName;
|
||||||
@@ -433,6 +448,7 @@ protected:
|
|||||||
S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have
|
S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have
|
||||||
|
|
||||||
S8 mNeedsAux; // We need to decode the auxiliary channels
|
S8 mNeedsAux; // We need to decode the auxiliary channels
|
||||||
|
S8 mHasAux; // We have aux channels
|
||||||
S8 mDecodingAux; // Are we decoding high components
|
S8 mDecodingAux; // Are we decoding high components
|
||||||
S8 mIsRawImageValid;
|
S8 mIsRawImageValid;
|
||||||
S8 mHasFetcher; // We've made a fecth request
|
S8 mHasFetcher; // We've made a fecth request
|
||||||
|
|||||||
@@ -139,6 +139,8 @@ size_t strnlen(const char *s, size_t n)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
|
||||||
|
|
||||||
const F32 MAX_HOVER_Z = 2.0;
|
const F32 MAX_HOVER_Z = 2.0;
|
||||||
const F32 MIN_HOVER_Z = -2.0;
|
const F32 MIN_HOVER_Z = -2.0;
|
||||||
|
|
||||||
@@ -290,6 +292,9 @@ const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f;
|
|||||||
|
|
||||||
const S32 MORPH_MASK_REQUESTED_DISCARD = 0;
|
const S32 MORPH_MASK_REQUESTED_DISCARD = 0;
|
||||||
|
|
||||||
|
const F32 MAX_STANDOFF_FROM_ORIGIN = 3;
|
||||||
|
const F32 MAX_STANDOFF_DISTANCE_CHANGE = 32;
|
||||||
|
|
||||||
// Discard level at which to switch to baked textures
|
// Discard level at which to switch to baked textures
|
||||||
// Should probably be 4 or 3, but didn't want to change it while change other logic - SJB
|
// Should probably be 4 or 3, but didn't want to change it while change other logic - SJB
|
||||||
const S32 SWITCH_TO_BAKED_DISCARD = 5;
|
const S32 SWITCH_TO_BAKED_DISCARD = 5;
|
||||||
@@ -1092,7 +1097,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||||||
mFullyLoadedInitialized(FALSE),
|
mFullyLoadedInitialized(FALSE),
|
||||||
mSupportsAlphaLayers(FALSE),
|
mSupportsAlphaLayers(FALSE),
|
||||||
mLoadedCallbacksPaused(FALSE),
|
mLoadedCallbacksPaused(FALSE),
|
||||||
mHasPelvisOffset( FALSE ),
|
|
||||||
mLastRezzedStatus(-1),
|
mLastRezzedStatus(-1),
|
||||||
mIsEditingAppearance(FALSE),
|
mIsEditingAppearance(FALSE),
|
||||||
mUseLocalAppearance(FALSE),
|
mUseLocalAppearance(FALSE),
|
||||||
@@ -1166,10 +1170,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
|||||||
mRuthDebugTimer.reset();
|
mRuthDebugTimer.reset();
|
||||||
mDebugExistenceTimer.reset();
|
mDebugExistenceTimer.reset();
|
||||||
mLastAppearanceMessageTimer.reset();
|
mLastAppearanceMessageTimer.reset();
|
||||||
mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
|
|
||||||
mLastPelvisToFoot = 0.0f;
|
|
||||||
mPelvisFixup = 0.0f;
|
|
||||||
mLastPelvisFixup = 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LLVOAvatar::avString() const
|
std::string LLVOAvatar::avString() const
|
||||||
@@ -1524,7 +1524,6 @@ void LLVOAvatar::deleteCachedImages(bool clearAll)
|
|||||||
}
|
}
|
||||||
LLViewerTexLayerSet::sHasCaches = FALSE;
|
LLViewerTexLayerSet::sHasCaches = FALSE;
|
||||||
}
|
}
|
||||||
LLVOAvatarSelf::deleteScratchTextures();
|
|
||||||
LLTexLayerStaticImageList::getInstance()->deleteCachedImages();
|
LLTexLayerStaticImageList::getInstance()->deleteCachedImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1659,23 +1658,25 @@ LLTexLayerSet* LLVOAvatar::createTexLayerSet()
|
|||||||
|
|
||||||
const LLVector3 LLVOAvatar::getRenderPosition() const
|
const LLVector3 LLVOAvatar::getRenderPosition() const
|
||||||
{
|
{
|
||||||
|
|
||||||
if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
|
if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
|
||||||
{
|
{
|
||||||
return getPositionAgent();
|
return getPositionAgent();
|
||||||
}
|
}
|
||||||
else if (isRoot() || !mDrawable->getParent())
|
else if (isRoot() || !mDrawable->getParent())
|
||||||
{
|
{
|
||||||
if ( !mHasPelvisOffset )
|
F32 fixup;
|
||||||
{
|
if ( hasPelvisFixup( fixup) )
|
||||||
return mDrawable->getPositionAgent();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
//Apply a pelvis fixup (as defined by the avs skin)
|
//Apply a pelvis fixup (as defined by the avs skin)
|
||||||
LLVector3 pos = mDrawable->getPositionAgent();
|
LLVector3 pos = mDrawable->getPositionAgent();
|
||||||
pos[VZ] += mPelvisFixup;
|
pos[VZ] += fixup;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return mDrawable->getPositionAgent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2420,11 +2421,16 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
|
|||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
const std::string url = getImageURL(te,uuid);
|
const std::string url = getImageURL(te,uuid);
|
||||||
|
|
||||||
if (!url.empty())
|
if (!url.empty())
|
||||||
{
|
{
|
||||||
LL_DEBUGS("Avatar") << avString() << "from URL " << url << LL_ENDL;
|
LL_DEBUGS("Avatar") << avString() << "from URL " << url << LL_ENDL;
|
||||||
result = LLViewerTextureManager::getFetchedTextureFromUrl(
|
result = LLViewerTextureManager::getFetchedTextureFromUrl(
|
||||||
url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
|
url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
|
||||||
|
if (result->isMissingAsset())
|
||||||
|
{
|
||||||
|
result->setIsMissingAsset(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2569,7 +2575,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
|||||||
|
|
||||||
// animate the character
|
// animate the character
|
||||||
// store off last frame's root position to be consistent with camera position
|
// store off last frame's root position to be consistent with camera position
|
||||||
LLVector3 root_pos_last = mRoot->getWorldPosition();
|
mLastRootPos = mRoot->getWorldPosition();
|
||||||
bool detailed_update;
|
bool detailed_update;
|
||||||
{
|
{
|
||||||
LLFastTimer t(FTM_CHARACTER_UPDATE);
|
LLFastTimer t(FTM_CHARACTER_UPDATE);
|
||||||
@@ -2598,7 +2604,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
|||||||
idleUpdateWindEffect();
|
idleUpdateWindEffect();
|
||||||
}
|
}
|
||||||
|
|
||||||
idleUpdateNameTag(root_pos_last);
|
idleUpdateNameTag( mLastRootPos );
|
||||||
idleUpdateRenderCost();
|
idleUpdateRenderCost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3845,18 +3851,8 @@ void LLVOAvatar::resetFreezeTime()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
void LLVOAvatar::updateDebugText()
|
||||||
// updateCharacter()
|
|
||||||
// called on both your avatar and other avatars
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
|
||||||
{
|
{
|
||||||
// Frozen!
|
|
||||||
if (areAnimationsPaused())
|
|
||||||
{
|
|
||||||
updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again.
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
|
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
|
||||||
{
|
{
|
||||||
@@ -3947,6 +3943,34 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mDebugText.size() && mText.notNull())
|
||||||
|
{
|
||||||
|
mText->markDead();
|
||||||
|
mText = NULL;
|
||||||
|
}
|
||||||
|
else if (mDebugText.size())
|
||||||
|
{
|
||||||
|
setDebugText(mDebugText);
|
||||||
|
}
|
||||||
|
mDebugText.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// updateCharacter()
|
||||||
|
// called on both your avatar and other avatars
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||||
|
{
|
||||||
|
// Frozen!
|
||||||
|
if (areAnimationsPaused())
|
||||||
|
{
|
||||||
|
updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again.
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDebugText();
|
||||||
|
|
||||||
if (gNoRender)
|
if (gNoRender)
|
||||||
{
|
{
|
||||||
// Hack if we're running drones...
|
// Hack if we're running drones...
|
||||||
@@ -3957,9 +3981,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LLVector3d root_pos_global;
|
|
||||||
|
|
||||||
if (!mIsBuilt)
|
if (!mIsBuilt)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@@ -4444,17 +4465,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
|||||||
|
|
||||||
mRoot->updateWorldMatrixChildren();
|
mRoot->updateWorldMatrixChildren();
|
||||||
|
|
||||||
if (!mDebugText.size() && mText.notNull())
|
|
||||||
{
|
|
||||||
mText->markDead();
|
|
||||||
mText = NULL;
|
|
||||||
}
|
|
||||||
else if (mDebugText.size())
|
|
||||||
{
|
|
||||||
setDebugText(mDebugText);
|
|
||||||
}
|
|
||||||
mDebugText.clear();
|
|
||||||
|
|
||||||
//mesh vertices need to be reskinned
|
//mesh vertices need to be reskinned
|
||||||
mNeedsSkin = TRUE;
|
mNeedsSkin = TRUE;
|
||||||
|
|
||||||
@@ -4485,39 +4495,13 @@ void LLVOAvatar::updateHeadOffset()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// setPelvisOffset
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup )
|
|
||||||
{
|
|
||||||
mHasPelvisOffset = hasOffset;
|
|
||||||
if ( mHasPelvisOffset )
|
|
||||||
{
|
|
||||||
//Store off last pelvis to foot value
|
|
||||||
mLastPelvisToFoot = mPelvisToFoot;
|
|
||||||
mPelvisOffset = offsetAmount;
|
|
||||||
mLastPelvisFixup = mPelvisFixup;
|
|
||||||
mPelvisFixup = pelvisFixup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// postPelvisSetRecalc
|
// postPelvisSetRecalc
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
void LLVOAvatar::postPelvisSetRecalc( void )
|
void LLVOAvatar::postPelvisSetRecalc( void )
|
||||||
{
|
{
|
||||||
computeBodySize();
|
mRoot->updateWorldMatrixChildren();
|
||||||
mRoot->touch();
|
computeBodySize();
|
||||||
mRoot->updateWorldMatrixChildren();
|
dirtyMesh(2);
|
||||||
dirtyMesh();
|
|
||||||
updateHeadOffset();
|
|
||||||
}
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
// pelisPoke
|
|
||||||
//------------------------------------------------------------------------
|
|
||||||
void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount )
|
|
||||||
{
|
|
||||||
mHasPelvisOffset = true;
|
|
||||||
mLastPelvisFixup = mPelvisFixup;
|
|
||||||
mPelvisFixup = pelvisFixupAmount;
|
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
// updateVisibility()
|
// updateVisibility()
|
||||||
@@ -5773,6 +5757,12 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
|
|||||||
{
|
{
|
||||||
sitDown(FALSE);
|
sitDown(FALSE);
|
||||||
}
|
}
|
||||||
|
if ((anim_id == ANIM_AGENT_BUSY) && gAgent.isDoNotDisturb())
|
||||||
|
{
|
||||||
|
// re-assert DND tag animation
|
||||||
|
gAgent.sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
stopMotion(anim_id);
|
stopMotion(anim_id);
|
||||||
result = TRUE;
|
result = TRUE;
|
||||||
}
|
}
|
||||||
@@ -5985,11 +5975,163 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
|
|||||||
|
|
||||||
return jointp;
|
return jointp;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// resetJointPositionsToDefault
|
// getRiggedMeshID
|
||||||
|
//
|
||||||
|
// If viewer object is a rigged mesh, set the mesh id and return true.
|
||||||
|
// Otherwise, null out the id and return false.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void LLVOAvatar::resetJointPositionsToDefault( void )
|
// static
|
||||||
|
bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id)
|
||||||
{
|
{
|
||||||
|
mesh_id.setNull();
|
||||||
|
|
||||||
|
//If a VO has a skin that we'll reset the joint positions to their default
|
||||||
|
if ( pVO && pVO->mDrawable )
|
||||||
|
{
|
||||||
|
LLVOVolume* pVObj = pVO->mDrawable->getVOVolume();
|
||||||
|
if ( pVObj )
|
||||||
|
{
|
||||||
|
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
|
||||||
|
if (pSkinData
|
||||||
|
&& pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG // full rig
|
||||||
|
&& pSkinData->mAlternateBindMatrix.size() > 0 )
|
||||||
|
{
|
||||||
|
mesh_id = pSkinData->mMeshID;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLVOAvatar::clearAttachmentPosOverrides()
|
||||||
|
{
|
||||||
|
//Subsequent joints are relative to pelvis
|
||||||
|
avatar_joint_list_t::iterator iter = mSkeleton.begin();
|
||||||
|
avatar_joint_list_t::iterator end = mSkeleton.end();
|
||||||
|
|
||||||
|
for (; iter != end; ++iter)
|
||||||
|
{
|
||||||
|
LLJoint* pJoint = (*iter);
|
||||||
|
pJoint->clearAttachmentPosOverrides();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// addAttachmentPosOverridesForObject
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void LLVOAvatar::addAttachmentPosOverridesForObject(LLViewerObject *vo)
|
||||||
|
{
|
||||||
|
LLVOAvatar *av = vo->getAvatarAncestor();
|
||||||
|
if (!av || (av != this))
|
||||||
|
{
|
||||||
|
LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process all children
|
||||||
|
LLViewerObject::const_child_list_t& children = vo->getChildren();
|
||||||
|
for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
|
||||||
|
it != children.end(); ++it)
|
||||||
|
{
|
||||||
|
LLViewerObject *childp = *it;
|
||||||
|
addAttachmentPosOverridesForObject(childp);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVOVolume *vobj = dynamic_cast<LLVOVolume*>(vo);
|
||||||
|
bool pelvisGotSet = false;
|
||||||
|
|
||||||
|
if (!vobj)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (vobj->isMesh() &&
|
||||||
|
((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
|
||||||
|
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
|
||||||
|
|
||||||
|
if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData )
|
||||||
|
{
|
||||||
|
const int bindCnt = pSkinData->mAlternateBindMatrix.size();
|
||||||
|
if ( bindCnt > 0 )
|
||||||
|
{
|
||||||
|
const U32 jointCnt = pSkinData->mJointNames.size();
|
||||||
|
const F32 pelvisZOffset = pSkinData->mPelvisOffset;
|
||||||
|
const LLUUID& mesh_id = pSkinData->mMeshID;
|
||||||
|
bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;
|
||||||
|
if ( fullRig )
|
||||||
|
{
|
||||||
|
for ( U32 i=0; i<jointCnt; ++i )
|
||||||
|
{
|
||||||
|
std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
|
||||||
|
LLJoint* pJoint = getJoint( lookingForJoint );
|
||||||
|
if ( pJoint && pJoint->getId() != currentId )
|
||||||
|
{
|
||||||
|
pJoint->setId( currentId );
|
||||||
|
const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();
|
||||||
|
//Set the joint position
|
||||||
|
pJoint->addAttachmentPosOverride( jointPos, mesh_id, avString() );
|
||||||
|
|
||||||
|
//If joint is a pelvis then handle old/new pelvis to foot values
|
||||||
|
if ( lookingForJoint == "mPelvis" )
|
||||||
|
{
|
||||||
|
pelvisGotSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pelvisZOffset != 0.0F)
|
||||||
|
{
|
||||||
|
addPelvisFixup( pelvisZOffset, mesh_id );
|
||||||
|
pelvisGotSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Rebuild body data if we altered joints/pelvis
|
||||||
|
if ( pelvisGotSet )
|
||||||
|
{
|
||||||
|
postPelvisSetRecalc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// resetJointPositionsOnDetach
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void LLVOAvatar::resetJointPositionsOnDetach(LLViewerObject *vo)
|
||||||
|
{
|
||||||
|
LLVOAvatar *av = vo->getAvatarAncestor();
|
||||||
|
if (!av || (av != this))
|
||||||
|
{
|
||||||
|
LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process all children
|
||||||
|
LLViewerObject::const_child_list_t& children = vo->getChildren();
|
||||||
|
for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
|
||||||
|
it != children.end(); ++it)
|
||||||
|
{
|
||||||
|
LLViewerObject *childp = *it;
|
||||||
|
resetJointPositionsOnDetach(childp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process self.
|
||||||
|
LLUUID mesh_id;
|
||||||
|
if (getRiggedMeshID(vo,mesh_id))
|
||||||
|
{
|
||||||
|
resetJointPositionsOnDetach(mesh_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// resetJointPositionsOnDetach
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void LLVOAvatar::resetJointPositionsOnDetach(const LLUUID& mesh_id)
|
||||||
|
{
|
||||||
//Subsequent joints are relative to pelvis
|
//Subsequent joints are relative to pelvis
|
||||||
avatar_joint_list_t::iterator iter = mSkeleton.begin();
|
avatar_joint_list_t::iterator iter = mSkeleton.begin();
|
||||||
avatar_joint_list_t::iterator end = mSkeleton.end();
|
avatar_joint_list_t::iterator end = mSkeleton.end();
|
||||||
@@ -6000,24 +6142,19 @@ void LLVOAvatar::resetJointPositionsToDefault( void )
|
|||||||
{
|
{
|
||||||
LLJoint* pJoint = (*iter);
|
LLJoint* pJoint = (*iter);
|
||||||
//Reset joints except for pelvis
|
//Reset joints except for pelvis
|
||||||
if ( pJoint && pJoint != pJointPelvis && pJoint->doesJointNeedToBeReset() )
|
if ( pJoint )
|
||||||
{
|
{
|
||||||
pJoint->setId( LLUUID::null );
|
pJoint->setId( LLUUID::null );
|
||||||
pJoint->restoreOldXform();
|
pJoint->removeAttachmentPosOverride(mesh_id, avString());
|
||||||
}
|
}
|
||||||
else
|
if ( pJoint && pJoint == pJointPelvis)
|
||||||
if ( pJoint && pJoint == pJointPelvis && pJoint->doesJointNeedToBeReset() )
|
|
||||||
{
|
{
|
||||||
pJoint->setId( LLUUID::null );
|
removePelvisFixup( mesh_id );
|
||||||
pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) );
|
pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) );
|
||||||
//pJoint->setJointResetFlag( false ); // Singu TODO
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
postPelvisSetRecalc();
|
||||||
//make sure we don't apply the joint offset
|
|
||||||
mHasPelvisOffset = false;
|
|
||||||
mPelvisFixup = mLastPelvisFixup;
|
|
||||||
postPelvisSetRecalc();
|
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// getCharacterPosition()
|
// getCharacterPosition()
|
||||||
@@ -6461,12 +6598,20 @@ BOOL LLVOAvatar::setParent(LLViewerObject* parent)
|
|||||||
void LLVOAvatar::addChild(LLViewerObject *childp)
|
void LLVOAvatar::addChild(LLViewerObject *childp)
|
||||||
{
|
{
|
||||||
childp->extractAttachmentItemID(); // find the inventory item this object is associated with.
|
childp->extractAttachmentItemID(); // find the inventory item this object is associated with.
|
||||||
|
if (isSelf())
|
||||||
|
{
|
||||||
|
const LLUUID& item_id = childp->getAttachmentItemID();
|
||||||
|
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||||
|
LL_DEBUGS("Avatar") << "ATT attachment child added " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
LLViewerObject::addChild(childp);
|
LLViewerObject::addChild(childp);
|
||||||
if (childp->mDrawable)
|
if (childp->mDrawable)
|
||||||
{
|
{
|
||||||
if (!attachObject(childp))
|
if (!attachObject(childp))
|
||||||
{
|
{
|
||||||
LL_WARNS() << "addChild() failed for "
|
LL_WARNS() << "ATT addChild() failed for "
|
||||||
<< childp->getID()
|
<< childp->getID()
|
||||||
<< " item " << childp->getAttachmentItemID()
|
<< " item " << childp->getAttachmentItemID()
|
||||||
<< LL_ENDL;
|
<< LL_ENDL;
|
||||||
@@ -6552,10 +6697,21 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
|
const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
|
||||||
{
|
{
|
||||||
|
if (isSelf())
|
||||||
|
{
|
||||||
|
const LLUUID& item_id = viewer_object->getAttachmentItemID();
|
||||||
|
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||||
|
LL_DEBUGS("Avatar") << "ATT attaching object "
|
||||||
|
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
|
||||||
|
}
|
||||||
LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
|
LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
|
||||||
|
|
||||||
if (!attachment || !attachment->addObject(viewer_object))
|
if (!attachment || !attachment->addObject(viewer_object))
|
||||||
{
|
{
|
||||||
|
const LLUUID& item_id = viewer_object->getAttachmentItemID();
|
||||||
|
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||||
|
LL_WARNS("Avatar") << "ATT attach failed "
|
||||||
|
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6620,7 +6776,14 @@ void LLVOAvatar::lazyAttach()
|
|||||||
LLPointer<LLViewerObject> cur_attachment = mPendingAttachment[i];
|
LLPointer<LLViewerObject> cur_attachment = mPendingAttachment[i];
|
||||||
if (cur_attachment->mDrawable)
|
if (cur_attachment->mDrawable)
|
||||||
{
|
{
|
||||||
if(!attachObject(cur_attachment))
|
if (isSelf())
|
||||||
|
{
|
||||||
|
const LLUUID& item_id = cur_attachment->getAttachmentItemID();
|
||||||
|
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||||
|
LL_DEBUGS("Avatar") << "ATT attaching object "
|
||||||
|
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
|
||||||
|
}
|
||||||
|
if (!attachObject(cur_attachment))
|
||||||
{ // Drop it
|
{ // Drop it
|
||||||
LL_WARNS() << "attachObject() failed for "
|
LL_WARNS() << "attachObject() failed for "
|
||||||
<< cur_attachment->getID()
|
<< cur_attachment->getID()
|
||||||
@@ -6686,27 +6849,15 @@ void LLVOAvatar::rebuildRiggedAttachments( void )
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
|
void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
|
||||||
{
|
{
|
||||||
//If a VO has a skin that we'll reset the joint positions to their default
|
LLUUID mesh_id;
|
||||||
if ( pVO && pVO->mDrawable )
|
if (getRiggedMeshID(pVO, mesh_id))
|
||||||
{
|
{
|
||||||
LLVOVolume* pVObj = pVO->mDrawable->getVOVolume();
|
resetJointPositionsOnDetach(mesh_id);
|
||||||
if ( pVObj )
|
if ( gAgentCamera.cameraCustomizeAvatar() )
|
||||||
{
|
{
|
||||||
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
|
gAgent.unpauseAnimation();
|
||||||
if ( pSkinData
|
//Still want to refocus on head bone
|
||||||
&& pSkinData->mJointNames.size() > 20 // full rig
|
gAgentCamera.changeCameraToCustomizeAvatar();
|
||||||
&& pSkinData->mAlternateBindMatrix.size() > 0 )
|
|
||||||
{
|
|
||||||
LLVOAvatar::resetJointPositionsToDefault();
|
|
||||||
//Need to handle the repositioning of the cam, updating rig data etc during outfit editing
|
|
||||||
//This handles the case where we detach a replacement rig.
|
|
||||||
if ( gAgentCamera.cameraCustomizeAvatar() )
|
|
||||||
{
|
|
||||||
gAgent.unpauseAnimation();
|
|
||||||
//Still want to refocus on head bone
|
|
||||||
gAgentCamera.changeCameraToCustomizeAvatar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6845,9 +6996,18 @@ void LLVOAvatar::getOffObject()
|
|||||||
LLVector3 cur_position_world = mDrawable->getWorldPosition();
|
LLVector3 cur_position_world = mDrawable->getWorldPosition();
|
||||||
LLQuaternion cur_rotation_world = mDrawable->getWorldRotation();
|
LLQuaternion cur_rotation_world = mDrawable->getWorldRotation();
|
||||||
|
|
||||||
|
if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN
|
||||||
|
&& (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN
|
||||||
|
|| dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE))
|
||||||
|
{
|
||||||
|
// Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent
|
||||||
|
// restore coordinates from cache
|
||||||
|
cur_position_world = mLastRootPos;
|
||||||
|
}
|
||||||
|
|
||||||
// set *local* position based on last *world* position, since we're unparenting the avatar
|
// set *local* position based on last *world* position, since we're unparenting the avatar
|
||||||
mDrawable->mXform.setPosition(cur_position_world);
|
mDrawable->mXform.setPosition(cur_position_world);
|
||||||
mDrawable->mXform.setRotation(cur_rotation_world);
|
mDrawable->mXform.setRotation(cur_rotation_world);
|
||||||
|
|
||||||
gPipeline.markMoved(mDrawable, TRUE);
|
gPipeline.markMoved(mDrawable, TRUE);
|
||||||
|
|
||||||
@@ -7065,6 +7225,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, bool
|
|||||||
BOOL LLVOAvatar::isVisible() const
|
BOOL LLVOAvatar::isVisible() const
|
||||||
{
|
{
|
||||||
return mDrawable.notNull()
|
return mDrawable.notNull()
|
||||||
|
&& (!mOrphaned || isSelf())
|
||||||
&& (mDrawable->isVisible() || mIsDummy);
|
&& (mDrawable->isVisible() || mIsDummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7109,6 +7270,7 @@ void LLVOAvatar::updateRezzedStatusTimers()
|
|||||||
for (S32 i = 1; i < 4; i++)
|
for (S32 i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
startPhase("load_" + LLVOAvatar::rezStatusToString(i));
|
startPhase("load_" + LLVOAvatar::rezStatusToString(i));
|
||||||
|
startPhase("first_load_" + LLVOAvatar::rezStatusToString(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rez_status < mLastRezzedStatus)
|
if (rez_status < mLastRezzedStatus)
|
||||||
@@ -7125,6 +7287,7 @@ void LLVOAvatar::updateRezzedStatusTimers()
|
|||||||
for (S32 i = llmax(mLastRezzedStatus+1,1); i <= rez_status; i++)
|
for (S32 i = llmax(mLastRezzedStatus+1,1); i <= rez_status; i++)
|
||||||
{
|
{
|
||||||
stopPhase("load_" + LLVOAvatar::rezStatusToString(i));
|
stopPhase("load_" + LLVOAvatar::rezStatusToString(i));
|
||||||
|
stopPhase("first_load_" + LLVOAvatar::rezStatusToString(i), false);
|
||||||
}
|
}
|
||||||
if (rez_status == 3)
|
if (rez_status == 3)
|
||||||
{
|
{
|
||||||
@@ -7254,14 +7417,7 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse
|
|||||||
record["grid_y"] = LLSD::Integer(grid_y);
|
record["grid_y"] = LLSD::Integer(grid_y);
|
||||||
record["is_using_server_bakes"] = ((bool) isUsingServerBakes());
|
record["is_using_server_bakes"] = ((bool) isUsingServerBakes());
|
||||||
record["is_self"] = isSelf();
|
record["is_self"] = isSelf();
|
||||||
|
|
||||||
|
|
||||||
#if 0 // verbose logging
|
|
||||||
std::ostringstream ostr;
|
|
||||||
ostr << LLSDNotationStreamer(record);
|
|
||||||
LL_DEBUGS("Avatar") << "record\n" << ostr.str() << LL_ENDL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (isAgentAvatarValid())
|
if (isAgentAvatarValid())
|
||||||
{
|
{
|
||||||
gAgentAvatarp->addMetricsTimerRecord(record);
|
gAgentAvatarp->addMetricsTimerRecord(record);
|
||||||
@@ -7535,6 +7691,8 @@ void LLVOAvatar::updateMeshTextures()
|
|||||||
// we'll consider it loaded and use it (rather than
|
// we'll consider it loaded and use it (rather than
|
||||||
// doing compositing).
|
// doing compositing).
|
||||||
useBakedTexture( baked_img->getID() );
|
useBakedTexture( baked_img->getID() );
|
||||||
|
mLoadedCallbacksPaused |= !isVisible();
|
||||||
|
checkTextureLoading();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -7547,6 +7705,10 @@ void LLVOAvatar::updateMeshTextures()
|
|||||||
}
|
}
|
||||||
baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ),
|
baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ),
|
||||||
src_callback_list, paused );
|
src_callback_list, paused );
|
||||||
|
|
||||||
|
// this could add paused texture callbacks
|
||||||
|
mLoadedCallbacksPaused |= paused;
|
||||||
|
checkTextureLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (layerset && isUsingLocalAppearance())
|
else if (layerset && isUsingLocalAppearance())
|
||||||
@@ -7615,7 +7777,15 @@ void LLVOAvatar::updateMeshTextures()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeMissingBakedTextures();
|
|
||||||
|
// removeMissingBakedTextures() will call back into this rountine if something is removed, and can blow up the stack
|
||||||
|
static bool call_remove_missing = true;
|
||||||
|
if (call_remove_missing)
|
||||||
|
{
|
||||||
|
call_remove_missing = false;
|
||||||
|
removeMissingBakedTextures(); // May call back into this function if anything is removed
|
||||||
|
call_remove_missing = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
@@ -7916,6 +8086,9 @@ void LLVOAvatar::onFirstTEMessageReceived()
|
|||||||
LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL;
|
LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL;
|
||||||
image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ),
|
image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ),
|
||||||
src_callback_list, paused );
|
src_callback_list, paused );
|
||||||
|
|
||||||
|
// this could add paused texture callbacks
|
||||||
|
mLoadedCallbacksPaused |= paused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8494,7 +8667,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
|
|||||||
}
|
}
|
||||||
if (!found_texture_id)
|
if (!found_texture_id)
|
||||||
{
|
{
|
||||||
LL_INFOS() << "onBakedTextureMasksLoaded(): unexpected image id: " << id << LL_ENDL;
|
LL_INFOS() << "unexpected image id: " << id << LL_ENDL;
|
||||||
}
|
}
|
||||||
self->dirtyMesh();
|
self->dirtyMesh();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -249,7 +249,10 @@ public:
|
|||||||
|
|
||||||
virtual LLJoint* getJoint(const std::string &name);
|
virtual LLJoint* getJoint(const std::string &name);
|
||||||
|
|
||||||
void resetJointPositionsToDefault( void );
|
void addAttachmentPosOverridesForObject(LLViewerObject *vo);
|
||||||
|
void resetJointPositionsOnDetach(const LLUUID& mesh_id);
|
||||||
|
void resetJointPositionsOnDetach(LLViewerObject *vo);
|
||||||
|
void clearAttachmentPosOverrides();
|
||||||
|
|
||||||
/*virtual*/ const LLUUID& getID() const;
|
/*virtual*/ const LLUUID& getID() const;
|
||||||
/*virtual*/ void addDebugText(const std::string& text);
|
/*virtual*/ void addDebugText(const std::string& text);
|
||||||
@@ -283,6 +286,7 @@ private:
|
|||||||
// Updates
|
// Updates
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
public:
|
public:
|
||||||
|
void updateDebugText();
|
||||||
virtual BOOL updateCharacter(LLAgent &agent);
|
virtual BOOL updateCharacter(LLAgent &agent);
|
||||||
void idleUpdateVoiceVisualizer(bool voice_enabled);
|
void idleUpdateVoiceVisualizer(bool voice_enabled);
|
||||||
void idleUpdateMisc(bool detailed_update);
|
void idleUpdateMisc(bool detailed_update);
|
||||||
@@ -393,19 +397,13 @@ protected:
|
|||||||
/*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh
|
/*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh
|
||||||
public:
|
public:
|
||||||
void updateHeadOffset();
|
void updateHeadOffset();
|
||||||
void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ;
|
|
||||||
bool hasPelvisOffset( void ) { return mHasPelvisOffset; }
|
|
||||||
void postPelvisSetRecalc( void );
|
void postPelvisSetRecalc( void );
|
||||||
void setPelvisOffset( F32 pelvixFixupAmount );
|
|
||||||
|
|
||||||
/*virtual*/ BOOL loadSkeletonNode();
|
/*virtual*/ BOOL loadSkeletonNode();
|
||||||
/*virtual*/ void buildCharacter();
|
/*virtual*/ void buildCharacter();
|
||||||
|
|
||||||
bool mHasPelvisOffset;
|
LLVector3 mCurRootToHeadOffset;
|
||||||
LLVector3 mPelvisOffset;
|
LLVector3 mTargetRootToHeadOffset;
|
||||||
F32 mLastPelvisToFoot;
|
|
||||||
F32 mPelvisFixup;
|
|
||||||
F32 mLastPelvisFixup;
|
|
||||||
|
|
||||||
S32 mLastSkeletonSerialNum;
|
S32 mLastSkeletonSerialNum;
|
||||||
|
|
||||||
@@ -744,6 +742,7 @@ public:
|
|||||||
void clampAttachmentPositions();
|
void clampAttachmentPositions();
|
||||||
virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
|
virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
|
||||||
virtual BOOL detachObject(LLViewerObject *viewer_object);
|
virtual BOOL detachObject(LLViewerObject *viewer_object);
|
||||||
|
static bool getRiggedMeshID( LLViewerObject* pVO, LLUUID& mesh_id );
|
||||||
void cleanupAttachedMesh( LLViewerObject* pVO );
|
void cleanupAttachedMesh( LLViewerObject* pVO );
|
||||||
static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj);
|
static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj);
|
||||||
/*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const;
|
/*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const;
|
||||||
@@ -905,6 +904,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
// set this property only with LLVOAvatar::sitDown method
|
// set this property only with LLVOAvatar::sitDown method
|
||||||
BOOL mIsSitting;
|
BOOL mIsSitting;
|
||||||
|
// position backup in case of missing data
|
||||||
|
LLVector3 mLastRootPos;
|
||||||
|
|
||||||
/** Hierarchy
|
/** Hierarchy
|
||||||
** **
|
** **
|
||||||
|
|||||||
@@ -153,15 +153,6 @@ typedef LLHTTPClient::ResponderIgnore LLHoverHeightResponder;
|
|||||||
** **
|
** **
|
||||||
*********************************************************************************/
|
*********************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Static Data
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
S32Bytes LLVOAvatarSelf::sScratchTexBytes(0);
|
|
||||||
LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames;
|
|
||||||
LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime;
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************************
|
/*********************************************************************************
|
||||||
** **
|
** **
|
||||||
** Begin LLVOAvatarSelf Constructor routines
|
** Begin LLVOAvatarSelf Constructor routines
|
||||||
@@ -2685,13 +2676,9 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe
|
|||||||
{
|
{
|
||||||
F32 desired_pixels;
|
F32 desired_pixels;
|
||||||
desired_pixels = llmin(mPixelArea, (F32)getTexImageArea());
|
desired_pixels = llmin(mPixelArea, (F32)getTexImageArea());
|
||||||
|
|
||||||
// DRANO what priority should wearable-based textures have?
|
imagep->setBoostLevel(getAvatarBoostLevel());
|
||||||
if (isUsingLocalAppearance())
|
imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
|
||||||
{
|
|
||||||
imagep->setBoostLevel(getAvatarBoostLevel());
|
|
||||||
imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
|
|
||||||
}
|
|
||||||
imagep->resetTextureStats();
|
imagep->resetTextureStats();
|
||||||
imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);
|
imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);
|
||||||
imagep->addTextureStats( desired_pixels / texel_area_ratio );
|
imagep->addTextureStats( desired_pixels / texel_area_ratio );
|
||||||
@@ -3210,77 +3197,6 @@ BOOL LLVOAvatarSelf::needsRenderBeam()
|
|||||||
return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection());
|
return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection());
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
void LLVOAvatarSelf::deleteScratchTextures()
|
|
||||||
{
|
|
||||||
if(gAuditTexture)
|
|
||||||
{
|
|
||||||
S32Bytes total_tex_size = sScratchTexBytes ;
|
|
||||||
S32Bytes tex_size(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT) ;
|
|
||||||
|
|
||||||
if( sScratchTexNames.checkData( GL_LUMINANCE ) )
|
|
||||||
{
|
|
||||||
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
|
||||||
total_tex_size -= tex_size ;
|
|
||||||
}
|
|
||||||
if( sScratchTexNames.checkData( GL_ALPHA ) )
|
|
||||||
{
|
|
||||||
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
|
||||||
total_tex_size -= tex_size ;
|
|
||||||
}
|
|
||||||
if( sScratchTexNames.checkData( GL_COLOR_INDEX ) )
|
|
||||||
{
|
|
||||||
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
|
||||||
total_tex_size -= tex_size ;
|
|
||||||
}
|
|
||||||
if( sScratchTexNames.checkData( LLRender::sGLCoreProfile ? GL_RG : GL_LUMINANCE_ALPHA ) )
|
|
||||||
{
|
|
||||||
LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
|
||||||
total_tex_size -= 2 * tex_size ;
|
|
||||||
}
|
|
||||||
if( sScratchTexNames.checkData( GL_RGB ) )
|
|
||||||
{
|
|
||||||
LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
|
||||||
total_tex_size -= 3 * tex_size ;
|
|
||||||
}
|
|
||||||
if( sScratchTexNames.checkData( GL_RGBA ) )
|
|
||||||
{
|
|
||||||
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
|
||||||
total_tex_size -= 4 * tex_size ;
|
|
||||||
}
|
|
||||||
//others
|
|
||||||
while(total_tex_size > S32Bytes(0))
|
|
||||||
{
|
|
||||||
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
|
||||||
total_tex_size -= 4 * tex_size ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( LLGLuint* namep = sScratchTexNames.getFirstData();
|
|
||||||
namep;
|
|
||||||
namep = sScratchTexNames.getNextData() )
|
|
||||||
{
|
|
||||||
LLImageGL::deleteTextures(1, (U32 *)namep );
|
|
||||||
stop_glerror();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( sScratchTexBytes.value() )
|
|
||||||
{
|
|
||||||
LL_DEBUGS() << "Clearing Scratch Textures " << (S32Kilobytes)sScratchTexBytes << "KB" << LL_ENDL;
|
|
||||||
|
|
||||||
sScratchTexNames.deleteAllData();
|
|
||||||
sScratchTexLastBindTime.deleteAllData();
|
|
||||||
LLImageGL::sGlobalTextureMemory -= sScratchTexBytes;
|
|
||||||
sScratchTexBytes = S32Bytes(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void LLVOAvatarSelf::dumpScratchTextureByteCount()
|
|
||||||
{
|
|
||||||
LL_INFOS() << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << LL_ENDL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
|
void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
|
||||||
|
|
||||||
void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)
|
void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "llviewertexture.h"
|
#include "llviewertexture.h"
|
||||||
#include "llvoavatar.h"
|
#include "llvoavatar.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
struct LocalTextureData;
|
struct LocalTextureData;
|
||||||
class LLInventoryCallback;
|
class LLInventoryCallback;
|
||||||
@@ -266,17 +267,6 @@ public:
|
|||||||
const LLUUID& grabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
|
const LLUUID& grabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
|
||||||
BOOL canGrabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
|
BOOL canGrabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
// Scratch textures (used for compositing)
|
|
||||||
//--------------------------------------------------------------------
|
|
||||||
public:
|
|
||||||
static void deleteScratchTextures();
|
|
||||||
private:
|
|
||||||
static S32Bytes sScratchTexBytes;
|
|
||||||
static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;
|
|
||||||
static LLMap< LLGLenum, F32*> sScratchTexLastBindTime;
|
|
||||||
|
|
||||||
/** Textures
|
/** Textures
|
||||||
** **
|
** **
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@@ -383,7 +373,6 @@ public:
|
|||||||
public:
|
public:
|
||||||
static void dumpTotalLocalTextureByteCount();
|
static void dumpTotalLocalTextureByteCount();
|
||||||
void dumpLocalTextures() const;
|
void dumpLocalTextures() const;
|
||||||
static void dumpScratchTextureByteCount();
|
|
||||||
void dumpWearableInfo(LLAPRFile& outfile);
|
void dumpWearableInfo(LLAPRFile& outfile);
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|||||||
@@ -93,6 +93,7 @@
|
|||||||
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
|
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
|
||||||
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
|
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
|
||||||
const F32 FORCE_CULL_AREA = 8.f;
|
const F32 FORCE_CULL_AREA = 8.f;
|
||||||
|
U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 20;
|
||||||
|
|
||||||
BOOL gAnimateTextures = TRUE;
|
BOOL gAnimateTextures = TRUE;
|
||||||
//extern BOOL gHideSelectedObjects;
|
//extern BOOL gHideSelectedObjects;
|
||||||
@@ -1564,6 +1565,65 @@ static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies");
|
|||||||
static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives");
|
static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives");
|
||||||
static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged");
|
static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged");
|
||||||
|
|
||||||
|
bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable)
|
||||||
|
{
|
||||||
|
bool regen_faces = false;
|
||||||
|
|
||||||
|
LLVolume *old_volumep, *new_volumep;
|
||||||
|
F32 old_lod, new_lod;
|
||||||
|
S32 old_num_faces, new_num_faces ;
|
||||||
|
|
||||||
|
old_volumep = getVolume();
|
||||||
|
old_lod = old_volumep->getDetail();
|
||||||
|
old_num_faces = old_volumep->getNumFaces() ;
|
||||||
|
old_volumep = NULL ;
|
||||||
|
|
||||||
|
{
|
||||||
|
LLFastTimer ftm(FTM_GEN_VOLUME);
|
||||||
|
const LLVolumeParams &volume_params = getVolume()->getParams();
|
||||||
|
setVolume(volume_params, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
new_volumep = getVolume();
|
||||||
|
new_lod = new_volumep->getDetail();
|
||||||
|
new_num_faces = new_volumep->getNumFaces() ;
|
||||||
|
new_volumep = NULL ;
|
||||||
|
|
||||||
|
if ((new_lod != old_lod) || mSculptChanged)
|
||||||
|
{
|
||||||
|
sNumLODChanges += new_num_faces ;
|
||||||
|
|
||||||
|
if((S32)getNumTEs() != getVolume()->getNumFaces())
|
||||||
|
{
|
||||||
|
setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
|
||||||
|
}
|
||||||
|
|
||||||
|
drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
|
||||||
|
|
||||||
|
{
|
||||||
|
LLFastTimer t(FTM_GEN_TRIANGLES);
|
||||||
|
regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs();
|
||||||
|
if (regen_faces)
|
||||||
|
{
|
||||||
|
regenFaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSculptChanged)
|
||||||
|
{ //changes in sculpt maps can thrash an object bounding box without
|
||||||
|
//triggering a spatial group bounding box update -- force spatial group
|
||||||
|
//to update bounding boxes
|
||||||
|
LLSpatialGroup* group = mDrawable->getSpatialGroup();
|
||||||
|
if (group)
|
||||||
|
{
|
||||||
|
group->unbound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return regen_faces;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
||||||
{
|
{
|
||||||
LLFastTimer t(FTM_UPDATE_PRIMITIVES);
|
LLFastTimer t(FTM_UPDATE_PRIMITIVES);
|
||||||
@@ -1595,8 +1655,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
|||||||
group->dirtyMesh();
|
group->dirtyMesh();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL compiled = FALSE;
|
|
||||||
|
|
||||||
updateRelativeXform();
|
updateRelativeXform();
|
||||||
|
|
||||||
if (mDrawable.isNull()) // Not sure why this is happening, but it is...
|
if (mDrawable.isNull()) // Not sure why this is happening, but it is...
|
||||||
@@ -1608,83 +1666,35 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
|||||||
{
|
{
|
||||||
dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
|
dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
|
||||||
|
|
||||||
compiled = TRUE;
|
bool was_regen_faces = false;
|
||||||
|
|
||||||
if (mVolumeChanged)
|
if (mVolumeChanged)
|
||||||
{
|
{
|
||||||
LLFastTimer ftm(FTM_GEN_VOLUME);
|
was_regen_faces = lodOrSculptChanged(drawable);
|
||||||
LLVolumeParams volume_params = getVolume()->getParams();
|
|
||||||
setVolume(volume_params, 0);
|
|
||||||
drawable->setState(LLDrawable::REBUILD_VOLUME);
|
drawable->setState(LLDrawable::REBUILD_VOLUME);
|
||||||
}
|
}
|
||||||
|
else if (mSculptChanged || mLODChanged)
|
||||||
{
|
{
|
||||||
|
was_regen_faces = lodOrSculptChanged(drawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!was_regen_faces) {
|
||||||
LLFastTimer t(FTM_GEN_TRIANGLES);
|
LLFastTimer t(FTM_GEN_TRIANGLES);
|
||||||
regenFaces();
|
regenFaces();
|
||||||
genBBoxes(FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
genBBoxes(FALSE);
|
||||||
}
|
}
|
||||||
else if ((mLODChanged) || (mSculptChanged))
|
else if (mLODChanged || mSculptChanged)
|
||||||
{
|
{
|
||||||
dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
|
dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
|
||||||
|
lodOrSculptChanged(drawable);
|
||||||
|
genBBoxes(FALSE);
|
||||||
|
|
||||||
LLVolume *old_volumep, *new_volumep;
|
|
||||||
F32 old_lod, new_lod;
|
|
||||||
S32 old_num_faces, new_num_faces ;
|
|
||||||
|
|
||||||
old_volumep = getVolume();
|
|
||||||
old_lod = old_volumep->getDetail();
|
|
||||||
old_num_faces = old_volumep->getNumFaces() ;
|
|
||||||
old_volumep = NULL ;
|
|
||||||
|
|
||||||
{
|
|
||||||
LLFastTimer ftm(FTM_GEN_VOLUME);
|
|
||||||
LLVolumeParams volume_params = getVolume()->getParams();
|
|
||||||
setVolume(volume_params, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
new_volumep = getVolume();
|
|
||||||
new_lod = new_volumep->getDetail();
|
|
||||||
new_num_faces = new_volumep->getNumFaces() ;
|
|
||||||
new_volumep = NULL ;
|
|
||||||
|
|
||||||
if ((new_lod != old_lod) || mSculptChanged)
|
|
||||||
{
|
|
||||||
compiled = TRUE;
|
|
||||||
sNumLODChanges += new_num_faces ;
|
|
||||||
|
|
||||||
if((S32)getNumTEs() != getVolume()->getNumFaces())
|
|
||||||
{
|
|
||||||
setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
|
|
||||||
}
|
|
||||||
|
|
||||||
drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
|
|
||||||
|
|
||||||
{
|
|
||||||
LLFastTimer t(FTM_GEN_TRIANGLES);
|
|
||||||
if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs())
|
|
||||||
{
|
|
||||||
regenFaces();
|
|
||||||
}
|
|
||||||
genBBoxes(FALSE);
|
|
||||||
|
|
||||||
if (mSculptChanged)
|
|
||||||
{ //changes in sculpt maps can thrash an object bounding box without
|
|
||||||
//triggering a spatial group bounding box update -- force spatial group
|
|
||||||
//to update bounding boxes
|
|
||||||
LLSpatialGroup* group = mDrawable->getSpatialGroup();
|
|
||||||
if (group)
|
|
||||||
{
|
|
||||||
group->unbound();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local
|
// it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
compiled = TRUE;
|
|
||||||
// All it did was move or we changed the texture coordinate offset
|
// All it did was move or we changed the texture coordinate offset
|
||||||
LLFastTimer t(FTM_GEN_TRIANGLES);
|
LLFastTimer t(FTM_GEN_TRIANGLES);
|
||||||
genBBoxes(FALSE);
|
genBBoxes(FALSE);
|
||||||
@@ -1692,7 +1702,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
|||||||
|
|
||||||
// Update face flags
|
// Update face flags
|
||||||
updateFaceFlags();
|
updateFaceFlags();
|
||||||
|
|
||||||
mVolumeChanged = FALSE;
|
mVolumeChanged = FALSE;
|
||||||
mLODChanged = FALSE;
|
mLODChanged = FALSE;
|
||||||
mSculptChanged = FALSE;
|
mSculptChanged = FALSE;
|
||||||
@@ -1819,7 +1829,7 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color)
|
|||||||
const LLTextureEntry *tep = getTE(te);
|
const LLTextureEntry *tep = getTE(te);
|
||||||
if (!tep)
|
if (!tep)
|
||||||
{
|
{
|
||||||
LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL;
|
LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL;
|
||||||
}
|
}
|
||||||
else if (color != tep->getColor())
|
else if (color != tep->getColor())
|
||||||
{
|
{
|
||||||
@@ -1971,10 +1981,237 @@ S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture)
|
||||||
|
{ //Ok, here we have confirmation about texture creation, check our wait-list
|
||||||
|
//and make changes, or return false
|
||||||
|
|
||||||
|
std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
|
||||||
|
|
||||||
|
typedef std::map<U8, LLMaterialPtr> map_te_material;
|
||||||
|
map_te_material new_material;
|
||||||
|
|
||||||
|
for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
|
||||||
|
{
|
||||||
|
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
|
||||||
|
|
||||||
|
//here we just interesting in DIFFUSE_MAP only!
|
||||||
|
if(cur_material.notNull() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat())
|
||||||
|
{ //ok let's check the diffuse mode
|
||||||
|
switch(cur_material->getDiffuseAlphaMode())
|
||||||
|
{
|
||||||
|
case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
|
||||||
|
case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
|
||||||
|
case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
|
||||||
|
{ //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
|
||||||
|
|
||||||
|
LLMaterialPtr mat = NULL;
|
||||||
|
map_te_material::iterator it = new_material.find(range_it->second.te);
|
||||||
|
if(new_material.end() == it) {
|
||||||
|
mat = new LLMaterial(cur_material->asLLSD());
|
||||||
|
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
|
||||||
|
} else {
|
||||||
|
mat = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
|
||||||
|
|
||||||
|
} break;
|
||||||
|
} //switch
|
||||||
|
} //if
|
||||||
|
} //for
|
||||||
|
|
||||||
|
//setup new materials
|
||||||
|
for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
|
||||||
|
{
|
||||||
|
LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
|
||||||
|
LLViewerObject::setTEMaterialParams(it->first, it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
//clear wait-list
|
||||||
|
mWaitingTextureInfo.erase(range.first, range.second);
|
||||||
|
|
||||||
|
return 0 != new_material.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)
|
||||||
|
{ //Ok, here if we wait information about texture and it's missing
|
||||||
|
//then depending from the texture map (diffuse, normal, or specular)
|
||||||
|
//make changes in material and confirm it. If not return false.
|
||||||
|
std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
|
||||||
|
if(range.first == range.second) return false;
|
||||||
|
|
||||||
|
typedef std::map<U8, LLMaterialPtr> map_te_material;
|
||||||
|
map_te_material new_material;
|
||||||
|
|
||||||
|
for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
|
||||||
|
{
|
||||||
|
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
|
||||||
|
if (cur_material.isNull())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch(range_it->second.map)
|
||||||
|
{
|
||||||
|
case LLRender::DIFFUSE_MAP:
|
||||||
|
{
|
||||||
|
if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode())
|
||||||
|
{ //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
|
||||||
|
LLMaterialPtr mat = NULL;
|
||||||
|
map_te_material::iterator it = new_material.find(range_it->second.te);
|
||||||
|
if(new_material.end() == it) {
|
||||||
|
mat = new LLMaterial(cur_material->asLLSD());
|
||||||
|
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
|
||||||
|
} else {
|
||||||
|
mat = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case LLRender::NORMAL_MAP:
|
||||||
|
{ //missing texture => reset material texture id
|
||||||
|
LLMaterialPtr mat = NULL;
|
||||||
|
map_te_material::iterator it = new_material.find(range_it->second.te);
|
||||||
|
if(new_material.end() == it) {
|
||||||
|
mat = new LLMaterial(cur_material->asLLSD());
|
||||||
|
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
|
||||||
|
} else {
|
||||||
|
mat = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat->setNormalID(LLUUID::null);
|
||||||
|
} break;
|
||||||
|
case LLRender::SPECULAR_MAP:
|
||||||
|
{ //missing texture => reset material texture id
|
||||||
|
LLMaterialPtr mat = NULL;
|
||||||
|
map_te_material::iterator it = new_material.find(range_it->second.te);
|
||||||
|
if(new_material.end() == it) {
|
||||||
|
mat = new LLMaterial(cur_material->asLLSD());
|
||||||
|
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
|
||||||
|
} else {
|
||||||
|
mat = it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat->setSpecularID(LLUUID::null);
|
||||||
|
} break;
|
||||||
|
case LLRender::NUM_TEXTURE_CHANNELS:
|
||||||
|
//nothing to do, make compiler happy
|
||||||
|
break;
|
||||||
|
} //switch
|
||||||
|
} //for
|
||||||
|
|
||||||
|
//setup new materials
|
||||||
|
for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
|
||||||
|
{
|
||||||
|
LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
|
||||||
|
LLViewerObject::setTEMaterialParams(it->first, it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
//clear wait-list
|
||||||
|
mWaitingTextureInfo.erase(range.first, range.second);
|
||||||
|
|
||||||
|
return 0 != new_material.size();
|
||||||
|
}
|
||||||
|
|
||||||
S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
|
S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
|
||||||
{
|
{
|
||||||
S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams);
|
LLMaterialPtr pMaterial = const_cast<LLMaterialPtr&>(pMaterialParams);
|
||||||
LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res
|
|
||||||
|
if(pMaterialParams)
|
||||||
|
{ //check all of them according to material settings
|
||||||
|
|
||||||
|
LLViewerTexture *img_diffuse = getTEImage(te);
|
||||||
|
LLViewerTexture *img_normal = getTENormalMap(te);
|
||||||
|
LLViewerTexture *img_specular = getTESpecularMap(te);
|
||||||
|
|
||||||
|
llassert(NULL != img_diffuse);
|
||||||
|
|
||||||
|
LLMaterialPtr new_material = NULL;
|
||||||
|
|
||||||
|
//diffuse
|
||||||
|
if(NULL != img_diffuse)
|
||||||
|
{ //guard
|
||||||
|
if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset())
|
||||||
|
{ //ok here we don't have information about texture, let's belief and leave material settings
|
||||||
|
//but we remember this case
|
||||||
|
mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool bSetDiffuseNone = false;
|
||||||
|
if(img_diffuse->isMissingAsset())
|
||||||
|
{
|
||||||
|
bSetDiffuseNone = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch(pMaterialParams->getDiffuseAlphaMode())
|
||||||
|
{
|
||||||
|
case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
|
||||||
|
case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
|
||||||
|
case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
|
||||||
|
{ //all of them modes available only for 32 bit textures
|
||||||
|
if(GL_RGBA != img_diffuse->getPrimaryFormat())
|
||||||
|
{
|
||||||
|
bSetDiffuseNone = true;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} //else
|
||||||
|
|
||||||
|
|
||||||
|
if(bSetDiffuseNone)
|
||||||
|
{ //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE
|
||||||
|
new_material = new LLMaterial(pMaterialParams->asLLSD());
|
||||||
|
new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//normal
|
||||||
|
if(LLUUID::null != pMaterialParams->getNormalID())
|
||||||
|
{
|
||||||
|
if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID())
|
||||||
|
{
|
||||||
|
if(!new_material) {
|
||||||
|
new_material = new LLMaterial(pMaterialParams->asLLSD());
|
||||||
|
}
|
||||||
|
new_material->setNormalID(LLUUID::null);
|
||||||
|
}
|
||||||
|
else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat())
|
||||||
|
{ //ok here we don't have information about texture, let's belief and leave material settings
|
||||||
|
//but we remember this case
|
||||||
|
mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//specular
|
||||||
|
if(LLUUID::null != pMaterialParams->getSpecularID())
|
||||||
|
{
|
||||||
|
if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID())
|
||||||
|
{
|
||||||
|
if(!new_material) {
|
||||||
|
new_material = new LLMaterial(pMaterialParams->asLLSD());
|
||||||
|
}
|
||||||
|
new_material->setSpecularID(LLUUID::null);
|
||||||
|
}
|
||||||
|
else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat())
|
||||||
|
{ //ok here we don't have information about texture, let's belief and leave material settings
|
||||||
|
//but we remember this case
|
||||||
|
mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_material) {
|
||||||
|
pMaterial = new_material;
|
||||||
|
LLMaterialMgr::getInstance()->put(getID(),te,*pMaterial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial);
|
||||||
|
|
||||||
|
LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res
|
||||||
<< ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
|
<< ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
|
||||||
<< LL_ENDL;
|
<< LL_ENDL;
|
||||||
setChanged(ALL_CHANGED);
|
setChanged(ALL_CHANGED);
|
||||||
@@ -4597,60 +4834,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
|
|
||||||
//get drawpool of avatar with rigged face
|
//get drawpool of avatar with rigged face
|
||||||
LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);
|
LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);
|
||||||
|
|
||||||
//Determine if we've received skininfo that contains an
|
// FIXME should this be inside the face loop?
|
||||||
//alternate bind matrix - if it does then apply the translational component
|
// doesn't seem to depend on any per-face state.
|
||||||
//to the joints of the avatar.
|
|
||||||
bool pelvisGotSet = false;
|
|
||||||
|
|
||||||
if ( pAvatarVO )
|
if ( pAvatarVO )
|
||||||
{
|
{
|
||||||
LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
|
pAvatarVO->addAttachmentPosOverridesForObject(vobj);
|
||||||
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
|
|
||||||
|
|
||||||
if ( pSkinData )
|
|
||||||
{
|
|
||||||
const int bindCnt = pSkinData->mAlternateBindMatrix.size();
|
|
||||||
if ( bindCnt > 0 )
|
|
||||||
{
|
|
||||||
const int jointCnt = pSkinData->mJointNames.size();
|
|
||||||
const F32 pelvisZOffset = pSkinData->mPelvisOffset;
|
|
||||||
bool fullRig = (jointCnt>=20) ? true : false;
|
|
||||||
if ( fullRig )
|
|
||||||
{
|
|
||||||
for ( int i=0; i<jointCnt; ++i )
|
|
||||||
{
|
|
||||||
std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
|
|
||||||
//LL_INFOS() <<"joint name "<<lookingForJoint.c_str()<<LL_ENDL;
|
|
||||||
LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint );
|
|
||||||
if ( pJoint && pJoint->getId() != currentId )
|
|
||||||
{
|
|
||||||
pJoint->setId( currentId );
|
|
||||||
const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();
|
|
||||||
//Set the joint position
|
|
||||||
pJoint->storeCurrentXform( jointPos );
|
|
||||||
//If joint is a pelvis then handle old/new pelvis to foot values
|
|
||||||
if ( lookingForJoint == "mPelvis" )
|
|
||||||
{
|
|
||||||
pJoint->storeCurrentXform( jointPos );
|
|
||||||
if ( !pAvatarVO->hasPelvisOffset() )
|
|
||||||
{
|
|
||||||
pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset );
|
|
||||||
//Trigger to rebuild viewer AV
|
|
||||||
pelvisGotSet = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//If we've set the pelvis to a new position we need to also rebuild some information that the
|
|
||||||
//viewer does at launch (e.g. body size etc.)
|
|
||||||
if ( pelvisGotSet )
|
|
||||||
{
|
|
||||||
pAvatarVO->postPelvisSetRecalc();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pool)
|
if (pool)
|
||||||
@@ -5407,6 +5596,10 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
|
|||||||
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
|
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
|
||||||
{
|
{
|
||||||
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
|
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
|
||||||
|
if(!drawablep)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
|
for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
|
||||||
{
|
{
|
||||||
LLFace* face = drawablep->getFace(i);
|
LLFace* face = drawablep->getFace(i);
|
||||||
|
|||||||
@@ -358,6 +358,10 @@ protected:
|
|||||||
void cleanUpMediaImpls();
|
void cleanUpMediaImpls();
|
||||||
void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
|
void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
|
||||||
void removeMediaImpl(S32 texture_index) ;
|
void removeMediaImpl(S32 texture_index) ;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool lodOrSculptChanged(LLDrawable *drawable);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static S32 getRenderComplexityMax() {return mRenderComplexity_last;}
|
static S32 getRenderComplexityMax() {return mRenderComplexity_last;}
|
||||||
@@ -402,6 +406,26 @@ protected:
|
|||||||
static S32 sNumLODChanges;
|
static S32 sNumLODChanges;
|
||||||
|
|
||||||
friend class LLVolumeImplFlexible;
|
friend class LLVolumeImplFlexible;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool notifyAboutCreatingTexture(LLViewerTexture *texture);
|
||||||
|
bool notifyAboutMissingAsset(LLViewerTexture *texture);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct material_info
|
||||||
|
{
|
||||||
|
LLRender::eTexIndex map;
|
||||||
|
U8 te;
|
||||||
|
|
||||||
|
material_info(LLRender::eTexIndex map_, U8 te_)
|
||||||
|
: map(map_)
|
||||||
|
, te(te_)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::multimap<LLUUID, material_info> mmap_UUID_MAP_t;
|
||||||
|
mmap_UUID_MAP_t mWaitingTextureInfo;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LL_LLVOVOLUME_H
|
#endif // LL_LLVOVOLUME_H
|
||||||
|
|||||||
Reference in New Issue
Block a user