Merge branch 'V2Mesh' of https://github.com/Shyotl/SingularityViewer into future
This commit is contained in:
@@ -295,6 +295,7 @@ endif (STANDALONE)
|
|||||||
|
|
||||||
if(1 EQUAL 1)
|
if(1 EQUAL 1)
|
||||||
add_definitions(-DOPENSIM_RULES=1)
|
add_definitions(-DOPENSIM_RULES=1)
|
||||||
|
add_definitions(-DMESH_ENABLED=1)
|
||||||
endif(1 EQUAL 1)
|
endif(1 EQUAL 1)
|
||||||
|
|
||||||
if(SERVER)
|
if(SERVER)
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
LLStringTable LLCharacter::sVisualParamNames(1024);
|
LLStringTable LLCharacter::sVisualParamNames(1024);
|
||||||
|
|
||||||
std::vector< LLCharacter* > LLCharacter::sInstances;
|
std::vector< LLCharacter* > LLCharacter::sInstances;
|
||||||
|
BOOL LLCharacter::sAllowInstancesChange = TRUE ;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// LLCharacter()
|
// LLCharacter()
|
||||||
@@ -59,8 +59,10 @@ LLCharacter::LLCharacter()
|
|||||||
mSkeletonSerialNum( 0 ),
|
mSkeletonSerialNum( 0 ),
|
||||||
mInAppearance( false )
|
mInAppearance( false )
|
||||||
{
|
{
|
||||||
mMotionController.setCharacter( this );
|
llassert_always(sAllowInstancesChange) ;
|
||||||
sInstances.push_back(this);
|
sInstances.push_back(this);
|
||||||
|
|
||||||
|
mMotionController.setCharacter( this );
|
||||||
mPauseRequest = new LLPauseRequestHandle();
|
mPauseRequest = new LLPauseRequestHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,11 +79,22 @@ LLCharacter::~LLCharacter()
|
|||||||
{
|
{
|
||||||
delete param;
|
delete param;
|
||||||
}
|
}
|
||||||
std::vector<LLCharacter*>::iterator iter = std::find(sInstances.begin(), sInstances.end(), this);
|
|
||||||
if (iter != sInstances.end())
|
U32 i ;
|
||||||
|
U32 size = sInstances.size() ;
|
||||||
|
for(i = 0 ; i < size ; i++)
|
||||||
{
|
{
|
||||||
sInstances.erase(iter);
|
if(sInstances[i] == this)
|
||||||
|
{
|
||||||
|
break ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llassert_always(i < size) ;
|
||||||
|
|
||||||
|
llassert_always(sAllowInstancesChange) ;
|
||||||
|
sInstances[i] = sInstances[size - 1] ;
|
||||||
|
sInstances.pop_back() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ public:
|
|||||||
void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; }
|
void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; }
|
||||||
|
|
||||||
static std::vector< LLCharacter* > sInstances;
|
static std::vector< LLCharacter* > sInstances;
|
||||||
|
static BOOL sAllowInstancesChange ; //debug use
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LLMotionController mMotionController;
|
LLMotionController mMotionController;
|
||||||
|
|||||||
@@ -56,6 +56,9 @@ LLJoint::LLJoint()
|
|||||||
mUpdateXform = TRUE;
|
mUpdateXform = TRUE;
|
||||||
mJointNum = -1;
|
mJointNum = -1;
|
||||||
touch();
|
touch();
|
||||||
|
#if MESH_ENABLED
|
||||||
|
mResetAfterRestoreOldXform = false;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -239,6 +242,43 @@ void LLJoint::setPosition( const LLVector3& pos )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// setPosition()
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void LLJoint::setDefaultFromCurrentXform( void )
|
||||||
|
{
|
||||||
|
mDefaultXform = mXform;
|
||||||
|
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// storeCurrentXform()
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void LLJoint::storeCurrentXform( const LLVector3& pos )
|
||||||
|
{
|
||||||
|
mOldXform = mXform;
|
||||||
|
mResetAfterRestoreOldXform = true;
|
||||||
|
setPosition( pos );
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// restoreOldXform()
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void LLJoint::restoreOldXform( void )
|
||||||
|
{
|
||||||
|
mResetAfterRestoreOldXform = false;
|
||||||
|
mXform = mOldXform;
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
// restoreOldXform()
|
||||||
|
//--------------------------------------------------------------------
|
||||||
|
void LLJoint::restoreToDefaultXform( void )
|
||||||
|
{
|
||||||
|
mXform = mDefaultXform;
|
||||||
|
setPosition( mXform.getPosition() );
|
||||||
|
}
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// getWorldPosition()
|
// getWorldPosition()
|
||||||
|
|||||||
@@ -86,11 +86,20 @@ protected:
|
|||||||
|
|
||||||
// explicit transformation members
|
// explicit transformation members
|
||||||
LLXformMatrix mXform;
|
LLXformMatrix mXform;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
LLXformMatrix mOldXform;
|
||||||
|
LLXformMatrix mDefaultXform;
|
||||||
|
|
||||||
|
LLUUID mId;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
public:
|
public:
|
||||||
U32 mDirtyFlags;
|
U32 mDirtyFlags;
|
||||||
BOOL mUpdateXform;
|
BOOL mUpdateXform;
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
BOOL mResetAfterRestoreOldXform;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
// describes the skin binding pose
|
// describes the skin binding pose
|
||||||
LLVector3 mSkinOffset;
|
LLVector3 mSkinOffset;
|
||||||
|
|
||||||
@@ -179,6 +188,24 @@ public:
|
|||||||
S32 getJointNum() const { return mJointNum; }
|
S32 getJointNum() const { return mJointNum; }
|
||||||
void setJointNum(S32 joint_num) { mJointNum = joint_num; }
|
void setJointNum(S32 joint_num) { mJointNum = joint_num; }
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
|
||||||
|
void restoreOldXform( void );
|
||||||
|
void restoreToDefaultXform( void );
|
||||||
|
void setDefaultFromCurrentXform( void );
|
||||||
|
void storeCurrentXform( const LLVector3& pos );
|
||||||
|
|
||||||
|
//Accessor for the joint id
|
||||||
|
LLUUID getId( void ) { return mId; }
|
||||||
|
//Setter for the joints 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; }
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
// <edit>
|
// <edit>
|
||||||
std::string exportString(U32 tabs = 0);
|
std::string exportString(U32 tabs = 0);
|
||||||
// </edit>
|
// </edit>
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ LLJointState *LLPose::getNextJointState()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
BOOL LLPose::addJointState(const LLPointer<LLJointState>& jointState)
|
BOOL LLPose::addJointState(const LLPointer<LLJointState>& jointState)
|
||||||
{
|
{
|
||||||
|
llassert_always(jointState.notNull());
|
||||||
if (mJointMap.find(jointState->getJoint()->getName()) == mJointMap.end())
|
if (mJointMap.find(jointState->getJoint()->getName()) == mJointMap.end())
|
||||||
{
|
{
|
||||||
mJointMap[jointState->getJoint()->getName()] = jointState;
|
mJointMap[jointState->getJoint()->getName()] = jointState;
|
||||||
@@ -161,6 +162,9 @@ void LLPose::setWeight(F32 weight)
|
|||||||
// <edit>
|
// <edit>
|
||||||
// there was a crash here
|
// there was a crash here
|
||||||
// </edit>
|
// </edit>
|
||||||
|
llassert_always(iter->second.notNull());
|
||||||
|
if(!iter->second) //uhoh...
|
||||||
|
continue;
|
||||||
iter->second->setWeight(weight);
|
iter->second->setWeight(weight);
|
||||||
}
|
}
|
||||||
mWeight = weight;
|
mWeight = weight;
|
||||||
|
|||||||
@@ -58,12 +58,14 @@ set(llcommon_SOURCE_FILES
|
|||||||
llprocessor.cpp
|
llprocessor.cpp
|
||||||
llqueuedthread.cpp
|
llqueuedthread.cpp
|
||||||
llrand.cpp
|
llrand.cpp
|
||||||
|
llrefcount.cpp
|
||||||
llrun.cpp
|
llrun.cpp
|
||||||
llsd.cpp
|
llsd.cpp
|
||||||
llsdserialize.cpp
|
llsdserialize.cpp
|
||||||
llsdserialize_xml.cpp
|
llsdserialize_xml.cpp
|
||||||
llsdutil.cpp
|
llsdutil.cpp
|
||||||
llsecondlifeurls.cpp
|
llsecondlifeurls.cpp
|
||||||
|
llsingleton.cpp
|
||||||
llstat.cpp
|
llstat.cpp
|
||||||
llstacktrace.cpp
|
llstacktrace.cpp
|
||||||
llstreamtools.cpp
|
llstreamtools.cpp
|
||||||
@@ -94,6 +96,7 @@ set(llcommon_HEADER_FILES
|
|||||||
indra_constants.h
|
indra_constants.h
|
||||||
linden_common.h
|
linden_common.h
|
||||||
linked_lists.h
|
linked_lists.h
|
||||||
|
llaccountingquota.h
|
||||||
llagentconstants.h
|
llagentconstants.h
|
||||||
llavatarname.h
|
llavatarname.h
|
||||||
llapp.h
|
llapp.h
|
||||||
@@ -159,6 +162,7 @@ set(llcommon_HEADER_FILES
|
|||||||
llmortician.h
|
llmortician.h
|
||||||
llnametable.h
|
llnametable.h
|
||||||
lloptioninterface.h
|
lloptioninterface.h
|
||||||
|
llpointer.h
|
||||||
llpreprocessor.h
|
llpreprocessor.h
|
||||||
llpriqueuemap.h
|
llpriqueuemap.h
|
||||||
llprocesslauncher.h
|
llprocesslauncher.h
|
||||||
@@ -168,6 +172,8 @@ set(llcommon_HEADER_FILES
|
|||||||
llqueuedthread.h
|
llqueuedthread.h
|
||||||
llrand.h
|
llrand.h
|
||||||
llrun.h
|
llrun.h
|
||||||
|
llrefcount.h
|
||||||
|
llsafehandle.h
|
||||||
llscopedvolatileaprpool.h
|
llscopedvolatileaprpool.h
|
||||||
llsd.h
|
llsd.h
|
||||||
llsdserialize.h
|
llsdserialize.h
|
||||||
@@ -175,6 +181,7 @@ set(llcommon_HEADER_FILES
|
|||||||
llsdutil.h
|
llsdutil.h
|
||||||
llsecondlifeurls.h
|
llsecondlifeurls.h
|
||||||
llsimplehash.h
|
llsimplehash.h
|
||||||
|
llsingleton.h
|
||||||
llskiplist.h
|
llskiplist.h
|
||||||
llskipmap.h
|
llskipmap.h
|
||||||
llstack.h
|
llstack.h
|
||||||
@@ -205,6 +212,7 @@ set(llcommon_HEADER_FILES
|
|||||||
stdenums.h
|
stdenums.h
|
||||||
stdtypes.h
|
stdtypes.h
|
||||||
string_table.h
|
string_table.h
|
||||||
|
stringize.h
|
||||||
timer.h
|
timer.h
|
||||||
timing.h
|
timing.h
|
||||||
u64.h
|
u64.h
|
||||||
|
|||||||
80
indra/llcommon/llaccountingquota.h
Normal file
80
indra/llcommon/llaccountingquota.h
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* @file llaccountingquota.h
|
||||||
|
* @
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2011, 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_ACCOUNTINGQUOTA_H
|
||||||
|
#define LL_ACCOUNTINGQUOTA_H
|
||||||
|
|
||||||
|
struct ParcelQuota
|
||||||
|
{
|
||||||
|
ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost,
|
||||||
|
F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost,
|
||||||
|
F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost,
|
||||||
|
F32 tempRenderCost, F32 tempPhysicsCost, F32 tempNetworkCost, F32 tempSimulationCost,
|
||||||
|
F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
|
||||||
|
F32 parcelCapacity )
|
||||||
|
: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost )
|
||||||
|
, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
|
||||||
|
, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
|
||||||
|
, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
|
||||||
|
, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
|
||||||
|
, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
|
||||||
|
, mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost )
|
||||||
|
, mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
|
||||||
|
, mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost )
|
||||||
|
, mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
|
||||||
|
, mParcelCapacity( parcelCapacity )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ParcelQuota(){}
|
||||||
|
F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
|
||||||
|
F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
|
||||||
|
F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
|
||||||
|
F32 mTempRenderCost, mTempPhysicsCost, mTempNetworkCost, mTempSimulationCost;
|
||||||
|
F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
|
||||||
|
F32 mParcelCapacity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SelectionQuota
|
||||||
|
{
|
||||||
|
SelectionQuota( LLUUID localId, F32 renderCost, F32 physicsCost, F32 networkCost, F32 simulationCost )
|
||||||
|
: mLocalId( localId)
|
||||||
|
, mRenderCost( renderCost )
|
||||||
|
, mPhysicsCost( physicsCost )
|
||||||
|
, mNetworkCost( networkCost )
|
||||||
|
, mSimulationCost( simulationCost )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
SelectionQuota() {}
|
||||||
|
|
||||||
|
F32 mRenderCost, mPhysicsCost, mNetworkCost, mSimulationCost;
|
||||||
|
LLUUID mLocalId;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -297,10 +297,13 @@ void LLApp::startErrorThread()
|
|||||||
// Start the error handling thread, which is responsible for taking action
|
// Start the error handling thread, which is responsible for taking action
|
||||||
// when the app goes into the APP_STATUS_ERROR state
|
// when the app goes into the APP_STATUS_ERROR state
|
||||||
//
|
//
|
||||||
llinfos << "Starting error thread" << llendl;
|
if(!mThreadErrorp)
|
||||||
mThreadErrorp = new LLErrorThread();
|
{
|
||||||
mThreadErrorp->setUserData((void *) this);
|
llinfos << "Starting error thread" << llendl;
|
||||||
mThreadErrorp->start();
|
mThreadErrorp = new LLErrorThread();
|
||||||
|
mThreadErrorp->setUserData((void *) this);
|
||||||
|
mThreadErrorp->start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLApp::setErrorHandler(LLAppErrorHandler handler)
|
void LLApp::setErrorHandler(LLAppErrorHandler handler)
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ LLAssetDictionary::LLAssetDictionary()
|
|||||||
//addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("FOLDER_LINK", "current", "current outfit", false, false, false));
|
//addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("FOLDER_LINK", "current", "current outfit", false, false, false));
|
||||||
//addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", false, false, false));
|
//addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", false, false, false));
|
||||||
//addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", false, false, false));
|
//addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", false, false, false));
|
||||||
|
#if MESH_ENABLED
|
||||||
|
addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
|
||||||
|
#endif //MESH_ENABLED
|
||||||
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false));
|
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -145,6 +145,12 @@ public:
|
|||||||
|
|
||||||
//AT_MY_OUTFITS = 48,
|
//AT_MY_OUTFITS = 48,
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
AT_MESH = 49,
|
||||||
|
// Mesh data in our proprietary SLM format
|
||||||
|
|
||||||
|
AT_COUNT = 50,
|
||||||
|
#endif //MESH_ENABLED
|
||||||
// +*********************************************+
|
// +*********************************************+
|
||||||
// | TO ADD AN ELEMENT TO THIS ENUM: |
|
// | TO ADD AN ELEMENT TO THIS ENUM: |
|
||||||
// +*********************************************+
|
// +*********************************************+
|
||||||
@@ -155,8 +161,9 @@ public:
|
|||||||
// +*********************************************+
|
// +*********************************************+
|
||||||
|
|
||||||
//AT_COUNT = 49,
|
//AT_COUNT = 49,
|
||||||
|
#if !MESH_ENABLED
|
||||||
AT_COUNT = 26,
|
AT_COUNT = 26,
|
||||||
|
#endif //!MESH_ENABLED
|
||||||
AT_NONE = -1
|
AT_NONE = -1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,11 @@ public:
|
|||||||
FTM_UPDATE_GRASS,
|
FTM_UPDATE_GRASS,
|
||||||
FTM_UPDATE_TREE,
|
FTM_UPDATE_TREE,
|
||||||
FTM_UPDATE_AVATAR,
|
FTM_UPDATE_AVATAR,
|
||||||
|
#if MESH_ENABLED
|
||||||
|
FTM_UPDATE_RIGGED_VOLUME,
|
||||||
|
FTM_SKIN_RIGGED,
|
||||||
|
FTM_RIGGED_OCTREE,
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
// common render components
|
// common render components
|
||||||
FTM_SHADOW_GEOMETRY,
|
FTM_SHADOW_GEOMETRY,
|
||||||
@@ -131,6 +136,12 @@ public:
|
|||||||
FTM_STATESORT,
|
FTM_STATESORT,
|
||||||
FTM_STATESORT_DRAWABLE,
|
FTM_STATESORT_DRAWABLE,
|
||||||
FTM_STATESORT_POSTSORT,
|
FTM_STATESORT_POSTSORT,
|
||||||
|
#if MESH_ENABLED
|
||||||
|
FTM_MESH_UPDATE,
|
||||||
|
FTM_MESH_LOCK1,
|
||||||
|
FTM_MESH_LOCK2,
|
||||||
|
FTM_LOAD_MESH_LOD,
|
||||||
|
#endif //MESH_ENABLED
|
||||||
FTM_REBUILD_VBO,
|
FTM_REBUILD_VBO,
|
||||||
FTM_REBUILD_VOLUME_VB,
|
FTM_REBUILD_VOLUME_VB,
|
||||||
FTM_REBUILD_BRIDGE_VB,
|
FTM_REBUILD_BRIDGE_VB,
|
||||||
|
|||||||
@@ -276,37 +276,12 @@ void operator delete[] (void *p)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
LLRefCount::LLRefCount() :
|
|
||||||
mRef(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LLRefCount::LLRefCount(const LLRefCount& other)
|
|
||||||
: mRef(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LLRefCount::~LLRefCount()
|
|
||||||
{
|
|
||||||
if (mRef != 0)
|
|
||||||
{
|
|
||||||
llerrs << "deleting non-zero reference" << llendl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
|
||||||
{
|
|
||||||
// do nothing, since ref count is specific to *this* reference
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(LL_WINDOWS)
|
#if defined(LL_WINDOWS)
|
||||||
|
|
||||||
U64 getCurrentRSS()
|
U64 LLMemory::getCurrentRSS()
|
||||||
{
|
{
|
||||||
HANDLE self = GetCurrentProcess();
|
HANDLE self = GetCurrentProcess();
|
||||||
PROCESS_MEMORY_COUNTERS counters;
|
PROCESS_MEMORY_COUNTERS counters;
|
||||||
@@ -320,6 +295,20 @@ U64 getCurrentRSS()
|
|||||||
return counters.WorkingSetSize;
|
return counters.WorkingSetSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
U32 LLMemory::getWorkingSetSize()
|
||||||
|
{
|
||||||
|
PROCESS_MEMORY_COUNTERS pmc ;
|
||||||
|
U32 ret = 0 ;
|
||||||
|
|
||||||
|
if (GetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) )
|
||||||
|
{
|
||||||
|
ret = pmc.WorkingSetSize ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret ;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(LL_DARWIN)
|
#elif defined(LL_DARWIN)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -344,7 +333,7 @@ U64 getCurrentRSS()
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
U64 getCurrentRSS()
|
U64 LLMemory::getCurrentRSS()
|
||||||
{
|
{
|
||||||
U64 residentSize = 0;
|
U64 residentSize = 0;
|
||||||
task_basic_info_data_t basicInfo;
|
task_basic_info_data_t basicInfo;
|
||||||
@@ -366,9 +355,14 @@ U64 getCurrentRSS()
|
|||||||
return residentSize;
|
return residentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U32 LLMemory::getWorkingSetSize()
|
||||||
|
{
|
||||||
|
return 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(LL_LINUX)
|
#elif defined(LL_LINUX)
|
||||||
|
|
||||||
U64 getCurrentRSS()
|
U64 LLMemory::getCurrentRSS()
|
||||||
{
|
{
|
||||||
static const char statPath[] = "/proc/self/stat";
|
static const char statPath[] = "/proc/self/stat";
|
||||||
LLFILE *fp = LLFile::fopen(statPath, "r");
|
LLFILE *fp = LLFile::fopen(statPath, "r");
|
||||||
@@ -400,6 +394,10 @@ bail:
|
|||||||
return rss;
|
return rss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U32 LLMemory::getWorkingSetSize()
|
||||||
|
{
|
||||||
|
return 0 ;
|
||||||
|
}
|
||||||
#elif LL_SOLARIS
|
#elif LL_SOLARIS
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -407,7 +405,7 @@ bail:
|
|||||||
#define _STRUCTURED_PROC 1
|
#define _STRUCTURED_PROC 1
|
||||||
#include <sys/procfs.h>
|
#include <sys/procfs.h>
|
||||||
|
|
||||||
U64 getCurrentRSS()
|
U64 LLMemory::getCurrentRSS()
|
||||||
{
|
{
|
||||||
char path [LL_MAX_PATH]; /* Flawfinder: ignore */
|
char path [LL_MAX_PATH]; /* Flawfinder: ignore */
|
||||||
|
|
||||||
@@ -428,11 +426,22 @@ U64 getCurrentRSS()
|
|||||||
|
|
||||||
return((U64)proc_psinfo.pr_rssize * 1024);
|
return((U64)proc_psinfo.pr_rssize * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U32 LLMemory::getWorkingSetSize()
|
||||||
|
{
|
||||||
|
return 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
U64 getCurrentRSS()
|
U64 LLMemory::getCurrentRSS()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U32 LLMemory::getWorkingSetSize()
|
||||||
|
{
|
||||||
|
return 0 ;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,20 +29,15 @@
|
|||||||
* COMPLETENESS OR PERFORMANCE.
|
* COMPLETENESS OR PERFORMANCE.
|
||||||
* $/LicenseInfo$
|
* $/LicenseInfo$
|
||||||
*/
|
*/
|
||||||
#ifndef LL_MEMORY_H
|
#ifndef LLMEMORY_H
|
||||||
#define LL_MEMORY_H
|
#define LLMEMORY_H
|
||||||
|
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "llerror.h"
|
#include "llerror.h"
|
||||||
|
|
||||||
extern S32 gTotalDAlloc;
|
|
||||||
extern S32 gTotalDAUse;
|
|
||||||
extern S32 gDACount;
|
|
||||||
|
|
||||||
const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA;
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
#if LL_DEBUG
|
#if LL_DEBUG
|
||||||
@@ -128,431 +123,18 @@ public:
|
|||||||
static void initClass();
|
static void initClass();
|
||||||
static void cleanupClass();
|
static void cleanupClass();
|
||||||
static void freeReserve();
|
static void freeReserve();
|
||||||
|
// Return the resident set size of the current process, in bytes.
|
||||||
|
// Return value is zero if not known.
|
||||||
|
static U64 getCurrentRSS();
|
||||||
|
static U32 getWorkingSetSize();
|
||||||
private:
|
private:
|
||||||
static char* reserveMem;
|
static char* reserveMem;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//EVENTUALLY REMOVE THESE:
|
||||||
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
#include "llpointer.h"
|
||||||
// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
|
#include "llrefcount.h"
|
||||||
// if LLFoo::LLFoo() does anything like put itself in an update queue.
|
#include "llsingleton.h"
|
||||||
// The queue may get accessed before it gets assigned to x.
|
#include "llsafehandle.h"
|
||||||
// The correct implementation is:
|
|
||||||
// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
|
|
||||||
// x->instantiate(); // does stuff like place x into an update queue
|
|
||||||
|
|
||||||
// see llthread.h for LLThreadSafeRefCount
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class LL_COMMON_API LLRefCount
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
LLRefCount(const LLRefCount&);
|
|
||||||
private:
|
|
||||||
LLRefCount&operator=(const LLRefCount&);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual ~LLRefCount(); // use unref()
|
|
||||||
|
|
||||||
public:
|
|
||||||
LLRefCount();
|
|
||||||
|
|
||||||
void ref()
|
|
||||||
{
|
|
||||||
mRef++;
|
|
||||||
}
|
|
||||||
|
|
||||||
S32 unref()
|
|
||||||
{
|
|
||||||
llassert(mRef >= 1);
|
|
||||||
if (0 == --mRef)
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return mRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
S32 getNumRefs() const
|
|
||||||
{
|
|
||||||
return mRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
S32 mRef;
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Note: relies on Type having ref() and unref() methods
|
|
||||||
template <class Type> class LLPointer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
LLPointer() :
|
|
||||||
mPointer(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LLPointer(Type* ptr) :
|
|
||||||
mPointer(ptr)
|
|
||||||
{
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
LLPointer(const LLPointer<Type>& ptr) :
|
|
||||||
mPointer(ptr.mPointer)
|
|
||||||
{
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
|
||||||
template<typename Subclass>
|
|
||||||
LLPointer(const LLPointer<Subclass>& ptr) :
|
|
||||||
mPointer(ptr.get())
|
|
||||||
{
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
~LLPointer()
|
|
||||||
{
|
|
||||||
unref();
|
|
||||||
}
|
|
||||||
|
|
||||||
Type* get() const { return mPointer; }
|
|
||||||
const Type* operator->() const { return mPointer; }
|
|
||||||
Type* operator->() { return mPointer; }
|
|
||||||
const Type& operator*() const { return *mPointer; }
|
|
||||||
Type& operator*() { return *mPointer; }
|
|
||||||
|
|
||||||
operator BOOL() const { return (mPointer != NULL); }
|
|
||||||
operator bool() const { return (mPointer != NULL); }
|
|
||||||
bool operator!() const { return (mPointer == NULL); }
|
|
||||||
bool isNull() const { return (mPointer == NULL); }
|
|
||||||
bool notNull() const { return (mPointer != NULL); }
|
|
||||||
|
|
||||||
operator Type*() const { return mPointer; }
|
|
||||||
operator const Type*() const { return mPointer; }
|
|
||||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
|
||||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
|
||||||
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
|
||||||
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
|
||||||
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
|
||||||
|
|
||||||
LLPointer<Type>& operator =(Type* ptr)
|
|
||||||
{
|
|
||||||
if( mPointer != ptr )
|
|
||||||
{
|
|
||||||
unref();
|
|
||||||
mPointer = ptr;
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
|
|
||||||
{
|
|
||||||
if( mPointer != ptr.mPointer )
|
|
||||||
{
|
|
||||||
unref();
|
|
||||||
mPointer = ptr.mPointer;
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
|
||||||
template<typename Subclass>
|
|
||||||
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
|
|
||||||
{
|
|
||||||
if( mPointer != ptr.get() )
|
|
||||||
{
|
|
||||||
unref();
|
|
||||||
mPointer = ptr.get();
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just exchange the pointers, which will not change the reference counts.
|
|
||||||
static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
|
|
||||||
{
|
|
||||||
Type* temp = a.mPointer;
|
|
||||||
a.mPointer = b.mPointer;
|
|
||||||
b.mPointer = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void ref()
|
|
||||||
{
|
|
||||||
if (mPointer)
|
|
||||||
{
|
|
||||||
mPointer->ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void unref()
|
|
||||||
{
|
|
||||||
if (mPointer)
|
|
||||||
{
|
|
||||||
Type *tempp = mPointer;
|
|
||||||
mPointer = NULL;
|
|
||||||
tempp->unref();
|
|
||||||
if (mPointer != NULL)
|
|
||||||
{
|
|
||||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
|
||||||
unref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Type* mPointer;
|
|
||||||
};
|
|
||||||
|
|
||||||
//template <class Type>
|
|
||||||
//class LLPointerTraits
|
|
||||||
//{
|
|
||||||
// static Type* null();
|
|
||||||
//};
|
|
||||||
//
|
|
||||||
// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
|
|
||||||
// This is useful in instances where operations on NULL pointers are semantically safe and/or
|
|
||||||
// when error checking occurs at a different granularity or in a different part of the code
|
|
||||||
// than when referencing an object via a LLSafeHandle.
|
|
||||||
//
|
|
||||||
|
|
||||||
template <class Type>
|
|
||||||
class LLSafeHandle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLSafeHandle() :
|
|
||||||
mPointer(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
LLSafeHandle(Type* ptr) :
|
|
||||||
mPointer(NULL)
|
|
||||||
{
|
|
||||||
assign(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLSafeHandle(const LLSafeHandle<Type>& ptr) :
|
|
||||||
mPointer(NULL)
|
|
||||||
{
|
|
||||||
assign(ptr.mPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
|
||||||
template<typename Subclass>
|
|
||||||
LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
|
|
||||||
mPointer(NULL)
|
|
||||||
{
|
|
||||||
assign(ptr.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
~LLSafeHandle()
|
|
||||||
{
|
|
||||||
unref();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Type* operator->() const { return nonNull(mPointer); }
|
|
||||||
Type* operator->() { return nonNull(mPointer); }
|
|
||||||
|
|
||||||
Type* get() const { return mPointer; }
|
|
||||||
// we disallow these operations as they expose our null objects to direct manipulation
|
|
||||||
// and bypass the reference counting semantics
|
|
||||||
//const Type& operator*() const { return *nonNull(mPointer); }
|
|
||||||
//Type& operator*() { return *nonNull(mPointer); }
|
|
||||||
|
|
||||||
operator BOOL() const { return mPointer != NULL; }
|
|
||||||
operator bool() const { return mPointer != NULL; }
|
|
||||||
bool operator!() const { return mPointer == NULL; }
|
|
||||||
bool isNull() const { return mPointer == NULL; }
|
|
||||||
bool notNull() const { return mPointer != NULL; }
|
|
||||||
|
|
||||||
|
|
||||||
operator Type*() const { return mPointer; }
|
|
||||||
operator const Type*() const { return mPointer; }
|
|
||||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
|
||||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
|
||||||
bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
|
||||||
bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
|
||||||
bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
|
||||||
|
|
||||||
LLSafeHandle<Type>& operator =(Type* ptr)
|
|
||||||
{
|
|
||||||
assign(ptr);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
|
|
||||||
{
|
|
||||||
assign(ptr.mPointer);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
|
||||||
template<typename Subclass>
|
|
||||||
LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
|
|
||||||
{
|
|
||||||
assign(ptr.get());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef Type* (*NullFunc)();
|
|
||||||
static const NullFunc sNullFunc;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void ref()
|
|
||||||
{
|
|
||||||
if (mPointer)
|
|
||||||
{
|
|
||||||
mPointer->ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void unref()
|
|
||||||
{
|
|
||||||
if (mPointer)
|
|
||||||
{
|
|
||||||
Type *tempp = mPointer;
|
|
||||||
mPointer = NULL;
|
|
||||||
tempp->unref();
|
|
||||||
if (mPointer != NULL)
|
|
||||||
{
|
|
||||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
|
||||||
unref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void assign(Type* ptr)
|
|
||||||
{
|
|
||||||
if( mPointer != ptr )
|
|
||||||
{
|
|
||||||
unref();
|
|
||||||
mPointer = ptr;
|
|
||||||
ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Type* nonNull(Type* ptr)
|
|
||||||
{
|
|
||||||
return ptr == NULL ? sNullFunc() : ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Type* mPointer;
|
|
||||||
};
|
|
||||||
|
|
||||||
// LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL
|
|
||||||
// NOT a smart pointer like LLPointer<>
|
|
||||||
// Useful for example in std::map<int,LLInitializedPointer<LLFoo> >
|
|
||||||
// (std::map uses the default constructor for creating new entries)
|
|
||||||
template <typename T> class LLInitializedPointer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLInitializedPointer() : mPointer(NULL) {}
|
|
||||||
~LLInitializedPointer() { delete mPointer; }
|
|
||||||
|
|
||||||
const T* operator->() const { return mPointer; }
|
|
||||||
T* operator->() { return mPointer; }
|
|
||||||
const T& operator*() const { return *mPointer; }
|
|
||||||
T& operator*() { return *mPointer; }
|
|
||||||
operator const T*() const { return mPointer; }
|
|
||||||
operator T*() { return mPointer; }
|
|
||||||
T* operator=(T* x) { return (mPointer = x); }
|
|
||||||
operator bool() const { return mPointer != NULL; }
|
|
||||||
bool operator!() const { return mPointer == NULL; }
|
|
||||||
bool operator==(T* rhs) { return mPointer == rhs; }
|
|
||||||
bool operator==(const LLInitializedPointer<T>* rhs) { return mPointer == rhs.mPointer; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
T* mPointer;
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// LLSingleton implements the getInstance() method part of the Singleton
|
|
||||||
// pattern. It can't make the derived class constructors protected, though, so
|
|
||||||
// you have to do that yourself.
|
|
||||||
//
|
|
||||||
// There are two ways to use LLSingleton. The first way is to inherit from it
|
|
||||||
// while using the typename that you'd like to be static as the template
|
|
||||||
// parameter, like so:
|
|
||||||
//
|
|
||||||
// class Foo: public LLSingleton<Foo>{};
|
|
||||||
//
|
|
||||||
// Foo& instance = Foo::instance();
|
|
||||||
//
|
|
||||||
// The second way is to use the singleton class directly, without inheritance:
|
|
||||||
//
|
|
||||||
// typedef LLSingleton<Foo> FooSingleton;
|
|
||||||
//
|
|
||||||
// Foo& instance = FooSingleton::instance();
|
|
||||||
//
|
|
||||||
// In this case, the class being managed as a singleton needs to provide an
|
|
||||||
// initSingleton() method since the LLSingleton virtual method won't be
|
|
||||||
// available
|
|
||||||
//
|
|
||||||
// As currently written, it is not thread-safe.
|
|
||||||
template <typename T>
|
|
||||||
class LLSingleton
|
|
||||||
{
|
|
||||||
static bool &needsInit()
|
|
||||||
{
|
|
||||||
static bool needs_init = true;
|
|
||||||
return needs_init;
|
|
||||||
}
|
|
||||||
public:
|
|
||||||
static bool instanceExists()
|
|
||||||
{
|
|
||||||
return !needsInit();
|
|
||||||
}
|
|
||||||
virtual ~LLSingleton() {}
|
|
||||||
#ifdef LL_MSVC7
|
|
||||||
// workaround for VC7 compiler bug
|
|
||||||
// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx
|
|
||||||
// our version doesn't introduce a nested struct so that you can still declare LLSingleton<MyClass>
|
|
||||||
// a friend and hide your constructor
|
|
||||||
static T* getInstance()
|
|
||||||
{
|
|
||||||
LLSingleton<T> singleton;
|
|
||||||
return singleton.vsHack();
|
|
||||||
}
|
|
||||||
|
|
||||||
T* vsHack()
|
|
||||||
#else
|
|
||||||
static T* getInstance()
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
static T instance;
|
|
||||||
bool &needs_init = needsInit();
|
|
||||||
if (needs_init)
|
|
||||||
{
|
|
||||||
needs_init = false;
|
|
||||||
instance.initSingleton();
|
|
||||||
}
|
|
||||||
return &instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
static T& instance()
|
|
||||||
{
|
|
||||||
return *getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual void initSingleton() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Return the resident set size of the current process, in bytes.
|
|
||||||
// Return value is zero if not known.
|
|
||||||
LL_COMMON_API U64 getCurrentRSS();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
170
indra/llcommon/llpointer.h
Normal file
170
indra/llcommon/llpointer.h
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
/**
|
||||||
|
* @file llpointer.h
|
||||||
|
* @brief A reference-counted pointer for objects derived from LLRefCount
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2002&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 LLPOINTER_H
|
||||||
|
#define LLPOINTER_H
|
||||||
|
|
||||||
|
#include "llerror.h" // *TODO: consider eliminating this
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
||||||
|
// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
|
||||||
|
// if LLFoo::LLFoo() does anything like put itself in an update queue.
|
||||||
|
// The queue may get accessed before it gets assigned to x.
|
||||||
|
// The correct implementation is:
|
||||||
|
// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
|
||||||
|
// x->instantiate(); // does stuff like place x into an update queue
|
||||||
|
|
||||||
|
// see llthread.h for LLThreadSafeRefCount
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Note: relies on Type having ref() and unref() methods
|
||||||
|
template <class Type> class LLPointer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
LLPointer() :
|
||||||
|
mPointer(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
LLPointer(Type* ptr) :
|
||||||
|
mPointer(ptr)
|
||||||
|
{
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
LLPointer(const LLPointer<Type>& ptr) :
|
||||||
|
mPointer(ptr.mPointer)
|
||||||
|
{
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||||
|
template<typename Subclass>
|
||||||
|
LLPointer(const LLPointer<Subclass>& ptr) :
|
||||||
|
mPointer(ptr.get())
|
||||||
|
{
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
~LLPointer()
|
||||||
|
{
|
||||||
|
unref();
|
||||||
|
}
|
||||||
|
|
||||||
|
Type* get() const { return mPointer; }
|
||||||
|
const Type* operator->() const { return mPointer; }
|
||||||
|
Type* operator->() { return mPointer; }
|
||||||
|
const Type& operator*() const { return *mPointer; }
|
||||||
|
Type& operator*() { return *mPointer; }
|
||||||
|
|
||||||
|
operator BOOL() const { return (mPointer != NULL); }
|
||||||
|
operator bool() const { return (mPointer != NULL); }
|
||||||
|
bool operator!() const { return (mPointer == NULL); }
|
||||||
|
bool isNull() const { return (mPointer == NULL); }
|
||||||
|
bool notNull() const { return (mPointer != NULL); }
|
||||||
|
|
||||||
|
operator Type*() const { return mPointer; }
|
||||||
|
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||||
|
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||||
|
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||||
|
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||||
|
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||||
|
|
||||||
|
LLPointer<Type>& operator =(Type* ptr)
|
||||||
|
{
|
||||||
|
if( mPointer != ptr )
|
||||||
|
{
|
||||||
|
unref();
|
||||||
|
mPointer = ptr;
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
|
||||||
|
{
|
||||||
|
if( mPointer != ptr.mPointer )
|
||||||
|
{
|
||||||
|
unref();
|
||||||
|
mPointer = ptr.mPointer;
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||||
|
template<typename Subclass>
|
||||||
|
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
|
||||||
|
{
|
||||||
|
if( mPointer != ptr.get() )
|
||||||
|
{
|
||||||
|
unref();
|
||||||
|
mPointer = ptr.get();
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just exchange the pointers, which will not change the reference counts.
|
||||||
|
static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
|
||||||
|
{
|
||||||
|
Type* temp = a.mPointer;
|
||||||
|
a.mPointer = b.mPointer;
|
||||||
|
b.mPointer = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ref()
|
||||||
|
{
|
||||||
|
if (mPointer)
|
||||||
|
{
|
||||||
|
mPointer->ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unref()
|
||||||
|
{
|
||||||
|
if (mPointer)
|
||||||
|
{
|
||||||
|
Type *tempp = mPointer;
|
||||||
|
mPointer = NULL;
|
||||||
|
tempp->unref();
|
||||||
|
if (mPointer != NULL)
|
||||||
|
{
|
||||||
|
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||||
|
unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Type* mPointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -41,7 +41,8 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
|
|||||||
LLThread(name),
|
LLThread(name),
|
||||||
mThreaded(threaded),
|
mThreaded(threaded),
|
||||||
mIdleThread(TRUE),
|
mIdleThread(TRUE),
|
||||||
mNextHandle(0)
|
mNextHandle(0),
|
||||||
|
mStarted(FALSE)
|
||||||
{
|
{
|
||||||
if (mThreaded)
|
if (mThreaded)
|
||||||
{
|
{
|
||||||
@@ -52,6 +53,10 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
|
|||||||
// MAIN THREAD
|
// MAIN THREAD
|
||||||
LLQueuedThread::~LLQueuedThread()
|
LLQueuedThread::~LLQueuedThread()
|
||||||
{
|
{
|
||||||
|
if (!mThreaded)
|
||||||
|
{
|
||||||
|
endThread();
|
||||||
|
}
|
||||||
shutdown();
|
shutdown();
|
||||||
// ~LLThread() will be called here
|
// ~LLThread() will be called here
|
||||||
}
|
}
|
||||||
@@ -90,6 +95,7 @@ void LLQueuedThread::shutdown()
|
|||||||
if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS)
|
if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS)
|
||||||
{
|
{
|
||||||
++active_count;
|
++active_count;
|
||||||
|
req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest
|
||||||
}
|
}
|
||||||
req->deleteRequest();
|
req->deleteRequest();
|
||||||
}
|
}
|
||||||
@@ -105,6 +111,14 @@ void LLQueuedThread::shutdown()
|
|||||||
// virtual
|
// virtual
|
||||||
S32 LLQueuedThread::update(U32 max_time_ms)
|
S32 LLQueuedThread::update(U32 max_time_ms)
|
||||||
{
|
{
|
||||||
|
if (!mStarted)
|
||||||
|
{
|
||||||
|
if (!mThreaded)
|
||||||
|
{
|
||||||
|
startThread();
|
||||||
|
mStarted = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
return updateQueue(max_time_ms);
|
return updateQueue(max_time_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,8 +132,11 @@ S32 LLQueuedThread::updateQueue(U32 max_time_ms)
|
|||||||
if (mThreaded)
|
if (mThreaded)
|
||||||
{
|
{
|
||||||
pending = getPending();
|
pending = getPending();
|
||||||
|
if(pending > 0)
|
||||||
|
{
|
||||||
unpause();
|
unpause();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (pending > 0)
|
while (pending > 0)
|
||||||
@@ -349,9 +366,9 @@ bool LLQueuedThread::completeRequest(handle_t handle)
|
|||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
// llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
|
// llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
|
||||||
#endif
|
#endif
|
||||||
//re insert to the queue to schedule for a delete later
|
mRequestHash.erase(handle);
|
||||||
req->setStatus(STATUS_DELETE);
|
req->deleteRequest();
|
||||||
mRequestQueue.insert(req);
|
// check();
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
unlockData();
|
unlockData();
|
||||||
@@ -395,19 +412,11 @@ S32 LLQueuedThread::processNextRequest()
|
|||||||
}
|
}
|
||||||
req = *mRequestQueue.begin();
|
req = *mRequestQueue.begin();
|
||||||
mRequestQueue.erase(mRequestQueue.begin());
|
mRequestQueue.erase(mRequestQueue.begin());
|
||||||
|
|
||||||
if(req->getStatus() == STATUS_DELETE)
|
|
||||||
{
|
|
||||||
mRequestHash.erase(req);
|
|
||||||
req->deleteRequest();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
|
if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
|
||||||
{
|
{
|
||||||
req->setStatus(STATUS_ABORTED);
|
req->setStatus(STATUS_ABORTED);
|
||||||
req->finishRequest(false);
|
req->finishRequest(false);
|
||||||
if ((req->getFlags() & FLAG_AUTO_COMPLETE))
|
if (req->getFlags() & FLAG_AUTO_COMPLETE)
|
||||||
{
|
{
|
||||||
mRequestHash.erase(req);
|
mRequestHash.erase(req);
|
||||||
req->deleteRequest();
|
req->deleteRequest();
|
||||||
@@ -418,9 +427,11 @@ S32 LLQueuedThread::processNextRequest()
|
|||||||
llassert_always(req->getStatus() == STATUS_QUEUED);
|
llassert_always(req->getStatus() == STATUS_QUEUED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
U32 start_priority = 0 ;
|
||||||
if (req)
|
if (req)
|
||||||
{
|
{
|
||||||
req->setStatus(STATUS_INPROGRESS);
|
req->setStatus(STATUS_INPROGRESS);
|
||||||
|
start_priority = req->getPriority();
|
||||||
}
|
}
|
||||||
unlockData();
|
unlockData();
|
||||||
|
|
||||||
@@ -436,13 +447,12 @@ S32 LLQueuedThread::processNextRequest()
|
|||||||
{
|
{
|
||||||
lockData();
|
lockData();
|
||||||
req->setStatus(STATUS_COMPLETE);
|
req->setStatus(STATUS_COMPLETE);
|
||||||
|
|
||||||
req->finishRequest(true);
|
req->finishRequest(true);
|
||||||
|
if (req->getFlags() & FLAG_AUTO_COMPLETE)
|
||||||
if ((req->getFlags() & FLAG_AUTO_COMPLETE))
|
|
||||||
{
|
{
|
||||||
mRequestHash.erase(req);
|
mRequestHash.erase(req);
|
||||||
req->deleteRequest();
|
req->deleteRequest();
|
||||||
|
// check();
|
||||||
}
|
}
|
||||||
unlockData();
|
unlockData();
|
||||||
}
|
}
|
||||||
@@ -451,9 +461,8 @@ S32 LLQueuedThread::processNextRequest()
|
|||||||
lockData();
|
lockData();
|
||||||
req->setStatus(STATUS_QUEUED);
|
req->setStatus(STATUS_QUEUED);
|
||||||
mRequestQueue.insert(req);
|
mRequestQueue.insert(req);
|
||||||
U32 priority = req->getPriority();
|
|
||||||
unlockData();
|
unlockData();
|
||||||
if (priority < PRIORITY_NORMAL)
|
if (mThreaded && start_priority < PRIORITY_NORMAL)
|
||||||
{
|
{
|
||||||
ms_sleep(1); // sleep the thread a little
|
ms_sleep(1); // sleep the thread a little
|
||||||
}
|
}
|
||||||
@@ -481,6 +490,7 @@ void LLQueuedThread::run()
|
|||||||
// call checPause() immediately so we don't try to do anything before the class is fully constructed
|
// call checPause() immediately so we don't try to do anything before the class is fully constructed
|
||||||
checkPause();
|
checkPause();
|
||||||
startThread();
|
startThread();
|
||||||
|
mStarted = TRUE;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ public:
|
|||||||
void waitOnPending();
|
void waitOnPending();
|
||||||
void printQueueStats();
|
void printQueueStats();
|
||||||
|
|
||||||
S32 getPending();
|
virtual S32 getPending();
|
||||||
bool getThreaded() { return mThreaded ? true : false; }
|
bool getThreaded() { return mThreaded ? true : false; }
|
||||||
|
|
||||||
// Request accessors
|
// Request accessors
|
||||||
@@ -202,6 +202,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
BOOL mThreaded; // if false, run on main thread and do updates during update()
|
BOOL mThreaded; // if false, run on main thread and do updates during update()
|
||||||
|
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
|
||||||
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
|
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
|
||||||
|
|
||||||
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
|
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
|
||||||
|
|||||||
164
indra/llcommon/llrefcount.cpp
Normal file
164
indra/llcommon/llrefcount.cpp
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/**
|
||||||
|
* @file llrefcount.cpp
|
||||||
|
* @brief Base class for reference counted objects for use with LLPointer
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2002&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 "linden_common.h"
|
||||||
|
|
||||||
|
#include "llrefcount.h"
|
||||||
|
|
||||||
|
#include "llerror.h"
|
||||||
|
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
#include "llthread.h"
|
||||||
|
#include "llapr.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LLRefCount::LLRefCount(const LLRefCount& other)
|
||||||
|
: mRef(0)
|
||||||
|
{
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
if(gAPRPoolp)
|
||||||
|
{
|
||||||
|
mMutexp = new LLMutex(gAPRPoolp) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mMutexp = NULL ;
|
||||||
|
}
|
||||||
|
mCrashAtUnlock = FALSE ;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||||
|
{
|
||||||
|
// do nothing, since ref count is specific to *this* reference
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLRefCount::LLRefCount() :
|
||||||
|
mRef(0)
|
||||||
|
{
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
if(gAPRPoolp)
|
||||||
|
{
|
||||||
|
mMutexp = new LLMutex(gAPRPoolp) ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mMutexp = NULL ;
|
||||||
|
}
|
||||||
|
mCrashAtUnlock = FALSE ;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
LLRefCount::~LLRefCount()
|
||||||
|
{
|
||||||
|
if (mRef != 0)
|
||||||
|
{
|
||||||
|
llerrs << "deleting non-zero reference" << llendl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
if(gAPRPoolp)
|
||||||
|
{
|
||||||
|
delete mMutexp ;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
void LLRefCount::ref() const
|
||||||
|
{
|
||||||
|
if(mMutexp)
|
||||||
|
{
|
||||||
|
if(mMutexp->isLocked())
|
||||||
|
{
|
||||||
|
mCrashAtUnlock = TRUE ;
|
||||||
|
llerrs << "the mutex is locked by the thread: " << mLockedThreadID
|
||||||
|
<< " Current thread: " << LLThread::currentID() << llendl ;
|
||||||
|
}
|
||||||
|
|
||||||
|
mMutexp->lock() ;
|
||||||
|
mLockedThreadID = LLThread::currentID() ;
|
||||||
|
|
||||||
|
mRef++;
|
||||||
|
|
||||||
|
if(mCrashAtUnlock)
|
||||||
|
{
|
||||||
|
while(1); //crash here.
|
||||||
|
}
|
||||||
|
mMutexp->unlock() ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mRef++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
S32 LLRefCount::unref() const
|
||||||
|
{
|
||||||
|
if(mMutexp)
|
||||||
|
{
|
||||||
|
if(mMutexp->isLocked())
|
||||||
|
{
|
||||||
|
mCrashAtUnlock = TRUE ;
|
||||||
|
llerrs << "the mutex is locked by the thread: " << mLockedThreadID
|
||||||
|
<< " Current thread: " << LLThread::currentID() << llendl ;
|
||||||
|
}
|
||||||
|
|
||||||
|
mMutexp->lock() ;
|
||||||
|
mLockedThreadID = LLThread::currentID() ;
|
||||||
|
|
||||||
|
llassert(mRef >= 1);
|
||||||
|
if (0 == --mRef)
|
||||||
|
{
|
||||||
|
if(mCrashAtUnlock)
|
||||||
|
{
|
||||||
|
while(1); //crash here.
|
||||||
|
}
|
||||||
|
mMutexp->unlock() ;
|
||||||
|
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mCrashAtUnlock)
|
||||||
|
{
|
||||||
|
while(1); //crash here.
|
||||||
|
}
|
||||||
|
mMutexp->unlock() ;
|
||||||
|
return mRef;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
llassert(mRef >= 1);
|
||||||
|
if (0 == --mRef)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return mRef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
89
indra/llcommon/llrefcount.h
Normal file
89
indra/llcommon/llrefcount.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* @file llrefcount.h
|
||||||
|
* @brief Base class for reference counted objects for use with LLPointer
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2002&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 LLREFCOUNT_H
|
||||||
|
#define LLREFCOUNT_H
|
||||||
|
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
#define LL_REF_COUNT_DEBUG 0
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
class LLMutex ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
||||||
|
// see llthread.h for LLThreadSafeRefCount
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class LL_COMMON_API LLRefCount
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
LLRefCount(const LLRefCount& other);
|
||||||
|
LLRefCount& operator=(const LLRefCount&);
|
||||||
|
virtual ~LLRefCount(); // use unref()
|
||||||
|
|
||||||
|
public:
|
||||||
|
LLRefCount();
|
||||||
|
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
void ref() const ;
|
||||||
|
S32 unref() const ;
|
||||||
|
#else
|
||||||
|
inline void ref() const
|
||||||
|
{
|
||||||
|
mRef++;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline S32 unref() const
|
||||||
|
{
|
||||||
|
llassert(mRef >= 1);
|
||||||
|
if (0 == --mRef)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return mRef;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//NOTE: when passing around a const LLRefCount object, this can return different results
|
||||||
|
// at different types, since mRef is mutable
|
||||||
|
S32 getNumRefs() const
|
||||||
|
{
|
||||||
|
return mRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable S32 mRef;
|
||||||
|
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
LLMutex* mMutexp ;
|
||||||
|
mutable U32 mLockedThreadID ;
|
||||||
|
mutable BOOL mCrashAtUnlock ;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
162
indra/llcommon/llsafehandle.h
Normal file
162
indra/llcommon/llsafehandle.h
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
/**
|
||||||
|
* @file llsafehandle.h
|
||||||
|
* @brief Reference-counted object where Object() is valid, not NULL.
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2002&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 LLSAFEHANDLE_H
|
||||||
|
#define LLSAFEHANDLE_H
|
||||||
|
|
||||||
|
#include "llerror.h" // *TODO: consider eliminating this
|
||||||
|
|
||||||
|
// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
|
||||||
|
// This is useful in instances where operations on NULL pointers are semantically safe and/or
|
||||||
|
// when error checking occurs at a different granularity or in a different part of the code
|
||||||
|
// than when referencing an object via a LLSafeHandle.
|
||||||
|
|
||||||
|
template <class Type>
|
||||||
|
class LLSafeHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLSafeHandle() :
|
||||||
|
mPointer(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
LLSafeHandle(Type* ptr) :
|
||||||
|
mPointer(NULL)
|
||||||
|
{
|
||||||
|
assign(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLSafeHandle(const LLSafeHandle<Type>& ptr) :
|
||||||
|
mPointer(NULL)
|
||||||
|
{
|
||||||
|
assign(ptr.mPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||||
|
template<typename Subclass>
|
||||||
|
LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
|
||||||
|
mPointer(NULL)
|
||||||
|
{
|
||||||
|
assign(ptr.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
~LLSafeHandle()
|
||||||
|
{
|
||||||
|
unref();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type* operator->() const { return nonNull(mPointer); }
|
||||||
|
Type* operator->() { return nonNull(mPointer); }
|
||||||
|
|
||||||
|
Type* get() const { return mPointer; }
|
||||||
|
void clear() { assign(NULL); }
|
||||||
|
// we disallow these operations as they expose our null objects to direct manipulation
|
||||||
|
// and bypass the reference counting semantics
|
||||||
|
//const Type& operator*() const { return *nonNull(mPointer); }
|
||||||
|
//Type& operator*() { return *nonNull(mPointer); }
|
||||||
|
|
||||||
|
operator BOOL() const { return mPointer != NULL; }
|
||||||
|
operator bool() const { return mPointer != NULL; }
|
||||||
|
bool operator!() const { return mPointer == NULL; }
|
||||||
|
bool isNull() const { return mPointer == NULL; }
|
||||||
|
bool notNull() const { return mPointer != NULL; }
|
||||||
|
|
||||||
|
|
||||||
|
operator Type*() const { return mPointer; }
|
||||||
|
operator const Type*() const { return mPointer; }
|
||||||
|
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||||
|
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||||
|
bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||||
|
bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||||
|
bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||||
|
|
||||||
|
LLSafeHandle<Type>& operator =(Type* ptr)
|
||||||
|
{
|
||||||
|
assign(ptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
|
||||||
|
{
|
||||||
|
assign(ptr.mPointer);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||||
|
template<typename Subclass>
|
||||||
|
LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
|
||||||
|
{
|
||||||
|
assign(ptr.get());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Type* (*NullFunc)();
|
||||||
|
static const NullFunc sNullFunc;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void ref()
|
||||||
|
{
|
||||||
|
if (mPointer)
|
||||||
|
{
|
||||||
|
mPointer->ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unref()
|
||||||
|
{
|
||||||
|
if (mPointer)
|
||||||
|
{
|
||||||
|
Type *tempp = mPointer;
|
||||||
|
mPointer = NULL;
|
||||||
|
tempp->unref();
|
||||||
|
if (mPointer != NULL)
|
||||||
|
{
|
||||||
|
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||||
|
unref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign(Type* ptr)
|
||||||
|
{
|
||||||
|
if( mPointer != ptr )
|
||||||
|
{
|
||||||
|
unref();
|
||||||
|
mPointer = ptr;
|
||||||
|
ref();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Type* nonNull(Type* ptr)
|
||||||
|
{
|
||||||
|
return ptr == NULL ? sNullFunc() : ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Type* mPointer;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -39,6 +39,13 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "apr_base64.h"
|
#include "apr_base64.h"
|
||||||
|
#if MESH_ENABLED
|
||||||
|
#ifdef LL_STANDALONE
|
||||||
|
# include <zlib.h>
|
||||||
|
#else
|
||||||
|
# include "zlib/zlib.h" // for davep's dirty little zip functions
|
||||||
|
#endif
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
#if !LL_WINDOWS
|
#if !LL_WINDOWS
|
||||||
#include <netinet/in.h> // htonl & ntohl
|
#include <netinet/in.h> // htonl & ntohl
|
||||||
@@ -1990,3 +1997,181 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
|
||||||
|
//dirty little zippers -- yell at davep if these are horrid
|
||||||
|
|
||||||
|
//return a string containing gzipped bytes of binary serialized LLSD
|
||||||
|
// VERY inefficient -- creates several copies of LLSD block in memory
|
||||||
|
std::string zip_llsd(LLSD& data)
|
||||||
|
{
|
||||||
|
std::stringstream llsd_strm;
|
||||||
|
|
||||||
|
LLSDSerialize::toBinary(data, llsd_strm);
|
||||||
|
|
||||||
|
const U32 CHUNK = 65536;
|
||||||
|
|
||||||
|
z_stream strm;
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
|
||||||
|
S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
|
||||||
|
if (ret != Z_OK)
|
||||||
|
{
|
||||||
|
llwarns << "Failed to compress LLSD block." << llendl;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string source = llsd_strm.str();
|
||||||
|
|
||||||
|
U8 out[CHUNK];
|
||||||
|
|
||||||
|
strm.avail_in = source.size();
|
||||||
|
strm.next_in = (U8*) source.data();
|
||||||
|
U8* output = NULL;
|
||||||
|
|
||||||
|
U32 cur_size = 0;
|
||||||
|
|
||||||
|
U32 have = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
strm.avail_out = CHUNK;
|
||||||
|
strm.next_out = out;
|
||||||
|
|
||||||
|
ret = deflate(&strm, Z_FINISH);
|
||||||
|
if (ret == Z_OK || ret == Z_STREAM_END)
|
||||||
|
{ //copy result into output
|
||||||
|
if (strm.avail_out >= CHUNK)
|
||||||
|
{
|
||||||
|
free(output);
|
||||||
|
llwarns << "Failed to compress LLSD block." << llendl;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
have = CHUNK-strm.avail_out;
|
||||||
|
output = (U8*) realloc(output, cur_size+have);
|
||||||
|
memcpy(output+cur_size, out, have);
|
||||||
|
cur_size += have;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(output);
|
||||||
|
llwarns << "Failed to compress LLSD block." << llendl;
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (ret == Z_OK);
|
||||||
|
|
||||||
|
std::string::size_type size = cur_size;
|
||||||
|
|
||||||
|
std::string result((char*) output, size);
|
||||||
|
deflateEnd(&strm);
|
||||||
|
free(output);
|
||||||
|
|
||||||
|
#if 0 //verify results work with unzip_llsd
|
||||||
|
std::istringstream test(result);
|
||||||
|
LLSD test_sd;
|
||||||
|
if (!unzip_llsd(test_sd, test, result.size()))
|
||||||
|
{
|
||||||
|
llerrs << "Invalid compression result!" << llendl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//decompress a block of LLSD from provided istream
|
||||||
|
// not very efficient -- creats a copy of decompressed LLSD block in memory
|
||||||
|
// and deserializes from that copy using LLSDSerialize
|
||||||
|
bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
|
||||||
|
{
|
||||||
|
U8* result = NULL;
|
||||||
|
U32 cur_size = 0;
|
||||||
|
z_stream strm;
|
||||||
|
|
||||||
|
const U32 CHUNK = 65536;
|
||||||
|
|
||||||
|
U8 *in = new U8[size];
|
||||||
|
is.read((char*) in, size);
|
||||||
|
|
||||||
|
U8 out[CHUNK];
|
||||||
|
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
strm.avail_in = size;
|
||||||
|
strm.next_in = in;
|
||||||
|
|
||||||
|
S32 ret = inflateInit(&strm);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
strm.avail_out = CHUNK;
|
||||||
|
strm.next_out = out;
|
||||||
|
ret = inflate(&strm, Z_NO_FLUSH);
|
||||||
|
if (ret == Z_STREAM_ERROR)
|
||||||
|
{
|
||||||
|
inflateEnd(&strm);
|
||||||
|
free(result);
|
||||||
|
delete [] in;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ret)
|
||||||
|
{
|
||||||
|
case Z_NEED_DICT:
|
||||||
|
ret = Z_DATA_ERROR;
|
||||||
|
case Z_DATA_ERROR:
|
||||||
|
case Z_MEM_ERROR:
|
||||||
|
inflateEnd(&strm);
|
||||||
|
free(result);
|
||||||
|
delete [] in;
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 have = CHUNK-strm.avail_out;
|
||||||
|
|
||||||
|
result = (U8*) realloc(result, cur_size + have);
|
||||||
|
memcpy(result+cur_size, out, have);
|
||||||
|
cur_size += have;
|
||||||
|
|
||||||
|
} while (ret == Z_OK);
|
||||||
|
|
||||||
|
inflateEnd(&strm);
|
||||||
|
delete [] in;
|
||||||
|
|
||||||
|
if (ret != Z_STREAM_END)
|
||||||
|
{
|
||||||
|
free(result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//result now points to the decompressed LLSD block
|
||||||
|
{
|
||||||
|
std::string res_str((char*) result, cur_size);
|
||||||
|
|
||||||
|
std::string deprecated_header("<? LLSD/Binary ?>");
|
||||||
|
|
||||||
|
if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
|
||||||
|
{
|
||||||
|
res_str = res_str.substr(deprecated_header.size()+1, cur_size);
|
||||||
|
}
|
||||||
|
cur_size = res_str.size();
|
||||||
|
|
||||||
|
std::istringstream istr(res_str);
|
||||||
|
|
||||||
|
if (!LLSDSerialize::fromBinary(data, istr, cur_size))
|
||||||
|
{
|
||||||
|
llwarns << "Failed to unzip LLSD block" << llendl;
|
||||||
|
free(result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif //MESH_ENABLED
|
||||||
@@ -787,4 +787,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
//dirty little zip functions -- yell at davep
|
||||||
|
LL_COMMON_API std::string zip_llsd(LLSD& data);
|
||||||
|
LL_COMMON_API bool unzip_llsd(LLSD& data, std::istream& is, S32 size);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
#endif // LL_LLSDSERIALIZE_H
|
#endif // LL_LLSDSERIALIZE_H
|
||||||
|
|||||||
32
indra/llcommon/llsingleton.cpp
Normal file
32
indra/llcommon/llsingleton.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* @file llsingleton.cpp
|
||||||
|
* @author Brad Kittenbrink
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2009&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 "linden_common.h"
|
||||||
|
|
||||||
|
#include "llsingleton.h"
|
||||||
|
|
||||||
|
std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL;
|
||||||
|
|
||||||
201
indra/llcommon/llsingleton.h
Normal file
201
indra/llcommon/llsingleton.h
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/**
|
||||||
|
* @file llsingleton.h
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2002&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 LLSINGLETON_H
|
||||||
|
#define LLSINGLETON_H
|
||||||
|
|
||||||
|
#include "llerror.h" // *TODO: eliminate this
|
||||||
|
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
/// @brief A global registry of all singletons to prevent duplicate allocations
|
||||||
|
/// across shared library boundaries
|
||||||
|
class LL_COMMON_API LLSingletonRegistry {
|
||||||
|
private:
|
||||||
|
typedef std::map<std::string, void *> TypeMap;
|
||||||
|
static TypeMap * sSingletonMap;
|
||||||
|
|
||||||
|
static void checkInit()
|
||||||
|
{
|
||||||
|
if(sSingletonMap == NULL)
|
||||||
|
{
|
||||||
|
sSingletonMap = new TypeMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template<typename T> static void * & get()
|
||||||
|
{
|
||||||
|
std::string name(typeid(T).name());
|
||||||
|
|
||||||
|
checkInit();
|
||||||
|
|
||||||
|
// the first entry of the pair returned by insert will be either the existing
|
||||||
|
// iterator matching our key, or the newly inserted NULL initialized entry
|
||||||
|
// see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||||
|
TypeMap::iterator result =
|
||||||
|
sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
|
||||||
|
|
||||||
|
return result->second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// LLSingleton implements the getInstance() method part of the Singleton
|
||||||
|
// pattern. It can't make the derived class constructors protected, though, so
|
||||||
|
// you have to do that yourself.
|
||||||
|
//
|
||||||
|
// There are two ways to use LLSingleton. The first way is to inherit from it
|
||||||
|
// while using the typename that you'd like to be static as the template
|
||||||
|
// parameter, like so:
|
||||||
|
//
|
||||||
|
// class Foo: public LLSingleton<Foo>{};
|
||||||
|
//
|
||||||
|
// Foo& instance = Foo::instance();
|
||||||
|
//
|
||||||
|
// The second way is to use the singleton class directly, without inheritance:
|
||||||
|
//
|
||||||
|
// typedef LLSingleton<Foo> FooSingleton;
|
||||||
|
//
|
||||||
|
// Foo& instance = FooSingleton::instance();
|
||||||
|
//
|
||||||
|
// In this case, the class being managed as a singleton needs to provide an
|
||||||
|
// initSingleton() method since the LLSingleton virtual method won't be
|
||||||
|
// available
|
||||||
|
//
|
||||||
|
// As currently written, it is not thread-safe.
|
||||||
|
|
||||||
|
template <typename DERIVED_TYPE>
|
||||||
|
class LLSingleton : private boost::noncopyable
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef enum e_init_state
|
||||||
|
{
|
||||||
|
UNINITIALIZED,
|
||||||
|
CONSTRUCTING,
|
||||||
|
INITIALIZING,
|
||||||
|
INITIALIZED,
|
||||||
|
DELETED
|
||||||
|
} EInitState;
|
||||||
|
|
||||||
|
static void deleteSingleton()
|
||||||
|
{
|
||||||
|
delete getData().mSingletonInstance;
|
||||||
|
getData().mSingletonInstance = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stores pointer to singleton instance
|
||||||
|
// and tracks initialization state of singleton
|
||||||
|
struct SingletonInstanceData
|
||||||
|
{
|
||||||
|
EInitState mInitState;
|
||||||
|
DERIVED_TYPE* mSingletonInstance;
|
||||||
|
|
||||||
|
SingletonInstanceData()
|
||||||
|
: mSingletonInstance(NULL),
|
||||||
|
mInitState(UNINITIALIZED)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~SingletonInstanceData()
|
||||||
|
{
|
||||||
|
deleteSingleton();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ~LLSingleton()
|
||||||
|
{
|
||||||
|
SingletonInstanceData& data = getData();
|
||||||
|
data.mSingletonInstance = NULL;
|
||||||
|
data.mInitState = DELETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SingletonInstanceData& getData()
|
||||||
|
{
|
||||||
|
// this is static to cache the lookup results
|
||||||
|
static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
|
||||||
|
|
||||||
|
// *TODO - look into making this threadsafe
|
||||||
|
if(NULL == registry)
|
||||||
|
{
|
||||||
|
static SingletonInstanceData data;
|
||||||
|
registry = &data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *static_cast<SingletonInstanceData *>(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DERIVED_TYPE* getInstance()
|
||||||
|
{
|
||||||
|
SingletonInstanceData& data = getData();
|
||||||
|
|
||||||
|
if (data.mInitState == CONSTRUCTING)
|
||||||
|
{
|
||||||
|
llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.mInitState == DELETED)
|
||||||
|
{
|
||||||
|
llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.mSingletonInstance)
|
||||||
|
{
|
||||||
|
data.mInitState = CONSTRUCTING;
|
||||||
|
data.mSingletonInstance = new DERIVED_TYPE();
|
||||||
|
data.mInitState = INITIALIZING;
|
||||||
|
data.mSingletonInstance->initSingleton();
|
||||||
|
data.mInitState = INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.mSingletonInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference version of getInstance()
|
||||||
|
// Preferred over getInstance() as it disallows checking for NULL
|
||||||
|
static DERIVED_TYPE& instance()
|
||||||
|
{
|
||||||
|
return *getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has this singleton been created uet?
|
||||||
|
// Use this to avoid accessing singletons before the can safely be constructed
|
||||||
|
static bool instanceExists()
|
||||||
|
{
|
||||||
|
return getData().mInitState == INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has this singleton already been deleted?
|
||||||
|
// Use this to avoid accessing singletons from a static object's destructor
|
||||||
|
static bool destroyed()
|
||||||
|
{
|
||||||
|
return getData().mInitState == DELETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void initSingleton() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -62,6 +62,21 @@
|
|||||||
//
|
//
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if !LL_DARWIN
|
||||||
|
U32 ll_thread_local sThreadID = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
U32 LLThread::sIDIter = 0;
|
||||||
|
|
||||||
|
LL_COMMON_API void assert_main_thread()
|
||||||
|
{
|
||||||
|
static U32 s_thread_id = LLThread::currentID();
|
||||||
|
if (LLThread::currentID() != s_thread_id)
|
||||||
|
{
|
||||||
|
llerrs << "Illegal execution outside main thread." << llendl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handed to the APR thread creation function
|
// Handed to the APR thread creation function
|
||||||
//
|
//
|
||||||
@@ -73,8 +88,10 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
|
|||||||
|
|
||||||
LLThread *threadp = (LLThread *)datap;
|
LLThread *threadp = (LLThread *)datap;
|
||||||
|
|
||||||
// Set thread state to running
|
#if !LL_DARWIN
|
||||||
threadp->mStatus = RUNNING;
|
sThreadID = threadp->mID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Create a thread local data.
|
// Create a thread local data.
|
||||||
AIThreadLocalData::create(threadp);
|
AIThreadLocalData::create(threadp);
|
||||||
@@ -98,6 +115,7 @@ LLThread::LLThread(std::string const& name) :
|
|||||||
mStatus(STOPPED),
|
mStatus(STOPPED),
|
||||||
mThreadLocalData(NULL)
|
mThreadLocalData(NULL)
|
||||||
{
|
{
|
||||||
|
mID = ++sIDIter;
|
||||||
mRunCondition = new LLCondition;
|
mRunCondition = new LLCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +137,7 @@ void LLThread::shutdown()
|
|||||||
// First, set the flag that indicates that we're ready to die
|
// First, set the flag that indicates that we're ready to die
|
||||||
setQuitting();
|
setQuitting();
|
||||||
|
|
||||||
llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl;
|
llinfos << "LLThread::shutdown() Killing thread " << mName << " Status: " << mStatus << llendl;
|
||||||
// Now wait a bit for the thread to exit
|
// Now wait a bit for the thread to exit
|
||||||
// It's unclear whether I should even bother doing this - this destructor
|
// It's unclear whether I should even bother doing this - this destructor
|
||||||
// should netver get called unless we're already stopped, really...
|
// should netver get called unless we're already stopped, really...
|
||||||
@@ -142,20 +160,38 @@ void LLThread::shutdown()
|
|||||||
{
|
{
|
||||||
// This thread just wouldn't stop, even though we gave it time
|
// This thread just wouldn't stop, even though we gave it time
|
||||||
llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl;
|
llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl;
|
||||||
|
// Put a stake in its heart.
|
||||||
|
apr_thread_exit(mAPRThreadp, -1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mAPRThreadp = NULL;
|
mAPRThreadp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete mRunCondition;
|
delete mRunCondition;
|
||||||
|
mRunCondition = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLThread::start()
|
void LLThread::start()
|
||||||
{
|
{
|
||||||
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool());
|
llassert(isStopped());
|
||||||
|
|
||||||
// We won't bother joining
|
// Set thread state to running
|
||||||
apr_thread_detach(mAPRThreadp);
|
mStatus = RUNNING;
|
||||||
|
|
||||||
|
apr_status_t status =
|
||||||
|
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool());
|
||||||
|
|
||||||
|
if(status == APR_SUCCESS)
|
||||||
|
{
|
||||||
|
// We won't bother joining
|
||||||
|
apr_thread_detach(mAPRThreadp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mStatus = STOPPED;
|
||||||
|
llwarns << "failed to start thread " << mName << llendl;
|
||||||
|
ll_apr_warn_status(status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
@@ -318,6 +354,55 @@ AIThreadLocalData& AIThreadLocalData::tldata(void)
|
|||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
void LLMutexBase::lock()
|
||||||
|
{
|
||||||
|
#if LL_DARWIN
|
||||||
|
if (mLockingThread == LLThread::currentID())
|
||||||
|
#else
|
||||||
|
if (mLockingThread == sThreadID)
|
||||||
|
#endif
|
||||||
|
{ //redundant lock
|
||||||
|
mCount++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
apr_thread_mutex_lock(mAPRMutexp);
|
||||||
|
|
||||||
|
#if MUTEX_DEBUG
|
||||||
|
// Have to have the lock before we can access the debug info
|
||||||
|
U32 id = LLThread::currentID();
|
||||||
|
if (mIsLocked[id] != FALSE)
|
||||||
|
llerrs << "Already locked in Thread: " << id << llendl;
|
||||||
|
mIsLocked[id] = TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LL_DARWIN
|
||||||
|
mLockingThread = LLThread::currentID();
|
||||||
|
#else
|
||||||
|
mLockingThread = sThreadID;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLMutexBase::unlock()
|
||||||
|
{
|
||||||
|
if (mCount > 0)
|
||||||
|
{ //not the root unlock
|
||||||
|
mCount--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MUTEX_DEBUG
|
||||||
|
// Access the debug info while we have the lock
|
||||||
|
U32 id = LLThread::currentID();
|
||||||
|
if (mIsLocked[id] != TRUE)
|
||||||
|
llerrs << "Not locked in Thread: " << id << llendl;
|
||||||
|
mIsLocked[id] = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mLockingThread = NO_THREAD;
|
||||||
|
apr_thread_mutex_unlock(mAPRMutexp);
|
||||||
|
}
|
||||||
|
|
||||||
bool LLMutexBase::isLocked()
|
bool LLMutexBase::isLocked()
|
||||||
{
|
{
|
||||||
if (!tryLock())
|
if (!tryLock())
|
||||||
@@ -328,6 +413,11 @@ bool LLMutexBase::isLocked()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
U32 LLMutexBase::lockingThread() const
|
||||||
|
{
|
||||||
|
return mLockingThread;
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent)
|
LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent)
|
||||||
@@ -335,14 +425,25 @@ LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent)
|
|||||||
apr_thread_cond_create(&mAPRCondp, mPool());
|
apr_thread_cond_create(&mAPRCondp, mPool());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LLCondition::~LLCondition()
|
LLCondition::~LLCondition()
|
||||||
{
|
{
|
||||||
apr_thread_cond_destroy(mAPRCondp);
|
apr_thread_cond_destroy(mAPRCondp);
|
||||||
mAPRCondp = NULL;
|
mAPRCondp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LLCondition::wait()
|
void LLCondition::wait()
|
||||||
{
|
{
|
||||||
|
if (!isLocked())
|
||||||
|
{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
|
||||||
|
apr_thread_mutex_lock(mAPRMutexp);
|
||||||
|
#if MUTEX_DEBUG
|
||||||
|
// avoid asserts on destruction in non-release builds
|
||||||
|
U32 id = LLThread::currentID();
|
||||||
|
mIsLocked[id] = TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
|
apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,12 @@ class LLThread;
|
|||||||
class LLMutex;
|
class LLMutex;
|
||||||
class LLCondition;
|
class LLCondition;
|
||||||
|
|
||||||
|
#if LL_WINDOWS
|
||||||
|
#define ll_thread_local __declspec(thread)
|
||||||
|
#else
|
||||||
|
#define ll_thread_local __thread
|
||||||
|
#endif
|
||||||
|
|
||||||
class LL_COMMON_API AIThreadLocalData
|
class LL_COMMON_API AIThreadLocalData
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -66,6 +72,9 @@ public:
|
|||||||
|
|
||||||
class LL_COMMON_API LLThread
|
class LL_COMMON_API LLThread
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
static U32 sIDIter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef enum e_thread_status
|
typedef enum e_thread_status
|
||||||
{
|
{
|
||||||
@@ -106,6 +115,8 @@ public:
|
|||||||
// Return thread-local data for the current thread.
|
// Return thread-local data for the current thread.
|
||||||
static AIThreadLocalData& tldata(void) { return AIThreadLocalData::tldata(); }
|
static AIThreadLocalData& tldata(void) { return AIThreadLocalData::tldata(); }
|
||||||
|
|
||||||
|
U32 getID() const { return mID; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BOOL mPaused;
|
BOOL mPaused;
|
||||||
|
|
||||||
@@ -118,6 +129,7 @@ protected:
|
|||||||
|
|
||||||
apr_thread_t *mAPRThreadp;
|
apr_thread_t *mAPRThreadp;
|
||||||
EThreadStatus mStatus;
|
EThreadStatus mStatus;
|
||||||
|
U32 mID;
|
||||||
|
|
||||||
friend void AIThreadLocalData::create(LLThread* threadp);
|
friend void AIThreadLocalData::create(LLThread* threadp);
|
||||||
AIThreadLocalData* mThreadLocalData;
|
AIThreadLocalData* mThreadLocalData;
|
||||||
@@ -151,16 +163,26 @@ protected:
|
|||||||
class LL_COMMON_API LLMutexBase
|
class LL_COMMON_API LLMutexBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void lock() { apr_thread_mutex_lock(mAPRMutexp); }
|
typedef enum
|
||||||
void unlock() { apr_thread_mutex_unlock(mAPRMutexp); }
|
{
|
||||||
|
NO_THREAD = 0xFFFFFFFF
|
||||||
|
} e_locking_thread;
|
||||||
|
|
||||||
|
LLMutexBase() : mLockingThread(NO_THREAD), mCount(0) {}
|
||||||
|
|
||||||
|
void lock(); //blocks
|
||||||
|
void unlock();
|
||||||
// Returns true if lock was obtained successfully.
|
// Returns true if lock was obtained successfully.
|
||||||
bool tryLock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); }
|
bool tryLock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); }
|
||||||
|
|
||||||
bool isLocked(); // non-blocking, but does do a lock/unlock so not free
|
bool isLocked(); // non-blocking, but does do a lock/unlock so not free
|
||||||
|
U32 lockingThread() const; //get ID of locking thread
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// mAPRMutexp is initialized and uninitialized in the derived class.
|
// mAPRMutexp is initialized and uninitialized in the derived class.
|
||||||
apr_thread_mutex_t* mAPRMutexp;
|
apr_thread_mutex_t* mAPRMutexp;
|
||||||
|
mutable U32 mCount;
|
||||||
|
mutable U32 mLockingThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LL_COMMON_API LLMutex : public LLMutexBase
|
class LL_COMMON_API LLMutex : public LLMutexBase
|
||||||
@@ -350,6 +372,7 @@ void LLThread::unlockData()
|
|||||||
mRunCondition->unlock();
|
mRunCondition->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
// see llmemory.h for LLPointer<> definition
|
// see llmemory.h for LLPointer<> definition
|
||||||
|
|||||||
@@ -1354,3 +1354,13 @@ LLParcel::ECategory category_ui_string_to_category(const std::string& s)
|
|||||||
// is a distinct option from "None" and "Other"
|
// is a distinct option from "None" and "Other"
|
||||||
return LLParcel::C_ANY;
|
return LLParcel::C_ANY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
void LLParcel::updateQuota( const LLUUID& objectId, const ParcelQuota& quota )
|
||||||
|
{
|
||||||
|
if ( mID == objectId )
|
||||||
|
{
|
||||||
|
mQuota = quota;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|||||||
@@ -38,8 +38,11 @@
|
|||||||
#include "lluuid.h"
|
#include "lluuid.h"
|
||||||
#include "llparcelflags.h"
|
#include "llparcelflags.h"
|
||||||
#include "llpermissions.h"
|
#include "llpermissions.h"
|
||||||
#include "v3math.h"
|
|
||||||
#include "lltimer.h"
|
#include "lltimer.h"
|
||||||
|
#include "v3math.h"
|
||||||
|
#if MESH_ENABLED
|
||||||
|
#include "llaccountingquota.h"
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
// Grid out of which parcels taken is stepped every 4 meters.
|
// Grid out of which parcels taken is stepped every 4 meters.
|
||||||
const F32 PARCEL_GRID_STEP_METERS = 4.f;
|
const F32 PARCEL_GRID_STEP_METERS = 4.f;
|
||||||
@@ -599,6 +602,10 @@ public:
|
|||||||
BOOL getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; }
|
BOOL getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; }
|
||||||
BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; }
|
BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; }
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
void updateQuota( const LLUUID& objectId, const ParcelQuota& quota );
|
||||||
|
const ParcelQuota& getQuota( void ) { return mQuota; }
|
||||||
|
#endif //MESH_ENABLED
|
||||||
protected:
|
protected:
|
||||||
LLUUID mID;
|
LLUUID mID;
|
||||||
LLUUID mOwnerID;
|
LLUUID mOwnerID;
|
||||||
@@ -671,7 +678,9 @@ protected:
|
|||||||
BOOL mRegionPushOverride;
|
BOOL mRegionPushOverride;
|
||||||
BOOL mRegionDenyAnonymousOverride;
|
BOOL mRegionDenyAnonymousOverride;
|
||||||
BOOL mRegionDenyAgeUnverifiedOverride;
|
BOOL mRegionDenyAgeUnverifiedOverride;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
ParcelQuota mQuota;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// HACK, make private
|
// HACK, make private
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ public:
|
|||||||
{
|
{
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
{
|
{
|
||||||
//OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
|
OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LLOctreeNode<T>* parent = getOctParent();
|
LLOctreeNode<T>* parent = getOctParent();
|
||||||
@@ -389,7 +389,7 @@ public:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
//it's not in here, give it to the root
|
//it's not in here, give it to the root
|
||||||
//OCT_ERRS << "Octree insertion failed, starting over from root!" << llendl;
|
OCT_ERRS << "Octree insertion failed, starting over from root!" << llendl;
|
||||||
|
|
||||||
oct_node* node = this;
|
oct_node* node = this;
|
||||||
|
|
||||||
@@ -590,7 +590,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//OCT_ERRS << "Octree failed to delete requested child." << llendl;
|
OCT_ERRS << "Octree failed to delete requested child." << llendl;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -670,13 +670,13 @@ public:
|
|||||||
{
|
{
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
{
|
{
|
||||||
//OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl;
|
OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->getBinRadius() > 4096.0)
|
if (data->getBinRadius() > 4096.0)
|
||||||
{
|
{
|
||||||
//OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl;
|
OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,7 +692,7 @@ public:
|
|||||||
|
|
||||||
if (lt != 0x7)
|
if (lt != 0x7)
|
||||||
{
|
{
|
||||||
//OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl;
|
OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -40,8 +40,13 @@ class LLPathParams;
|
|||||||
class LLVolumeParams;
|
class LLVolumeParams;
|
||||||
class LLProfile;
|
class LLProfile;
|
||||||
class LLPath;
|
class LLPath;
|
||||||
|
|
||||||
|
template <class T> class LLOctreeNode;
|
||||||
|
|
||||||
|
class LLVector4a;
|
||||||
class LLVolumeFace;
|
class LLVolumeFace;
|
||||||
class LLVolume;
|
class LLVolume;
|
||||||
|
class LLVolumeTriangle;
|
||||||
|
|
||||||
#include "lldarray.h"
|
#include "lldarray.h"
|
||||||
#include "lluuid.h"
|
#include "lluuid.h"
|
||||||
@@ -186,12 +191,21 @@ const U8 LL_SCULPT_TYPE_SPHERE = 1;
|
|||||||
const U8 LL_SCULPT_TYPE_TORUS = 2;
|
const U8 LL_SCULPT_TYPE_TORUS = 2;
|
||||||
const U8 LL_SCULPT_TYPE_PLANE = 3;
|
const U8 LL_SCULPT_TYPE_PLANE = 3;
|
||||||
const U8 LL_SCULPT_TYPE_CYLINDER = 4;
|
const U8 LL_SCULPT_TYPE_CYLINDER = 4;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
const U8 LL_SCULPT_TYPE_MESH = 5;
|
||||||
|
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
|
||||||
|
LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
#if !MESH_ENABLED
|
||||||
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER;
|
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER;
|
||||||
|
#endif //!MESH_ENABLED
|
||||||
|
|
||||||
const U8 LL_SCULPT_FLAG_INVERT = 64;
|
const U8 LL_SCULPT_FLAG_INVERT = 64;
|
||||||
const U8 LL_SCULPT_FLAG_MIRROR = 128;
|
const U8 LL_SCULPT_FLAG_MIRROR = 128;
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
const S32 LL_SCULPT_MESH_MAX_FACES = 8;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
class LLProfileParams
|
class LLProfileParams
|
||||||
{
|
{
|
||||||
@@ -578,6 +592,9 @@ public:
|
|||||||
BOOL importLegacyStream(std::istream& input_stream);
|
BOOL importLegacyStream(std::istream& input_stream);
|
||||||
BOOL exportLegacyStream(std::ostream& output_stream) const;
|
BOOL exportLegacyStream(std::ostream& output_stream) const;
|
||||||
|
|
||||||
|
LLSD sculptAsLLSD() const;
|
||||||
|
bool sculptFromLLSD(LLSD& sd);
|
||||||
|
|
||||||
LLSD asLLSD() const;
|
LLSD asLLSD() const;
|
||||||
operator LLSD() const { return asLLSD(); }
|
operator LLSD() const { return asLLSD(); }
|
||||||
bool fromLLSD(LLSD& sd);
|
bool fromLLSD(LLSD& sd);
|
||||||
@@ -637,7 +654,10 @@ public:
|
|||||||
const F32& getSkew() const { return mPathParams.getSkew(); }
|
const F32& getSkew() const { return mPathParams.getSkew(); }
|
||||||
const LLUUID& getSculptID() const { return mSculptID; }
|
const LLUUID& getSculptID() const { return mSculptID; }
|
||||||
const U8& getSculptType() const { return mSculptType; }
|
const U8& getSculptType() const { return mSculptType; }
|
||||||
|
bool isSculpt() const;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
bool isMeshSculpt() const;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
BOOL isConvex() const;
|
BOOL isConvex() const;
|
||||||
|
|
||||||
// 'begin' and 'end' should be in range [0, 1] (they will be clamped)
|
// 'begin' and 'end' should be in range [0, 1] (they will be clamped)
|
||||||
@@ -686,6 +706,9 @@ public:
|
|||||||
BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); }
|
BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); }
|
||||||
BOOL isOpen() const { return mOpen; }
|
BOOL isOpen() const { return mOpen; }
|
||||||
void setDirty() { mDirty = TRUE; }
|
void setDirty() { mDirty = TRUE; }
|
||||||
|
|
||||||
|
static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
|
||||||
|
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
|
||||||
BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
|
BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0,
|
||||||
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
|
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
|
||||||
BOOL isConcave() const { return mConcave; }
|
BOOL isConcave() const { return mConcave; }
|
||||||
@@ -710,6 +733,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void genNormals(const LLProfileParams& params);
|
void genNormals(const LLProfileParams& params);
|
||||||
|
static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
|
||||||
void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
|
void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
|
||||||
|
|
||||||
Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
|
Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0);
|
||||||
@@ -752,6 +776,9 @@ public:
|
|||||||
|
|
||||||
virtual ~LLPath();
|
virtual ~LLPath();
|
||||||
|
|
||||||
|
static S32 getNumPoints(const LLPathParams& params, F32 detail);
|
||||||
|
static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
|
||||||
|
|
||||||
void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
|
void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f);
|
||||||
virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
|
virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0,
|
||||||
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
|
BOOL is_sculpted = FALSE, S32 sculpt_size = 0);
|
||||||
@@ -790,20 +817,87 @@ class LLVolumeFace
|
|||||||
public:
|
public:
|
||||||
class VertexData
|
class VertexData
|
||||||
{
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
POSITION = 0,
|
||||||
|
NORMAL = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
public:
|
public:
|
||||||
LLVector3 mPosition;
|
VertexData();
|
||||||
LLVector3 mNormal;
|
VertexData(const VertexData& rhs);
|
||||||
LLVector3 mBinormal;
|
const VertexData& operator=(const VertexData& rhs);
|
||||||
|
|
||||||
|
~VertexData();
|
||||||
|
LLVector4a& getPosition();
|
||||||
|
LLVector4a& getNormal();
|
||||||
|
const LLVector4a& getPosition() const;
|
||||||
|
const LLVector4a& getNormal() const;
|
||||||
|
void setPosition(const LLVector4a& pos);
|
||||||
|
void setNormal(const LLVector4a& norm);
|
||||||
|
|
||||||
|
|
||||||
LLVector2 mTexCoord;
|
LLVector2 mTexCoord;
|
||||||
|
|
||||||
|
bool operator<(const VertexData& rhs) const;
|
||||||
|
bool operator==(const VertexData& rhs) const;
|
||||||
|
bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
LLVector4a* mData;
|
||||||
};
|
};
|
||||||
|
|
||||||
LLVolumeFace();
|
LLVolumeFace();
|
||||||
LLVolumeFace(const LLVolumeFace& src);
|
LLVolumeFace(const LLVolumeFace& src);
|
||||||
LLVolumeFace& operator=(const LLVolumeFace& rhs);
|
LLVolumeFace& operator=(const LLVolumeFace& rhs);
|
||||||
|
|
||||||
~LLVolumeFace();
|
~LLVolumeFace();
|
||||||
|
private:
|
||||||
|
void freeData();
|
||||||
|
public:
|
||||||
|
|
||||||
BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
|
BOOL create(LLVolume* volume, BOOL partial_build = FALSE);
|
||||||
void createBinormals();
|
void createBinormals();
|
||||||
|
|
||||||
|
void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform);
|
||||||
|
|
||||||
|
void resizeVertices(S32 num_verts);
|
||||||
|
void allocateBinormals(S32 num_verts);
|
||||||
|
#if MESH_ENABLED
|
||||||
|
void allocateWeights(S32 num_verts);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
void resizeIndices(S32 num_indices);
|
||||||
|
void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
|
||||||
|
|
||||||
|
void pushVertex(const VertexData& cv);
|
||||||
|
void pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc);
|
||||||
|
void pushIndex(const U16& idx);
|
||||||
|
|
||||||
|
void swapData(LLVolumeFace& rhs);
|
||||||
|
|
||||||
|
void getVertexData(U16 indx, LLVolumeFace::VertexData& cv);
|
||||||
|
|
||||||
|
class VertexMapData : public LLVolumeFace::VertexData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
U16 mIndex;
|
||||||
|
|
||||||
|
bool operator==(const LLVolumeFace::VertexData& rhs) const;
|
||||||
|
|
||||||
|
struct ComparePosition
|
||||||
|
{
|
||||||
|
bool operator()(const LLVector3& a, const LLVector3& b) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
void optimize(F32 angle_cutoff = 2.f);
|
||||||
|
void cacheOptimize();
|
||||||
|
|
||||||
|
void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@@ -823,7 +917,6 @@ public:
|
|||||||
public:
|
public:
|
||||||
S32 mID;
|
S32 mID;
|
||||||
U32 mTypeMask;
|
U32 mTypeMask;
|
||||||
BOOL mHasBinormals;
|
|
||||||
|
|
||||||
// Only used for INNER/OUTER faces
|
// Only used for INNER/OUTER faces
|
||||||
S32 mBeginS;
|
S32 mBeginS;
|
||||||
@@ -835,10 +928,26 @@ public:
|
|||||||
LLVector4a* mCenter;
|
LLVector4a* mCenter;
|
||||||
LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.
|
LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.
|
||||||
|
|
||||||
std::vector<VertexData> mVertices;
|
S32 mNumVertices;
|
||||||
std::vector<U16> mIndices;
|
S32 mNumIndices;
|
||||||
|
|
||||||
|
LLVector4a* mPositions;
|
||||||
|
LLVector4a* mNormals;
|
||||||
|
LLVector4a* mBinormals;
|
||||||
|
LLVector2* mTexCoords;
|
||||||
|
U16* mIndices;
|
||||||
|
|
||||||
std::vector<S32> mEdge;
|
std::vector<S32> mEdge;
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
//list of skin weights for rigged volumes
|
||||||
|
// format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight>
|
||||||
|
// mWeights.size() should be empty or match mVertices.size()
|
||||||
|
LLVector4a* mWeights;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
|
LLOctreeNode<LLVolumeTriangle>* mOctree;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
|
BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
|
||||||
BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
|
BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
|
||||||
@@ -849,7 +958,12 @@ class LLVolume : public LLRefCount
|
|||||||
{
|
{
|
||||||
friend class LLVolumeLODGroup;
|
friend class LLVolumeLODGroup;
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
protected:
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
#if !MESH_ENABLED
|
||||||
private:
|
private:
|
||||||
|
#endif //!MESH_ENABLED
|
||||||
LLVolume(const LLVolume&); // Don't implement
|
LLVolume(const LLVolume&); // Don't implement
|
||||||
~LLVolume(); // use unref
|
~LLVolume(); // use unref
|
||||||
|
|
||||||
@@ -872,7 +986,7 @@ public:
|
|||||||
|
|
||||||
U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); }
|
U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); }
|
||||||
U8 getPathType() const { return mParams.getPathParams().getCurveType(); }
|
U8 getPathType() const { return mParams.getPathParams().getCurveType(); }
|
||||||
S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); }
|
S32 getNumFaces() const;
|
||||||
S32 getNumVolumeFaces() const { return mVolumeFaces.size(); }
|
S32 getNumVolumeFaces() const { return mVolumeFaces.size(); }
|
||||||
F32 getDetail() const { return mDetail; }
|
F32 getDetail() const { return mDetail; }
|
||||||
const LLVolumeParams& getParams() const { return mParams; }
|
const LLVolumeParams& getParams() const { return mParams; }
|
||||||
@@ -900,10 +1014,12 @@ public:
|
|||||||
|
|
||||||
// returns number of triangle indeces required for path/profile mesh
|
// returns number of triangle indeces required for path/profile mesh
|
||||||
S32 getNumTriangleIndices() const;
|
S32 getNumTriangleIndices() const;
|
||||||
|
static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
|
||||||
|
|
||||||
|
S32 getNumTriangles() const;
|
||||||
|
|
||||||
void generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
void generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
||||||
std::vector<LLVector3> &normals,
|
std::vector<LLVector3> &normals,
|
||||||
std::vector<S32> &segments,
|
|
||||||
const LLVector3& view_vec,
|
const LLVector3& view_vec,
|
||||||
const LLMatrix4& mat,
|
const LLMatrix4& mat,
|
||||||
const LLMatrix3& norm_mat,
|
const LLMatrix3& norm_mat,
|
||||||
@@ -952,6 +1068,9 @@ public:
|
|||||||
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 cacheOptimize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
|
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
|
||||||
F32 sculptGetSurfaceArea();
|
F32 sculptGetSurfaceArea();
|
||||||
@@ -962,11 +1081,20 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
BOOL generate();
|
BOOL generate();
|
||||||
void createVolumeFaces();
|
void createVolumeFaces();
|
||||||
|
#if MESH_ENABLED
|
||||||
|
public:
|
||||||
|
virtual bool unpackVolumeFaces(std::istream& is, S32 size);
|
||||||
|
|
||||||
|
virtual void makeTetrahedron();
|
||||||
|
virtual BOOL isTetrahedron();
|
||||||
|
#endif //MESH_ENABLED
|
||||||
protected:
|
protected:
|
||||||
BOOL mUnique;
|
BOOL mUnique;
|
||||||
F32 mDetail;
|
F32 mDetail;
|
||||||
S32 mSculptLevel;
|
S32 mSculptLevel;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
BOOL mIsTetrahedron;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
LLVolumeParams mParams;
|
LLVolumeParams mParams;
|
||||||
LLPath *mPathp;
|
LLPath *mPathp;
|
||||||
@@ -976,16 +1104,25 @@ protected:
|
|||||||
BOOL mGenerateSingleFace;
|
BOOL mGenerateSingleFace;
|
||||||
typedef std::vector<LLVolumeFace> face_list_t;
|
typedef std::vector<LLVolumeFace> face_list_t;
|
||||||
face_list_t mVolumeFaces;
|
face_list_t mVolumeFaces;
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
public:
|
||||||
|
LLVector4a* mHullPoints;
|
||||||
|
U16* mHullIndices;
|
||||||
|
S32 mNumHullPoints;
|
||||||
|
S32 mNumHullIndices;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
|
std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params);
|
||||||
|
|
||||||
LLVector3 calc_binormal_from_triangle(
|
void calc_binormal_from_triangle(
|
||||||
const LLVector3& pos0,
|
LLVector4a& binormal,
|
||||||
|
const LLVector4a& pos0,
|
||||||
const LLVector2& tex0,
|
const LLVector2& tex0,
|
||||||
const LLVector3& pos1,
|
const LLVector4a& pos1,
|
||||||
const LLVector2& tex1,
|
const LLVector2& tex1,
|
||||||
const LLVector3& pos2,
|
const LLVector4a& pos2,
|
||||||
const LLVector2& tex2);
|
const LLVector2& tex2);
|
||||||
|
|
||||||
BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);
|
BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size);
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ void LLVolumeMgr::unrefVolume(LLVolume *volumep)
|
|||||||
volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
|
volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
|
||||||
if( iter == mVolumeLODGroups.end() )
|
if( iter == mVolumeLODGroups.end() )
|
||||||
{
|
{
|
||||||
llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
|
llwarns << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
|
||||||
if (mDataMutex)
|
if (mDataMutex)
|
||||||
{
|
{
|
||||||
mDataMutex->unlock();
|
mDataMutex->unlock();
|
||||||
|
|||||||
@@ -74,8 +74,6 @@ BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, c
|
|||||||
return (grt & 0x7) ? false : true;
|
return (grt & 0x7) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0 //MESH
|
|
||||||
LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node)
|
LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode<LLVolumeTriangle>* node)
|
||||||
{
|
{
|
||||||
node->addListener(this);
|
node->addListener(this);
|
||||||
@@ -122,7 +120,7 @@ void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode<LLVolumeTriangle>
|
|||||||
if (LLLineSegmentBoxIntersect(mStart.getF32ptr(), mEnd.getF32ptr(), vl->mBounds[0].getF32ptr(), vl->mBounds[1].getF32ptr()))
|
if (LLLineSegmentBoxIntersect(mStart.getF32ptr(), mEnd.getF32ptr(), vl->mBounds[0].getF32ptr(), vl->mBounds[1].getF32ptr()))
|
||||||
{
|
{
|
||||||
node->accept(this);
|
node->accept(this);
|
||||||
for (S32 i = 0; i < node->getChildCount(); ++i)
|
for (U32 i = 0; i < node->getChildCount(); ++i)
|
||||||
{
|
{
|
||||||
traverse(node->getChild(i));
|
traverse(node->getChild(i));
|
||||||
}
|
}
|
||||||
@@ -253,5 +251,5 @@ void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
#include "llvolume.h"
|
#include "llvolume.h"
|
||||||
#include "llvector4a.h"
|
#include "llvector4a.h"
|
||||||
|
|
||||||
#if 0 //MESH
|
|
||||||
class LLVolumeTriangle : public LLRefCount
|
class LLVolumeTriangle : public LLRefCount
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -131,5 +130,5 @@ class LLVolumeOctreeValidate : public LLOctreeTraveler<LLVolumeTriangle>
|
|||||||
{
|
{
|
||||||
virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch);
|
virtual void visit(const LLOctreeNode<LLVolumeTriangle>* branch);
|
||||||
};
|
};
|
||||||
#endif //0
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -39,6 +39,9 @@
|
|||||||
const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f
|
const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f
|
||||||
const F32 MIN_OBJECT_Z = -256.f;
|
const F32 MIN_OBJECT_Z = -256.f;
|
||||||
const F32 DEFAULT_MAX_PRIM_SCALE = 256.f;
|
const F32 DEFAULT_MAX_PRIM_SCALE = 256.f;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = DEFAULT_MAX_PRIM_SCALE;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
const F32 MIN_PRIM_SCALE = 0.01f;
|
const F32 MIN_PRIM_SCALE = 0.01f;
|
||||||
const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX
|
const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX
|
||||||
|
|
||||||
|
|||||||
@@ -620,11 +620,18 @@ void LLCurl::Easy::prepRequest(const std::string& url,
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class LLCurl::Multi
|
class LLCurl::Multi : public LLThread
|
||||||
{
|
{
|
||||||
LOG_CLASS(Multi);
|
LOG_CLASS(Multi);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PERFORM_STATE_READY=0,
|
||||||
|
PERFORM_STATE_PERFORMING=1,
|
||||||
|
PERFORM_STATE_COMPLETED=2
|
||||||
|
} ePerformState;
|
||||||
|
|
||||||
Multi();
|
Multi();
|
||||||
~Multi();
|
~Multi();
|
||||||
|
|
||||||
@@ -634,13 +641,20 @@ public:
|
|||||||
void removeEasy(Easy* easy);
|
void removeEasy(Easy* easy);
|
||||||
|
|
||||||
S32 process();
|
S32 process();
|
||||||
S32 perform();
|
void perform();
|
||||||
|
|
||||||
|
virtual void run();
|
||||||
|
|
||||||
CURLMsg* info_read(S32* msgs_in_queue);
|
CURLMsg* info_read(S32* msgs_in_queue);
|
||||||
|
|
||||||
S32 mQueued;
|
S32 mQueued;
|
||||||
S32 mErrorCount;
|
S32 mErrorCount;
|
||||||
|
|
||||||
|
S32 mPerformState;
|
||||||
|
|
||||||
|
LLCondition* mSignal;
|
||||||
|
bool mQuitting;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void easyFree(Easy*);
|
void easyFree(Easy*);
|
||||||
|
|
||||||
@@ -655,21 +669,32 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
LLCurl::Multi::Multi()
|
LLCurl::Multi::Multi()
|
||||||
: mQueued(0),
|
: LLThread("Curl Multi"),
|
||||||
mErrorCount(0)
|
mQueued(0),
|
||||||
|
mErrorCount(0),
|
||||||
|
mPerformState(PERFORM_STATE_READY)
|
||||||
{
|
{
|
||||||
|
mQuitting = false;
|
||||||
|
mSignal = new LLCondition;
|
||||||
|
|
||||||
mCurlMultiHandle = curl_multi_init();
|
mCurlMultiHandle = curl_multi_init();
|
||||||
if (!mCurlMultiHandle)
|
if (!mCurlMultiHandle)
|
||||||
{
|
{
|
||||||
llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
|
llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
|
||||||
mCurlMultiHandle = curl_multi_init();
|
mCurlMultiHandle = curl_multi_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
llassert_always(mCurlMultiHandle);
|
llassert_always(mCurlMultiHandle);
|
||||||
++gCurlMultiCount;
|
++gCurlMultiCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLCurl::Multi::~Multi()
|
LLCurl::Multi::~Multi()
|
||||||
{
|
{
|
||||||
|
llassert(isStopped());
|
||||||
|
|
||||||
|
delete mSignal;
|
||||||
|
mSignal = NULL;
|
||||||
|
|
||||||
// Clean up active
|
// Clean up active
|
||||||
for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
|
for(easy_active_list_t::iterator iter = mEasyActiveList.begin();
|
||||||
iter != mEasyActiveList.end(); ++iter)
|
iter != mEasyActiveList.end(); ++iter)
|
||||||
@@ -695,30 +720,50 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue)
|
|||||||
return curlmsg;
|
return curlmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLCurl::Multi::perform()
|
||||||
S32 LLCurl::Multi::perform()
|
|
||||||
{
|
{
|
||||||
S32 q = 0;
|
if (mPerformState == PERFORM_STATE_READY)
|
||||||
for (S32 call_count = 0;
|
|
||||||
call_count < MULTI_PERFORM_CALL_REPEAT;
|
|
||||||
call_count += 1)
|
|
||||||
{
|
{
|
||||||
CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
|
mSignal->signal();
|
||||||
if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
|
}
|
||||||
{
|
}
|
||||||
check_curl_multi_code(code);
|
|
||||||
break;
|
void LLCurl::Multi::run()
|
||||||
}
|
{
|
||||||
|
while (!mQuitting)
|
||||||
|
{
|
||||||
|
mSignal->wait();
|
||||||
|
mPerformState = PERFORM_STATE_PERFORMING;
|
||||||
|
if (!mQuitting)
|
||||||
|
{
|
||||||
|
S32 q = 0;
|
||||||
|
for (S32 call_count = 0;
|
||||||
|
call_count < MULTI_PERFORM_CALL_REPEAT;
|
||||||
|
call_count += 1)
|
||||||
|
{
|
||||||
|
CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q);
|
||||||
|
if (CURLM_CALL_MULTI_PERFORM != code || q == 0)
|
||||||
|
{
|
||||||
|
check_curl_multi_code(code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
mQueued = q;
|
||||||
|
mPerformState = PERFORM_STATE_COMPLETED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mQueued = q;
|
|
||||||
return q;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
S32 LLCurl::Multi::process()
|
S32 LLCurl::Multi::process()
|
||||||
{
|
{
|
||||||
perform();
|
perform();
|
||||||
|
|
||||||
|
if (mPerformState != PERFORM_STATE_COMPLETED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
CURLMsg* msg;
|
CURLMsg* msg;
|
||||||
int msgs_in_queue;
|
int msgs_in_queue;
|
||||||
|
|
||||||
@@ -749,6 +794,8 @@ S32 LLCurl::Multi::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mPerformState = PERFORM_STATE_READY;
|
||||||
return processed;
|
return processed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -827,6 +874,18 @@ LLCurlRequest::LLCurlRequest() :
|
|||||||
LLCurlRequest::~LLCurlRequest()
|
LLCurlRequest::~LLCurlRequest()
|
||||||
{
|
{
|
||||||
llassert_always(mThreadID == LLThread::currentID());
|
llassert_always(mThreadID == LLThread::currentID());
|
||||||
|
|
||||||
|
//stop all Multi handle background threads
|
||||||
|
for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter)
|
||||||
|
{
|
||||||
|
LLCurl::Multi* multi = *iter;
|
||||||
|
multi->mQuitting = true;
|
||||||
|
while (!multi->isStopped())
|
||||||
|
{
|
||||||
|
multi->mSignal->signal();
|
||||||
|
apr_sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
|
for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -834,6 +893,7 @@ void LLCurlRequest::addMulti()
|
|||||||
{
|
{
|
||||||
llassert_always(mThreadID == LLThread::currentID());
|
llassert_always(mThreadID == LLThread::currentID());
|
||||||
LLCurl::Multi* multi = new LLCurl::Multi();
|
LLCurl::Multi* multi = new LLCurl::Multi();
|
||||||
|
multi->start();
|
||||||
mMultiSet.insert(multi);
|
mMultiSet.insert(multi);
|
||||||
mActiveMulti = multi;
|
mActiveMulti = multi;
|
||||||
mActiveRequestCount = 0;
|
mActiveRequestCount = 0;
|
||||||
@@ -963,6 +1023,13 @@ S32 LLCurlRequest::process()
|
|||||||
if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
|
if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0)
|
||||||
{
|
{
|
||||||
mMultiSet.erase(curiter);
|
mMultiSet.erase(curiter);
|
||||||
|
multi->mQuitting = true;
|
||||||
|
while (!multi->isStopped())
|
||||||
|
{
|
||||||
|
multi->mSignal->signal();
|
||||||
|
apr_sleep(1000);
|
||||||
|
}
|
||||||
|
|
||||||
delete multi;
|
delete multi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -993,6 +1060,7 @@ LLCurlEasyRequest::LLCurlEasyRequest()
|
|||||||
mResultReturned(false)
|
mResultReturned(false)
|
||||||
{
|
{
|
||||||
mMulti = new LLCurl::Multi();
|
mMulti = new LLCurl::Multi();
|
||||||
|
mMulti->start();
|
||||||
mEasy = mMulti->allocEasy();
|
mEasy = mMulti->allocEasy();
|
||||||
if (mEasy)
|
if (mEasy)
|
||||||
{
|
{
|
||||||
@@ -1003,6 +1071,12 @@ LLCurlEasyRequest::LLCurlEasyRequest()
|
|||||||
|
|
||||||
LLCurlEasyRequest::~LLCurlEasyRequest()
|
LLCurlEasyRequest::~LLCurlEasyRequest()
|
||||||
{
|
{
|
||||||
|
mMulti->mQuitting = true;
|
||||||
|
while (!mMulti->isStopped())
|
||||||
|
{
|
||||||
|
mMulti->mSignal->signal();
|
||||||
|
apr_sleep(1000);
|
||||||
|
}
|
||||||
delete mMulti;
|
delete mMulti;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,14 +1173,20 @@ void LLCurlEasyRequest::requestComplete()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
S32 LLCurlEasyRequest::perform()
|
void LLCurlEasyRequest::perform()
|
||||||
{
|
{
|
||||||
return mMulti->perform();
|
mMulti->perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usage: Call getRestult until it returns false (no more messages)
|
// Usage: Call getRestult until it returns false (no more messages)
|
||||||
bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info)
|
bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info)
|
||||||
{
|
{
|
||||||
|
if (mMulti->mPerformState != LLCurl::Multi::PERFORM_STATE_COMPLETED)
|
||||||
|
{ //we're busy, try again later
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mMulti->mPerformState = LLCurl::Multi::PERFORM_STATE_READY;
|
||||||
|
|
||||||
if (!mEasy)
|
if (!mEasy)
|
||||||
{
|
{
|
||||||
// Special case - we failed to initialize a curl_easy (can happen if too many open files)
|
// Special case - we failed to initialize a curl_easy (can happen if too many open files)
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ public:
|
|||||||
void slist_append(const char* str);
|
void slist_append(const char* str);
|
||||||
void sendRequest(const std::string& url);
|
void sendRequest(const std::string& url);
|
||||||
void requestComplete();
|
void requestComplete();
|
||||||
S32 perform();
|
void perform();
|
||||||
bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL);
|
bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL);
|
||||||
std::string getErrorString();
|
std::string getErrorString();
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ include_directories(
|
|||||||
|
|
||||||
set(llprimitive_SOURCE_FILES
|
set(llprimitive_SOURCE_FILES
|
||||||
llmaterialtable.cpp
|
llmaterialtable.cpp
|
||||||
|
llmodel.cpp
|
||||||
llprimitive.cpp
|
llprimitive.cpp
|
||||||
llprimtexturelist.cpp
|
llprimtexturelist.cpp
|
||||||
lltextureanim.cpp
|
lltextureanim.cpp
|
||||||
@@ -32,6 +33,7 @@ set(llprimitive_HEADER_FILES
|
|||||||
|
|
||||||
legacy_object_types.h
|
legacy_object_types.h
|
||||||
llmaterialtable.h
|
llmaterialtable.h
|
||||||
|
llmodel.h
|
||||||
llprimitive.h
|
llprimitive.h
|
||||||
llprimtexturelist.h
|
llprimtexturelist.h
|
||||||
lltextureanim.h
|
lltextureanim.h
|
||||||
|
|||||||
2394
indra/llprimitive/llmodel.cpp
Normal file
2394
indra/llprimitive/llmodel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
288
indra/llprimitive/llmodel.h
Normal file
288
indra/llprimitive/llmodel.h
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
/**
|
||||||
|
* @file llmodel.h
|
||||||
|
* @brief Model handling class definitions
|
||||||
|
*
|
||||||
|
* $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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LL_LLMODEL_H
|
||||||
|
#define LL_LLMODEL_H
|
||||||
|
|
||||||
|
#include "llpointer.h"
|
||||||
|
#include "llvolume.h"
|
||||||
|
#include "v4math.h"
|
||||||
|
#include "m4math.h"
|
||||||
|
|
||||||
|
#if MESH_IMPORT
|
||||||
|
class daeElement;
|
||||||
|
class domMesh;
|
||||||
|
#endif //MESH_IMPORT
|
||||||
|
|
||||||
|
#define MAX_MODEL_FACES 8
|
||||||
|
|
||||||
|
|
||||||
|
class LLMeshSkinInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLUUID mMeshID;
|
||||||
|
std::vector<std::string> mJointNames;
|
||||||
|
std::vector<LLMatrix4> mInvBindMatrix;
|
||||||
|
std::vector<LLMatrix4> mAlternateBindMatrix;
|
||||||
|
std::map<std::string, U32> mJointMap;
|
||||||
|
|
||||||
|
LLMeshSkinInfo() { }
|
||||||
|
LLMeshSkinInfo(LLSD& data);
|
||||||
|
void fromLLSD(LLSD& data);
|
||||||
|
LLSD asLLSD(bool include_joints) const;
|
||||||
|
LLMatrix4 mBindShapeMatrix;
|
||||||
|
float mPelvisOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LLModel : public LLVolume
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
LOD_IMPOSTOR = 0,
|
||||||
|
LOD_LOW,
|
||||||
|
LOD_MEDIUM,
|
||||||
|
LOD_HIGH,
|
||||||
|
LOD_PHYSICS,
|
||||||
|
NUM_LODS
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EModelStatus
|
||||||
|
{
|
||||||
|
NO_ERRORS = 0,
|
||||||
|
VERTEX_NUMBER_OVERFLOW, //vertex number is >= 65535.
|
||||||
|
BAD_ELEMENT,
|
||||||
|
INVALID_STATUS
|
||||||
|
} ;
|
||||||
|
|
||||||
|
//convex_hull_decomposition is a vector of convex hulls
|
||||||
|
//each convex hull is a set of points
|
||||||
|
typedef std::vector<std::vector<LLVector3> > convex_hull_decomposition;
|
||||||
|
typedef std::vector<LLVector3> hull;
|
||||||
|
|
||||||
|
class PhysicsMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector<LLVector3> mPositions;
|
||||||
|
std::vector<LLVector3> mNormals;
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
mPositions.clear();
|
||||||
|
mNormals.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return mPositions.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Decomposition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Decomposition() { }
|
||||||
|
Decomposition(LLSD& data);
|
||||||
|
void fromLLSD(LLSD& data);
|
||||||
|
LLSD asLLSD() const;
|
||||||
|
bool hasHullList() const;
|
||||||
|
|
||||||
|
void merge(const Decomposition* rhs);
|
||||||
|
|
||||||
|
LLUUID mMeshID;
|
||||||
|
LLModel::convex_hull_decomposition mHull;
|
||||||
|
LLModel::hull mBaseHull;
|
||||||
|
|
||||||
|
std::vector<LLModel::PhysicsMesh> mMesh;
|
||||||
|
LLModel::PhysicsMesh mBaseHullMesh;
|
||||||
|
LLModel::PhysicsMesh mPhysicsShapeMesh;
|
||||||
|
};
|
||||||
|
|
||||||
|
LLModel(LLVolumeParams& params, F32 detail);
|
||||||
|
~LLModel();
|
||||||
|
|
||||||
|
bool loadModel(std::istream& is);
|
||||||
|
bool loadSkinInfo(LLSD& header, std::istream& is);
|
||||||
|
bool loadDecomposition(LLSD& header, std::istream& is);
|
||||||
|
|
||||||
|
static LLSD writeModel(
|
||||||
|
std::ostream& ostr,
|
||||||
|
LLModel* physics,
|
||||||
|
LLModel* high,
|
||||||
|
LLModel* medium,
|
||||||
|
LLModel* low,
|
||||||
|
LLModel* imposotr,
|
||||||
|
const LLModel::Decomposition& decomp,
|
||||||
|
BOOL upload_skin,
|
||||||
|
BOOL upload_joints,
|
||||||
|
BOOL nowrite = FALSE,
|
||||||
|
BOOL as_slm = FALSE);
|
||||||
|
|
||||||
|
static LLSD writeModelToStream(
|
||||||
|
std::ostream& ostr,
|
||||||
|
LLSD& mdl,
|
||||||
|
BOOL nowrite = FALSE, BOOL as_slm = FALSE);
|
||||||
|
|
||||||
|
#if MESH_IMPORT
|
||||||
|
static LLModel* loadModelFromDomMesh(domMesh* mesh);
|
||||||
|
static std::string getElementLabel(daeElement* element);
|
||||||
|
#endif //MESH_IMPORT
|
||||||
|
std::string getName() const;
|
||||||
|
std::string getMetric() const {return mMetric;}
|
||||||
|
EModelStatus getStatus() const {return mStatus;}
|
||||||
|
static std::string getStatusString(U32 status) ;
|
||||||
|
|
||||||
|
void appendFaces(LLModel* model, LLMatrix4& transform, LLMatrix4& normal_transform);
|
||||||
|
void appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat);
|
||||||
|
|
||||||
|
void setNumVolumeFaces(S32 count);
|
||||||
|
void setVolumeFaceData(
|
||||||
|
S32 f,
|
||||||
|
LLStrider<LLVector3> pos,
|
||||||
|
LLStrider<LLVector3> norm,
|
||||||
|
LLStrider<LLVector2> tc,
|
||||||
|
LLStrider<U16> ind,
|
||||||
|
U32 num_verts,
|
||||||
|
U32 num_indices);
|
||||||
|
|
||||||
|
void generateNormals(F32 angle_cutoff);
|
||||||
|
|
||||||
|
void addFace(const LLVolumeFace& face);
|
||||||
|
|
||||||
|
void normalizeVolumeFaces();
|
||||||
|
void optimizeVolumeFaces();
|
||||||
|
void offsetMesh( const LLVector3& pivotPoint );
|
||||||
|
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
|
||||||
|
|
||||||
|
//reorder face list based on mMaterialList in this and reference so
|
||||||
|
//order matches that of reference (material ordering touchup)
|
||||||
|
void matchMaterialOrder(LLModel* reference);
|
||||||
|
|
||||||
|
std::vector<std::string> mMaterialList;
|
||||||
|
|
||||||
|
//data used for skin weights
|
||||||
|
class JointWeight
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
S32 mJointIdx;
|
||||||
|
F32 mWeight;
|
||||||
|
|
||||||
|
JointWeight()
|
||||||
|
{
|
||||||
|
mJointIdx = 0;
|
||||||
|
mWeight = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
JointWeight(S32 idx, F32 weight)
|
||||||
|
: mJointIdx(idx), mWeight(weight)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const JointWeight& rhs) const
|
||||||
|
{
|
||||||
|
if (mWeight == rhs.mWeight)
|
||||||
|
{
|
||||||
|
return mJointIdx < rhs.mJointIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mWeight < rhs.mWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CompareWeightGreater
|
||||||
|
{
|
||||||
|
bool operator()(const JointWeight& lhs, const JointWeight& rhs)
|
||||||
|
{
|
||||||
|
return rhs < lhs; // strongest = first
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct JointPositionalCompare
|
||||||
|
{
|
||||||
|
//Are the doubles the same w/in epsilon specified tolerance
|
||||||
|
bool areEqual( double a, double b )
|
||||||
|
{
|
||||||
|
const float epsilon = 1e-5f;
|
||||||
|
return (abs((int)(a - b)) < epsilon) && (a < b);
|
||||||
|
}
|
||||||
|
//Make sure that we return false for any values that are within the tolerance for equivalence
|
||||||
|
bool operator() ( const LLVector3& a, const LLVector3& b )
|
||||||
|
{
|
||||||
|
return ( areEqual( a[0],b[0]) && areEqual( a[1],b[1] ) && areEqual( a[2],b[2]) ) ? false : true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//copy of position array for this model -- mPosition[idx].mV[X,Y,Z]
|
||||||
|
std::vector<LLVector3> mPosition;
|
||||||
|
|
||||||
|
//map of positions to skin weights --- mSkinWeights[pos].mV[0..4] == <joint_index>.<weight>
|
||||||
|
//joint_index corresponds to mJointList
|
||||||
|
typedef std::vector<JointWeight> weight_list;
|
||||||
|
typedef std::map<LLVector3, weight_list > weight_map;
|
||||||
|
weight_map mSkinWeights;
|
||||||
|
|
||||||
|
//get list of weight influences closest to given position
|
||||||
|
weight_list& getJointInfluences(const LLVector3& pos);
|
||||||
|
|
||||||
|
LLMeshSkinInfo mSkinInfo;
|
||||||
|
|
||||||
|
std::string mRequestedLabel; // name requested in UI, if any.
|
||||||
|
std::string mLabel; // name computed from dae.
|
||||||
|
|
||||||
|
std::string mMetric; // user-supplied metric data for upload
|
||||||
|
|
||||||
|
LLVector3 mNormalizedScale;
|
||||||
|
LLVector3 mNormalizedTranslation;
|
||||||
|
|
||||||
|
float mPelvisOffset;
|
||||||
|
// convex hull decomposition
|
||||||
|
S32 mDecompID;
|
||||||
|
|
||||||
|
void setConvexHullDecomposition(
|
||||||
|
const convex_hull_decomposition& decomp);
|
||||||
|
void updateHullCenters();
|
||||||
|
|
||||||
|
LLVector3 mCenterOfHullCenters;
|
||||||
|
std::vector<LLVector3> mHullCenter;
|
||||||
|
U32 mHullPoints;
|
||||||
|
|
||||||
|
//ID for storing this model in a .slm file
|
||||||
|
S32 mLocalID;
|
||||||
|
|
||||||
|
Decomposition mPhysics;
|
||||||
|
|
||||||
|
EModelStatus mStatus ;
|
||||||
|
protected:
|
||||||
|
#if MESH_IMPORT
|
||||||
|
void addVolumeFacesFromDomMesh(domMesh* mesh);
|
||||||
|
virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh);
|
||||||
|
#endif //MESH_IMPORT
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //LL_LLMODEL_H
|
||||||
@@ -109,6 +109,10 @@ public:
|
|||||||
PARAMS_LIGHT = 0x20,
|
PARAMS_LIGHT = 0x20,
|
||||||
PARAMS_SCULPT = 0x30,
|
PARAMS_SCULPT = 0x30,
|
||||||
PARAMS_LIGHT_IMAGE = 0x40,
|
PARAMS_LIGHT_IMAGE = 0x40,
|
||||||
|
#if MESH_ENABLED
|
||||||
|
PARAMS_RESERVED = 0x50, // Used on server-side
|
||||||
|
PARAMS_MESH = 0x60,
|
||||||
|
#endif MESH_ENABLED
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ LLShaderFeatures::LLShaderFeatures()
|
|||||||
: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
|
: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
|
||||||
hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false),
|
hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false),
|
||||||
hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
|
hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
|
||||||
|
#if MESH_ENABLED
|
||||||
|
, hasObjectSkinning(false)
|
||||||
|
#endif //MESH_ENABLED
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ public:
|
|||||||
bool hasWaterFog; // implies no gamma
|
bool hasWaterFog; // implies no gamma
|
||||||
bool hasTransport; // implies no lighting (it's possible to have neither though)
|
bool hasTransport; // implies no lighting (it's possible to have neither though)
|
||||||
bool hasSkinning;
|
bool hasSkinning;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
bool hasObjectSkinning;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
bool hasAtmospherics;
|
bool hasAtmospherics;
|
||||||
bool hasGamma;
|
bool hasGamma;
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ void LLTexUnit::refreshState(void)
|
|||||||
// We set dirty to true so that the tex unit knows to ignore caching
|
// We set dirty to true so that the tex unit knows to ignore caching
|
||||||
// and we reset the cached tex unit state
|
// and we reset the cached tex unit state
|
||||||
|
|
||||||
|
gGL.flush();
|
||||||
|
|
||||||
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
|
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -163,6 +165,7 @@ void LLTexUnit::activate(void)
|
|||||||
|
|
||||||
if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
|
if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
|
||||||
{
|
{
|
||||||
|
gGL.flush();
|
||||||
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
|
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
|
||||||
gGL.mCurrTextureUnitIndex = mIndex;
|
gGL.mCurrTextureUnitIndex = mIndex;
|
||||||
}
|
}
|
||||||
@@ -180,6 +183,7 @@ void LLTexUnit::enable(eTextureType type)
|
|||||||
disable(); // Force a disable of a previous texture type if it's enabled.
|
disable(); // Force a disable of a previous texture type if it's enabled.
|
||||||
}
|
}
|
||||||
mCurrTexType = type;
|
mCurrTexType = type;
|
||||||
|
gGL.flush();
|
||||||
if (mIndex < gGLManager.mNumTextureUnits)
|
if (mIndex < gGLManager.mNumTextureUnits)
|
||||||
{
|
{
|
||||||
glEnable(sGLTextureType[type]);
|
glEnable(sGLTextureType[type]);
|
||||||
@@ -195,6 +199,7 @@ void LLTexUnit::disable(void)
|
|||||||
{
|
{
|
||||||
activate();
|
activate();
|
||||||
unbind(mCurrTexType);
|
unbind(mCurrTexType);
|
||||||
|
gGL.flush();
|
||||||
if (mIndex < gGLManager.mNumTextureUnits)
|
if (mIndex < gGLManager.mNumTextureUnits)
|
||||||
{
|
{
|
||||||
glDisable(sGLTextureType[mCurrTexType]);
|
glDisable(sGLTextureType[mCurrTexType]);
|
||||||
@@ -279,6 +284,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
|
|||||||
}
|
}
|
||||||
if ((mCurrTexture != texture->getTexName()) || forceBind)
|
if ((mCurrTexture != texture->getTexName()) || forceBind)
|
||||||
{
|
{
|
||||||
|
gGL.flush();
|
||||||
activate();
|
activate();
|
||||||
enable(texture->getTarget());
|
enable(texture->getTarget());
|
||||||
mCurrTexture = texture->getTexName();
|
mCurrTexture = texture->getTexName();
|
||||||
@@ -406,6 +412,8 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
|
|||||||
{
|
{
|
||||||
if (mIndex < 0 || mCurrTexture == 0) return;
|
if (mIndex < 0 || mCurrTexture == 0) return;
|
||||||
|
|
||||||
|
gGL.flush();
|
||||||
|
|
||||||
activate();
|
activate();
|
||||||
|
|
||||||
glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]);
|
glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]);
|
||||||
@@ -420,6 +428,8 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
|
|||||||
{
|
{
|
||||||
if (mIndex < 0 || mCurrTexture == 0) return;
|
if (mIndex < 0 || mCurrTexture == 0) return;
|
||||||
|
|
||||||
|
gGL.flush();
|
||||||
|
|
||||||
if (option == TFO_POINT)
|
if (option == TFO_POINT)
|
||||||
{
|
{
|
||||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
@@ -472,6 +482,8 @@ void LLTexUnit::setTextureBlendType(eTextureBlendType type)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gGL.flush();
|
||||||
|
|
||||||
activate();
|
activate();
|
||||||
mCurrBlendType = type;
|
mCurrBlendType = type;
|
||||||
S32 scale_amount = 1;
|
S32 scale_amount = 1;
|
||||||
@@ -588,6 +600,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT
|
|||||||
if (mCurrBlendType != TB_COMBINE || gGL.mDirty)
|
if (mCurrBlendType != TB_COMBINE || gGL.mDirty)
|
||||||
{
|
{
|
||||||
mCurrBlendType = TB_COMBINE;
|
mCurrBlendType = TB_COMBINE;
|
||||||
|
gGL.flush();
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,6 +611,8 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gGL.flush();
|
||||||
|
|
||||||
// Get the gl source enums according to the eTextureBlendSrc sources passed in
|
// Get the gl source enums according to the eTextureBlendSrc sources passed in
|
||||||
GLint source1 = getTextureSource(src1);
|
GLint source1 = getTextureSource(src1);
|
||||||
GLint source2 = getTextureSource(src2);
|
GLint source2 = getTextureSource(src2);
|
||||||
@@ -730,6 +745,7 @@ void LLTexUnit::setColorScale(S32 scale)
|
|||||||
if (mCurrColorScale != scale || gGL.mDirty)
|
if (mCurrColorScale != scale || gGL.mDirty)
|
||||||
{
|
{
|
||||||
mCurrColorScale = scale;
|
mCurrColorScale = scale;
|
||||||
|
gGL.flush();
|
||||||
glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
|
glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -739,6 +755,7 @@ void LLTexUnit::setAlphaScale(S32 scale)
|
|||||||
if (mCurrAlphaScale != scale || gGL.mDirty)
|
if (mCurrAlphaScale != scale || gGL.mDirty)
|
||||||
{
|
{
|
||||||
mCurrAlphaScale = scale;
|
mCurrAlphaScale = scale;
|
||||||
|
gGL.flush();
|
||||||
glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
|
glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,6 +153,16 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
if (features->hasObjectSkinning)
|
||||||
|
{
|
||||||
|
if (!shader->attachObject("avatar/objectSkinV.glsl"))
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
// Attach Fragment Shader Features Next
|
// Attach Fragment Shader Features Next
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
#include "llglheaders.h"
|
#include "llglheaders.h"
|
||||||
#include "llmemtype.h"
|
#include "llmemtype.h"
|
||||||
#include "llrender.h"
|
#include "llrender.h"
|
||||||
|
#include "llvector4a.h"
|
||||||
#include "llcontrol.h"
|
#include "llcontrol.h"
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
@@ -88,7 +88,7 @@ void LLVBOPool::releaseName(GLuint name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
|
S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
|
||||||
{
|
{
|
||||||
sizeof(LLVector4), // TYPE_VERTEX,
|
sizeof(LLVector4), // TYPE_VERTEX,
|
||||||
sizeof(LLVector4), // TYPE_NORMAL,
|
sizeof(LLVector4), // TYPE_NORMAL,
|
||||||
@@ -488,6 +488,8 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
|
|||||||
|
|
||||||
mTypeMask = typemask;
|
mTypeMask = typemask;
|
||||||
mStride = stride;
|
mStride = stride;
|
||||||
|
mAlignedOffset = 0;
|
||||||
|
mAlignedIndexOffset = 0;
|
||||||
sCount++;
|
sCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,7 +506,7 @@ S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets)
|
|||||||
{
|
{
|
||||||
offsets[i] = stride;
|
offsets[i] = stride;
|
||||||
}
|
}
|
||||||
stride += sTypeOffsets[i];
|
stride += sTypeSize[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,7 +622,7 @@ void LLVertexBuffer::createGLBuffer()
|
|||||||
{
|
{
|
||||||
static int gl_buffer_idx = 0;
|
static int gl_buffer_idx = 0;
|
||||||
mGLBuffer = ++gl_buffer_idx;
|
mGLBuffer = ++gl_buffer_idx;
|
||||||
mMappedData = new U8[size];
|
mMappedData = (U8*) ll_aligned_malloc_16(size);
|
||||||
if(!sOmitBlank) memset((void*)mMappedData, 0, size);
|
if(!sOmitBlank) memset((void*)mMappedData, 0, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,15 +644,20 @@ void LLVertexBuffer::createGLIndices()
|
|||||||
|
|
||||||
mEmpty = TRUE;
|
mEmpty = TRUE;
|
||||||
|
|
||||||
|
//pad by 16 bytes for aligned copies
|
||||||
|
size += 16;
|
||||||
|
|
||||||
if (useVBOs())
|
if (useVBOs())
|
||||||
{
|
{
|
||||||
|
//pad by another 16 bytes for VBO pointer adjustment
|
||||||
|
size += 16;
|
||||||
mMappedIndexData = NULL;
|
mMappedIndexData = NULL;
|
||||||
genIndices();
|
genIndices();
|
||||||
mResized = TRUE;
|
mResized = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mMappedIndexData = new U8[size];
|
mMappedIndexData = (U8*) ll_aligned_malloc_16(size);
|
||||||
if(!sOmitBlank) memset((void*)mMappedIndexData, 0, size);
|
if(!sOmitBlank) memset((void*)mMappedIndexData, 0, size);
|
||||||
static int gl_buffer_idx = 0;
|
static int gl_buffer_idx = 0;
|
||||||
mGLIndices = ++gl_buffer_idx;
|
mGLIndices = ++gl_buffer_idx;
|
||||||
@@ -674,7 +681,7 @@ void LLVertexBuffer::destroyGLBuffer()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete [] mMappedData;
|
ll_aligned_free_16((void*)mMappedData);
|
||||||
mMappedData = NULL;
|
mMappedData = NULL;
|
||||||
mEmpty = TRUE;
|
mEmpty = TRUE;
|
||||||
}
|
}
|
||||||
@@ -683,7 +690,7 @@ void LLVertexBuffer::destroyGLBuffer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mGLBuffer = 0;
|
mGLBuffer = 0;
|
||||||
unbind();
|
//unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLVertexBuffer::destroyGLIndices()
|
void LLVertexBuffer::destroyGLIndices()
|
||||||
@@ -703,7 +710,7 @@ void LLVertexBuffer::destroyGLIndices()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
delete [] mMappedIndexData;
|
ll_aligned_free_16((void*)mMappedIndexData);
|
||||||
mMappedIndexData = NULL;
|
mMappedIndexData = NULL;
|
||||||
mEmpty = TRUE;
|
mEmpty = TRUE;
|
||||||
}
|
}
|
||||||
@@ -712,7 +719,7 @@ void LLVertexBuffer::destroyGLIndices()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mGLIndices = 0;
|
mGLIndices = 0;
|
||||||
unbind();
|
//unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLVertexBuffer::updateNumVerts(S32 nverts)
|
void LLVertexBuffer::updateNumVerts(S32 nverts)
|
||||||
@@ -779,6 +786,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
|
|||||||
{
|
{
|
||||||
llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl;
|
llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNumVerts(nverts);
|
updateNumVerts(nverts);
|
||||||
updateNumIndices(nindices);
|
updateNumIndices(nindices);
|
||||||
|
|
||||||
@@ -840,7 +848,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
|
|||||||
if (!useVBOs())
|
if (!useVBOs())
|
||||||
{
|
{
|
||||||
volatile U8* old = mMappedData;
|
volatile U8* old = mMappedData;
|
||||||
mMappedData = new U8[newsize];
|
mMappedData = (U8*) ll_aligned_malloc_16(newsize);
|
||||||
if (old)
|
if (old)
|
||||||
{
|
{
|
||||||
memcpy((void*)mMappedData, (void*)old, llmin(newsize, oldsize));
|
memcpy((void*)mMappedData, (void*)old, llmin(newsize, oldsize));
|
||||||
@@ -849,7 +857,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
|
|||||||
memset((void*)(mMappedData+oldsize), 0, newsize-oldsize);
|
memset((void*)(mMappedData+oldsize), 0, newsize-oldsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] old;
|
ll_aligned_free_16((void*)old);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -877,7 +885,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
|
|||||||
{
|
{
|
||||||
//delete old buffer, keep GL buffer for now
|
//delete old buffer, keep GL buffer for now
|
||||||
volatile U8* old = mMappedIndexData;
|
volatile U8* old = mMappedIndexData;
|
||||||
mMappedIndexData = new U8[new_index_size];
|
mMappedIndexData = (U8*) ll_aligned_malloc_16(new_index_size);
|
||||||
|
|
||||||
if (old)
|
if (old)
|
||||||
{
|
{
|
||||||
@@ -886,7 +894,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
|
|||||||
{
|
{
|
||||||
memset((void*)(mMappedIndexData+old_index_size), 0, new_index_size - old_index_size);
|
memset((void*)(mMappedIndexData+old_index_size), 0, new_index_size - old_index_size);
|
||||||
}
|
}
|
||||||
delete [] old;
|
ll_aligned_free_16((void*)old);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -924,8 +932,8 @@ void LLVertexBuffer::freeClientBuffer()
|
|||||||
{
|
{
|
||||||
if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData))
|
if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData))
|
||||||
{
|
{
|
||||||
delete[] mMappedData ;
|
ll_aligned_free_16((void*)mMappedData) ;
|
||||||
delete[] mMappedIndexData ;
|
ll_aligned_free_16((void*)mMappedIndexData) ;
|
||||||
mMappedData = NULL ;
|
mMappedData = NULL ;
|
||||||
mMappedIndexData = NULL ;
|
mMappedIndexData = NULL ;
|
||||||
}
|
}
|
||||||
@@ -935,9 +943,8 @@ void LLVertexBuffer::allocateClientVertexBuffer()
|
|||||||
{
|
{
|
||||||
if(!mMappedData)
|
if(!mMappedData)
|
||||||
{
|
{
|
||||||
U32 size = getSize() ;
|
mMappedData = (U8*)ll_aligned_malloc_16(getSize());
|
||||||
mMappedData = new U8[size];
|
if (!sOmitBlank) memset((void*)mMappedData, 0, getSize());
|
||||||
memset((void*)mMappedData, 0, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -945,9 +952,8 @@ void LLVertexBuffer::allocateClientIndexBuffer()
|
|||||||
{
|
{
|
||||||
if(!mMappedIndexData)
|
if(!mMappedIndexData)
|
||||||
{
|
{
|
||||||
U32 size = getIndicesSize();
|
mMappedIndexData = (U8*)ll_aligned_malloc_16(getIndicesSize());
|
||||||
mMappedIndexData = new U8[size];
|
if (!sOmitBlank) memset((void*)mMappedIndexData, 0, getIndicesSize());
|
||||||
memset((void*)mMappedIndexData, 0, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -977,7 +983,12 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
U8* src = NULL;
|
||||||
|
{
|
||||||
|
src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||||
|
}
|
||||||
|
mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
|
||||||
|
mAlignedOffset = mMappedData - src;
|
||||||
}
|
}
|
||||||
stop_glerror();
|
stop_glerror();
|
||||||
}
|
}
|
||||||
@@ -1049,7 +1060,13 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 access)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
U8* src = NULL;
|
||||||
|
{
|
||||||
|
src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
|
mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
|
||||||
|
mAlignedIndexOffset = mMappedIndexData - src;
|
||||||
stop_glerror();
|
stop_glerror();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1165,29 +1182,30 @@ template <class T,S32 type> struct VertexBufferStrider
|
|||||||
{
|
{
|
||||||
if (type == LLVertexBuffer::TYPE_INDEX)
|
if (type == LLVertexBuffer::TYPE_INDEX)
|
||||||
{
|
{
|
||||||
S32 stride = sizeof(T);
|
volatile U8* ptr = vbo.mapIndexBuffer();
|
||||||
|
|
||||||
if (vbo.mapIndexBuffer() == NULL)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
llwarns << "mapIndexBuffer failed!" << llendl;
|
llwarns << "mapIndexBuffer failed!" << llendl;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
strider = (T*)(vbo.getMappedIndices() + index*stride);
|
strider = (T*)(ptr + index*sizeof(T));
|
||||||
strider.setStride(0);
|
strider.setStride(0);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (vbo.hasDataType(type))
|
else if (vbo.hasDataType(type))
|
||||||
{
|
{
|
||||||
S32 stride = vbo.getStride();
|
S32 stride = vbo.getStride();
|
||||||
|
volatile U8* ptr = vbo.mapVertexBuffer(type);
|
||||||
|
|
||||||
if (vbo.mapVertexBuffer(type) == NULL)
|
if (ptr == NULL)
|
||||||
{
|
{
|
||||||
llwarns << "mapVertexBuffer failed!" << llendl;
|
llwarns << "mapVertexBuffer failed!" << llendl;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride);
|
strider = (T*)(ptr + vbo.getOffset(type) + index*stride);
|
||||||
strider.setStride(stride);
|
strider.setStride(stride);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1259,7 +1277,7 @@ void LLVertexBuffer::setStride(S32 type, S32 new_stride)
|
|||||||
llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl;
|
llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl;
|
||||||
}
|
}
|
||||||
// This code assumes that setStride() will only be called once per VBO per type.
|
// This code assumes that setStride() will only be called once per VBO per type.
|
||||||
S32 delta = new_stride - sTypeOffsets[type];
|
S32 delta = new_stride - sTypeSize[type];
|
||||||
for (S32 i=type+1; i<TYPE_MAX; i++)
|
for (S32 i=type+1; i<TYPE_MAX; i++)
|
||||||
{
|
{
|
||||||
if (mTypeMask & (1<<i))
|
if (mTypeMask & (1<<i))
|
||||||
@@ -1466,7 +1484,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
|
|||||||
{
|
{
|
||||||
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
|
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
|
||||||
stop_glerror();
|
stop_glerror();
|
||||||
volatile U8* base = useVBOs() ? NULL : mMappedData;
|
volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
|
||||||
S32 stride = mStride;
|
S32 stride = mStride;
|
||||||
|
|
||||||
if ((data_mask & mTypeMask) != data_mask)
|
if ((data_mask & mTypeMask) != data_mask)
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ public:
|
|||||||
llerrs << "Illegal operation!" << llendl;
|
llerrs << "Illegal operation!" << llendl;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVBOPool sStreamVBOPool;
|
static LLVBOPool sStreamVBOPool;
|
||||||
static LLVBOPool sDynamicVBOPool;
|
static LLVBOPool sDynamicVBOPool;
|
||||||
static LLVBOPool sStreamIBOPool;
|
static LLVBOPool sStreamIBOPool;
|
||||||
@@ -96,6 +97,7 @@ public:
|
|||||||
static void cleanupClass();
|
static void cleanupClass();
|
||||||
static void setupClientArrays(U32 data_mask);
|
static void setupClientArrays(U32 data_mask);
|
||||||
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);
|
static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);
|
||||||
|
|
||||||
static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
|
static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
|
||||||
static void unbind(); //unbind any bound vertex buffer
|
static void unbind(); //unbind any bound vertex buffer
|
||||||
|
|
||||||
@@ -197,8 +199,8 @@ public:
|
|||||||
S32 getRequestedVerts() const { return mRequestedNumVerts; }
|
S32 getRequestedVerts() const { return mRequestedNumVerts; }
|
||||||
S32 getRequestedIndices() const { return mRequestedNumIndices; }
|
S32 getRequestedIndices() const { return mRequestedNumIndices; }
|
||||||
|
|
||||||
volatile U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; }
|
volatile U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
|
||||||
volatile U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; }
|
volatile U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
|
||||||
S32 getStride() const { return mStride; }
|
S32 getStride() const { return mStride; }
|
||||||
S32 getTypeMask() const { return mTypeMask; }
|
S32 getTypeMask() const { return mTypeMask; }
|
||||||
BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; }
|
BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; }
|
||||||
@@ -228,6 +230,8 @@ protected:
|
|||||||
S32 mRequestedNumVerts; // Number of vertices requested
|
S32 mRequestedNumVerts; // Number of vertices requested
|
||||||
S32 mRequestedNumIndices; // Number of indices requested
|
S32 mRequestedNumIndices; // Number of indices requested
|
||||||
|
|
||||||
|
ptrdiff_t mAlignedOffset;
|
||||||
|
ptrdiff_t mAlignedIndexOffset;
|
||||||
S32 mStride;
|
S32 mStride;
|
||||||
U32 mTypeMask;
|
U32 mTypeMask;
|
||||||
S32 mUsage; // GL usage
|
S32 mUsage; // GL usage
|
||||||
@@ -244,21 +248,6 @@ protected:
|
|||||||
BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
|
BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded)
|
||||||
S32 mOffsets[TYPE_MAX];
|
S32 mOffsets[TYPE_MAX];
|
||||||
|
|
||||||
class DirtyRegion
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
U32 mIndex;
|
|
||||||
U32 mCount;
|
|
||||||
U32 mIndicesIndex;
|
|
||||||
U32 mIndicesCount;
|
|
||||||
|
|
||||||
DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic)
|
|
||||||
: mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static S32 sCount;
|
static S32 sCount;
|
||||||
static S32 sGLCount;
|
static S32 sGLCount;
|
||||||
@@ -269,7 +258,7 @@ public:
|
|||||||
|
|
||||||
static BOOL sDisableVBOMapping; //disable glMapBufferARB
|
static BOOL sDisableVBOMapping; //disable glMapBufferARB
|
||||||
static BOOL sEnableVBOs;
|
static BOOL sEnableVBOs;
|
||||||
static S32 sTypeOffsets[TYPE_MAX];
|
static S32 sTypeSize[TYPE_MAX];
|
||||||
static U32 sGLMode[LLRender::NUM_MODES];
|
static U32 sGLMode[LLRender::NUM_MODES];
|
||||||
static U32 sGLRenderBuffer;
|
static U32 sGLRenderBuffer;
|
||||||
static U32 sGLRenderIndices;
|
static U32 sGLRenderIndices;
|
||||||
|
|||||||
@@ -431,7 +431,8 @@ public:
|
|||||||
|
|
||||||
void setText(const LLStringExplicit &new_text) { mSearchEdit->setText(new_text); }
|
void setText(const LLStringExplicit &new_text) { mSearchEdit->setText(new_text); }
|
||||||
|
|
||||||
void setSearchCallback(void (*search_callback)(const std::string& search_string, void* user_data), void* data) { mSearchCallback = search_callback; mCallbackUserData = data; }
|
typedef boost::function<void (const std::string&, void *)> search_callback_t;
|
||||||
|
void setSearchCallback(search_callback_t cb,void *user_data) { mSearchCallback = boost::bind(cb,_1,user_data); }
|
||||||
|
|
||||||
// LLUICtrl interface
|
// LLUICtrl interface
|
||||||
virtual void setValue(const LLSD& value );
|
virtual void setValue(const LLSD& value );
|
||||||
@@ -446,7 +447,8 @@ private:
|
|||||||
|
|
||||||
LLLineEditor* mSearchEdit;
|
LLLineEditor* mSearchEdit;
|
||||||
class LLButton* mClearSearchButton;
|
class LLButton* mClearSearchButton;
|
||||||
void (*mSearchCallback)(const std::string& search_string, void* user_data);
|
|
||||||
|
search_callback_t mSearchCallback;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -307,17 +307,10 @@ void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
|
|||||||
val = (F32) atof( text.c_str() );
|
val = (F32) atof( text.c_str() );
|
||||||
if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() )
|
if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() )
|
||||||
{
|
{
|
||||||
if( self->mValidateCallback )
|
self->setCurSliderValue( val );
|
||||||
|
if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) &&
|
||||||
|
(!self->mValidateSignal || (*(self->mValidateSignal))(self, val)))
|
||||||
{
|
{
|
||||||
self->setCurSliderValue( val ); // set the value temporarily so that the callback can retrieve it.
|
|
||||||
if( self->mValidateCallback( self, self->mCallbackUserData ) )
|
|
||||||
{
|
|
||||||
success = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->setCurSliderValue( val );
|
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,18 +341,11 @@ void LLMultiSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
|
|||||||
F32 saved_val = self->mCurValue;
|
F32 saved_val = self->mCurValue;
|
||||||
F32 new_val = self->mMultiSlider->getCurSliderValue();
|
F32 new_val = self->mMultiSlider->getCurSliderValue();
|
||||||
|
|
||||||
if( self->mValidateCallback )
|
self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it.
|
||||||
|
if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) &&
|
||||||
|
(!self->mValidateSignal || (*(self->mValidateSignal))(self, new_val )))
|
||||||
{
|
{
|
||||||
self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it.
|
|
||||||
if( self->mValidateCallback( self, self->mCallbackUserData ) )
|
|
||||||
{
|
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->mCurValue = new_val;
|
|
||||||
success = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( success )
|
if( success )
|
||||||
|
|||||||
@@ -238,17 +238,10 @@ void LLSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
|
|||||||
val = (F32) atof( text.c_str() );
|
val = (F32) atof( text.c_str() );
|
||||||
if( self->mSlider->getMinValue() <= val && val <= self->mSlider->getMaxValue() )
|
if( self->mSlider->getMinValue() <= val && val <= self->mSlider->getMaxValue() )
|
||||||
{
|
{
|
||||||
if( self->mValidateCallback )
|
self->setValue( val );
|
||||||
|
if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) &&
|
||||||
|
(!self->mValidateSignal || (*(self->mValidateSignal))( self, val )))
|
||||||
{
|
{
|
||||||
self->setValue( val ); // set the value temporarily so that the callback can retrieve it.
|
|
||||||
if( self->mValidateCallback( self, self->mCallbackUserData ) )
|
|
||||||
{
|
|
||||||
success = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->setValue( val );
|
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,17 +272,10 @@ void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata )
|
|||||||
F32 saved_val = self->mValue;
|
F32 saved_val = self->mValue;
|
||||||
F32 new_val = self->mSlider->getValueF32();
|
F32 new_val = self->mSlider->getValueF32();
|
||||||
|
|
||||||
if( self->mValidateCallback )
|
self->mValue = new_val; // set the value temporarily so that the callback can retrieve it.
|
||||||
|
if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) &&
|
||||||
|
(!self->mValidateSignal || (*(self->mValidateSignal))( self, new_val )))
|
||||||
{
|
{
|
||||||
self->mValue = new_val; // set the value temporarily so that the callback can retrieve it.
|
|
||||||
if( self->mValidateCallback( self, self->mCallbackUserData ) )
|
|
||||||
{
|
|
||||||
success = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->mValue = new_val;
|
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,21 +168,15 @@ void LLSpinCtrl::onUpBtn( void *userdata )
|
|||||||
val = clamp_precision(val, self->mPrecision);
|
val = clamp_precision(val, self->mPrecision);
|
||||||
val = llmin( val, self->mMaxValue );
|
val = llmin( val, self->mMaxValue );
|
||||||
|
|
||||||
if( self->mValidateCallback )
|
F32 saved_val = (F32)self->getValue().asReal();
|
||||||
|
self->setValue(val);
|
||||||
|
if( (self->mValidateCallback && !self->mValidateCallback( self, self->mCallbackUserData ) ) ||
|
||||||
|
(self->mValidateSignal && !(*(self->mValidateSignal))( self, val ) ))
|
||||||
{
|
{
|
||||||
F32 saved_val = (F32)self->getValue().asReal();
|
self->setValue( saved_val );
|
||||||
self->setValue(val);
|
self->reportInvalidData();
|
||||||
if( !self->mValidateCallback( self, self->mCallbackUserData ) )
|
self->updateEditor();
|
||||||
{
|
return;
|
||||||
self->setValue( saved_val );
|
|
||||||
self->reportInvalidData();
|
|
||||||
self->updateEditor();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->setValue(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self->updateEditor();
|
self->updateEditor();
|
||||||
@@ -201,21 +195,19 @@ void LLSpinCtrl::onDownBtn( void *userdata )
|
|||||||
val = clamp_precision(val, self->mPrecision);
|
val = clamp_precision(val, self->mPrecision);
|
||||||
val = llmax( val, self->mMinValue );
|
val = llmax( val, self->mMinValue );
|
||||||
|
|
||||||
if( self->mValidateCallback )
|
|
||||||
|
if (val < self->mMinValue) val = self->mMinValue;
|
||||||
|
if (val > self->mMaxValue) val = self->mMaxValue;
|
||||||
|
|
||||||
|
F32 saved_val = (F32)self->getValue().asReal();
|
||||||
|
self->setValue(val);
|
||||||
|
if( (self->mValidateCallback && !self->mValidateCallback( self, self->mCallbackUserData ) ) ||
|
||||||
|
(self->mValidateSignal && !(*(self->mValidateSignal))( self, val ) ))
|
||||||
{
|
{
|
||||||
F32 saved_val = (F32)self->getValue().asReal();
|
self->setValue( saved_val );
|
||||||
self->setValue(val);
|
self->reportInvalidData();
|
||||||
if( !self->mValidateCallback( self, self->mCallbackUserData ) )
|
self->updateEditor();
|
||||||
{
|
return;
|
||||||
self->setValue( saved_val );
|
|
||||||
self->reportInvalidData();
|
|
||||||
self->updateEditor();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->setValue(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self->updateEditor();
|
self->updateEditor();
|
||||||
@@ -303,32 +295,20 @@ void LLSpinCtrl::onEditorCommit( LLUICtrl* caller, void *userdata )
|
|||||||
if (val < self->mMinValue) val = self->mMinValue;
|
if (val < self->mMinValue) val = self->mMinValue;
|
||||||
if (val > self->mMaxValue) val = self->mMaxValue;
|
if (val > self->mMaxValue) val = self->mMaxValue;
|
||||||
|
|
||||||
if( self->mValidateCallback )
|
F32 saved_val = self->mValue;
|
||||||
|
self->mValue = val;
|
||||||
|
|
||||||
|
if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) &&
|
||||||
|
(!self->mValidateSignal || (*(self->mValidateSignal))(self, val)))
|
||||||
{
|
{
|
||||||
F32 saved_val = self->mValue;
|
success = TRUE;
|
||||||
self->mValue = val;
|
self->onCommit();
|
||||||
if( self->mValidateCallback( self, self->mCallbackUserData ) )
|
|
||||||
{
|
|
||||||
success = TRUE;
|
|
||||||
self->onCommit();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->mValue = saved_val;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self->mValue = val;
|
self->mValue = saved_val;
|
||||||
self->onCommit();
|
|
||||||
success = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// We want to update the editor in case it fails while blanking -- MC
|
|
||||||
success = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( success )
|
if( success )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4095,7 +4095,7 @@ void LLTextEditor::appendHighlightedText(const std::string &new_text,
|
|||||||
|
|
||||||
if (highlight && stylep)
|
if (highlight && stylep)
|
||||||
{
|
{
|
||||||
LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), highlight_part);
|
LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), (LLTextParser::EHighlightPosition)highlight_part);
|
||||||
bool lprepend=prepend_newline;
|
bool lprepend=prepend_newline;
|
||||||
for (S32 i=0;i<pieces.size();i++)
|
for (S32 i=0;i<pieces.size();i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,29 +43,14 @@
|
|||||||
#include "v4color.h"
|
#include "v4color.h"
|
||||||
#include "lldir.h"
|
#include "lldir.h"
|
||||||
|
|
||||||
// Routines used for parsing text for TextParsers and html
|
|
||||||
|
|
||||||
LLTextParser* LLTextParser::sInstance = NULL;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Member Functions
|
// Member Functions
|
||||||
//
|
//
|
||||||
|
|
||||||
LLTextParser::~LLTextParser()
|
LLTextParser::LLTextParser()
|
||||||
{
|
: mLoaded(false)
|
||||||
sInstance=NULL;
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
LLTextParser* LLTextParser::getInstance()
|
|
||||||
{
|
|
||||||
if (!sInstance)
|
|
||||||
{
|
|
||||||
sInstance = new LLTextParser();
|
|
||||||
sInstance->loadFromDisk();
|
|
||||||
}
|
|
||||||
return sInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency.
|
// Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency.
|
||||||
|
|
||||||
@@ -103,8 +88,10 @@ S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, S32 part, S32 index)
|
LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index)
|
||||||
{
|
{
|
||||||
|
loadKeywords();
|
||||||
|
|
||||||
//evil recursive string atomizer.
|
//evil recursive string atomizer.
|
||||||
LLSD ret_llsd, start_llsd, middle_llsd, end_llsd;
|
LLSD ret_llsd, start_llsd, middle_llsd, end_llsd;
|
||||||
|
|
||||||
@@ -122,7 +109,7 @@ LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLC
|
|||||||
{
|
{
|
||||||
S32 end = std::string(mHighlights[i]["pattern"]).length();
|
S32 end = std::string(mHighlights[i]["pattern"]).length();
|
||||||
S32 len = text.length();
|
S32 len = text.length();
|
||||||
S32 newpart;
|
EHighlightPosition newpart;
|
||||||
if (start==0)
|
if (start==0)
|
||||||
{
|
{
|
||||||
start_llsd[0]["text"] =text.substr(0,end);
|
start_llsd[0]["text"] =text.substr(0,end);
|
||||||
@@ -195,6 +182,8 @@ LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLC
|
|||||||
|
|
||||||
bool LLTextParser::parseFullLineHighlights(const std::string &text, LLColor4 *color)
|
bool LLTextParser::parseFullLineHighlights(const std::string &text, LLColor4 *color)
|
||||||
{
|
{
|
||||||
|
loadKeywords();
|
||||||
|
|
||||||
for (S32 i=0;i<mHighlights.size();i++)
|
for (S32 i=0;i<mHighlights.size();i++)
|
||||||
{
|
{
|
||||||
if ((S32)mHighlights[i]["highlight"]==ALL || (S32)mHighlights[i]["condition"]==MATCHES)
|
if ((S32)mHighlights[i]["highlight"]==ALL || (S32)mHighlights[i]["condition"]==MATCHES)
|
||||||
@@ -221,14 +210,14 @@ std::string LLTextParser::getFileName()
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLSD LLTextParser::loadFromDisk()
|
void LLTextParser::loadKeywords()
|
||||||
{
|
{
|
||||||
std::string filename=getFileName();
|
if (mLoaded)
|
||||||
if (filename.empty())
|
{// keywords already loaded
|
||||||
{
|
return;
|
||||||
llwarns << "LLTextParser::loadFromDisk() no valid user directory." << llendl;
|
|
||||||
}
|
}
|
||||||
else
|
std::string filename=getFileName();
|
||||||
|
if (!filename.empty())
|
||||||
{
|
{
|
||||||
llifstream file;
|
llifstream file;
|
||||||
file.open(filename.c_str());
|
file.open(filename.c_str());
|
||||||
@@ -237,9 +226,8 @@ LLSD LLTextParser::loadFromDisk()
|
|||||||
LLSDSerialize::fromXML(mHighlights, file);
|
LLSDSerialize::fromXML(mHighlights, file);
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
mLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mHighlights;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LLTextParser::saveToDisk(LLSD highlights)
|
bool LLTextParser::saveToDisk(LLSD highlights)
|
||||||
|
|||||||
@@ -35,34 +35,34 @@
|
|||||||
#define LL_LLTEXTPARSER_H
|
#define LL_LLTEXTPARSER_H
|
||||||
|
|
||||||
#include "llsd.h"
|
#include "llsd.h"
|
||||||
|
#include "llsingleton.h"
|
||||||
|
|
||||||
class LLUUID;
|
class LLUUID;
|
||||||
class LLVector3d;
|
class LLVector3d;
|
||||||
class LLColor4;
|
class LLColor4;
|
||||||
|
|
||||||
class LLTextParser
|
class LLTextParser : public LLSingleton<LLTextParser>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum ConditionType { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH };
|
typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType;
|
||||||
enum HighlightType { PART, ALL };
|
typedef enum e_highlight_type { PART, ALL } EHighlightType;
|
||||||
enum HighlightPosition { WHOLE, START, MIDDLE, END };
|
typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition;
|
||||||
enum DialogAction { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE };
|
typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction;
|
||||||
|
|
||||||
static LLTextParser* getInstance();
|
LLTextParser();
|
||||||
LLTextParser(){};
|
|
||||||
~LLTextParser();
|
|
||||||
|
|
||||||
S32 findPattern(const std::string &text, LLSD highlight);
|
LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0);
|
||||||
LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color,S32 part=WHOLE, S32 index=0);
|
|
||||||
bool parseFullLineHighlights(const std::string &text, LLColor4 *color);
|
bool parseFullLineHighlights(const std::string &text, LLColor4 *color);
|
||||||
|
|
||||||
std::string getFileName();
|
S32 findPattern(const std::string &text, LLSD highlight);
|
||||||
LLSD loadFromDisk();
|
|
||||||
bool saveToDisk(LLSD highlights);
|
|
||||||
public:
|
|
||||||
LLSD mHighlights;
|
|
||||||
private:
|
private:
|
||||||
static LLTextParser* sInstance;
|
std::string getFileName();
|
||||||
|
void loadKeywords();
|
||||||
|
bool saveToDisk(LLSD highlights);
|
||||||
|
|
||||||
|
public:
|
||||||
|
LLSD mHighlights;
|
||||||
|
bool mLoaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ static LLRegisterWidget<LLUICtrl> r("ui_ctrl");
|
|||||||
// NOTE: the LLFocusableElement implementation has been moved to llfocusmgr.cpp, to mirror the header where the class is defined.
|
// NOTE: the LLFocusableElement implementation has been moved to llfocusmgr.cpp, to mirror the header where the class is defined.
|
||||||
|
|
||||||
LLUICtrl::LLUICtrl() :
|
LLUICtrl::LLUICtrl() :
|
||||||
|
mCommitSignal(NULL),
|
||||||
|
mValidateSignal(NULL),
|
||||||
mCommitCallback(NULL),
|
mCommitCallback(NULL),
|
||||||
mLostTopCallback(NULL),
|
mLostTopCallback(NULL),
|
||||||
mValidateCallback(NULL),
|
mValidateCallback(NULL),
|
||||||
@@ -59,7 +61,9 @@ LLUICtrl::LLUICtrl(const std::string& name, const LLRect& rect, BOOL mouse_opaqu
|
|||||||
: // can't make this automatically follow top and left, breaks lots
|
: // can't make this automatically follow top and left, breaks lots
|
||||||
// of buttons in the UI. JC 7/20/2002
|
// of buttons in the UI. JC 7/20/2002
|
||||||
LLView( name, rect, mouse_opaque, reshape ),
|
LLView( name, rect, mouse_opaque, reshape ),
|
||||||
mCommitCallback( on_commit_callback) ,
|
mCommitSignal(NULL),
|
||||||
|
mValidateSignal(NULL),
|
||||||
|
mCommitCallback( on_commit_callback),
|
||||||
mLostTopCallback( NULL ),
|
mLostTopCallback( NULL ),
|
||||||
mValidateCallback( NULL ),
|
mValidateCallback( NULL ),
|
||||||
mCallbackUserData( callback_userdata ),
|
mCallbackUserData( callback_userdata ),
|
||||||
@@ -78,6 +82,9 @@ LLUICtrl::~LLUICtrl()
|
|||||||
llwarns << "UI Control holding top ctrl deleted: " << getName() << ". Top view removed." << llendl;
|
llwarns << "UI Control holding top ctrl deleted: " << getName() << ". Top view removed." << llendl;
|
||||||
gFocusMgr.removeTopCtrlWithoutCallback( this );
|
gFocusMgr.removeTopCtrlWithoutCallback( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete mCommitSignal;
|
||||||
|
delete mValidateSignal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLUICtrl::onCommit()
|
void LLUICtrl::onCommit()
|
||||||
@@ -86,6 +93,8 @@ void LLUICtrl::onCommit()
|
|||||||
{
|
{
|
||||||
mCommitCallback( this, mCallbackUserData );
|
mCommitCallback( this, mCallbackUserData );
|
||||||
}
|
}
|
||||||
|
if (mCommitSignal)
|
||||||
|
(*mCommitSignal)(this, getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
//virtual
|
//virtual
|
||||||
@@ -555,3 +564,15 @@ void LLUICtrl::setMinValue(LLSD min_value)
|
|||||||
// virtual
|
// virtual
|
||||||
void LLUICtrl::setMaxValue(LLSD max_value)
|
void LLUICtrl::setMaxValue(LLSD max_value)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb )
|
||||||
|
{
|
||||||
|
if (!mCommitSignal) mCommitSignal = new commit_signal_t();
|
||||||
|
return mCommitSignal->connect(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb )
|
||||||
|
{
|
||||||
|
if (!mValidateSignal) mValidateSignal = new enable_signal_t();
|
||||||
|
return mValidateSignal->connect(cb);
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ class LLUICtrl
|
|||||||
: public LLView
|
: public LLView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> commit_signal_t;
|
||||||
|
typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t;
|
||||||
|
|
||||||
typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata);
|
typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata);
|
||||||
typedef BOOL (*LLUICtrlValidate)(LLUICtrl* ctrl, void* userdata);
|
typedef BOOL (*LLUICtrlValidate)(LLUICtrl* ctrl, void* userdata);
|
||||||
|
|
||||||
@@ -111,6 +114,12 @@ public:
|
|||||||
|
|
||||||
LLUICtrl* getParentUICtrl() const;
|
LLUICtrl* getParentUICtrl() const;
|
||||||
|
|
||||||
|
//Start using these!
|
||||||
|
boost::signals2::connection setCommitCallback( const commit_signal_t::slot_type& cb );
|
||||||
|
boost::signals2::connection setValidateCallback( const enable_signal_t::slot_type& cb );
|
||||||
|
|
||||||
|
// *TODO: Deprecate; for backwards compatability only:
|
||||||
|
//Keeping userdata around with legacy setCommitCallback because it's used ALL OVER THE PLACE.
|
||||||
void* getCallbackUserData() const { return mCallbackUserData; }
|
void* getCallbackUserData() const { return mCallbackUserData; }
|
||||||
void setCallbackUserData( void* data ) { mCallbackUserData = data; }
|
void setCallbackUserData( void* data ) { mCallbackUserData = data; }
|
||||||
|
|
||||||
@@ -132,6 +141,8 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
commit_signal_t* mCommitSignal;
|
||||||
|
enable_signal_t* mValidateSignal;
|
||||||
void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata );
|
void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata );
|
||||||
void (*mLostTopCallback)( LLUICtrl* ctrl, void* userdata );
|
void (*mLostTopCallback)( LLUICtrl* ctrl, void* userdata );
|
||||||
BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata );
|
BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata );
|
||||||
|
|||||||
@@ -100,12 +100,14 @@ set(viewer_SOURCE_FILES
|
|||||||
jcfloaterareasearch.cpp
|
jcfloaterareasearch.cpp
|
||||||
chatbar_as_cmdline.cpp
|
chatbar_as_cmdline.cpp
|
||||||
qtoolalign.cpp
|
qtoolalign.cpp
|
||||||
|
llaccountingquotamanager.cpp
|
||||||
llagent.cpp
|
llagent.cpp
|
||||||
llagentaccess.cpp
|
llagentaccess.cpp
|
||||||
llagentcamera.cpp
|
llagentcamera.cpp
|
||||||
llagentdata.cpp
|
llagentdata.cpp
|
||||||
llagentlanguage.cpp
|
llagentlanguage.cpp
|
||||||
llagentpilot.cpp
|
llagentpilot.cpp
|
||||||
|
llagentui.cpp
|
||||||
llagentwearables.cpp
|
llagentwearables.cpp
|
||||||
llanimstatelabels.cpp
|
llanimstatelabels.cpp
|
||||||
llappviewer.cpp
|
llappviewer.cpp
|
||||||
@@ -293,6 +295,7 @@ set(viewer_SOURCE_FILES
|
|||||||
llmediaremotectrl.cpp
|
llmediaremotectrl.cpp
|
||||||
llmemoryview.cpp
|
llmemoryview.cpp
|
||||||
llmenucommands.cpp
|
llmenucommands.cpp
|
||||||
|
llmeshrepository.cpp
|
||||||
llmimetypes.cpp
|
llmimetypes.cpp
|
||||||
llmorphview.cpp
|
llmorphview.cpp
|
||||||
llmoveview.cpp
|
llmoveview.cpp
|
||||||
@@ -577,12 +580,14 @@ set(viewer_HEADER_FILES
|
|||||||
lgghunspell_wrapper.h
|
lgghunspell_wrapper.h
|
||||||
chatbar_as_cmdline.h
|
chatbar_as_cmdline.h
|
||||||
qtoolalign.h
|
qtoolalign.h
|
||||||
|
llaccountingquotamanager.h
|
||||||
llagent.h
|
llagent.h
|
||||||
llagentaccess.h
|
llagentaccess.h
|
||||||
llagentcamera.h
|
llagentcamera.h
|
||||||
llagentdata.h
|
llagentdata.h
|
||||||
llagentlanguage.h
|
llagentlanguage.h
|
||||||
llagentpilot.h
|
llagentpilot.h
|
||||||
|
llagentui.h
|
||||||
llagentwearables.h
|
llagentwearables.h
|
||||||
llanimstatelabels.h
|
llanimstatelabels.h
|
||||||
llappearance.h
|
llappearance.h
|
||||||
@@ -771,6 +776,7 @@ set(viewer_HEADER_FILES
|
|||||||
llmediaremotectrl.h
|
llmediaremotectrl.h
|
||||||
llmemoryview.h
|
llmemoryview.h
|
||||||
llmenucommands.h
|
llmenucommands.h
|
||||||
|
llmeshrepository.h
|
||||||
llmimetypes.h
|
llmimetypes.h
|
||||||
llmorphview.h
|
llmorphview.h
|
||||||
llmoveview.h
|
llmoveview.h
|
||||||
|
|||||||
@@ -3835,10 +3835,21 @@
|
|||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</map>
|
</map>
|
||||||
|
<key>DebugShowMemory</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Show Total Allocated Memory</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>Boolean</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</map>
|
||||||
<key>DebugShowRenderInfo</key>
|
<key>DebugShowRenderInfo</key>
|
||||||
<map>
|
<map>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
<string>Show depth buffer contents</string>
|
<string>Show stats about current scene</string>
|
||||||
<key>Persist</key>
|
<key>Persist</key>
|
||||||
<integer>1</integer>
|
<integer>1</integer>
|
||||||
<key>Type</key>
|
<key>Type</key>
|
||||||
@@ -7920,6 +7931,51 @@
|
|||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<integer>410</integer>
|
<integer>410</integer>
|
||||||
</map>
|
</map>
|
||||||
|
<key>MeshEnabled</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Expose UI for mesh functionality (may require restart to take effect).</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>Boolean</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<real>1</real>
|
||||||
|
</map>
|
||||||
|
<key>MeshImportUseSLM</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Use cached copy of last upload for a dae if available instead of loading dae file from scratch.</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>Boolean</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<real>0</real>
|
||||||
|
</map>
|
||||||
|
<key>MeshUploadLogXML</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Verbose XML logging on mesh upload</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>Boolean</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<real>0</real>
|
||||||
|
</map>
|
||||||
|
<key>MeshUploadFakeErrors</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Force upload errors (for testing)</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>S32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<real>0</real>
|
||||||
|
</map>
|
||||||
|
|
||||||
<key>MigrateCacheDirectory</key>
|
<key>MigrateCacheDirectory</key>
|
||||||
<map>
|
<map>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
@@ -11072,6 +11128,39 @@
|
|||||||
<key>Value</key>
|
<key>Value</key>
|
||||||
<real>1.0</real>
|
<real>1.0</real>
|
||||||
</map>
|
</map>
|
||||||
|
<key>MeshStreamingCostScaler</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>DEBUG</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>F32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<real>2.0</real>
|
||||||
|
</map>
|
||||||
|
<key>MeshThreadCount</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Number of threads to use for loading meshes.</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>U32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<integer>8</integer>
|
||||||
|
</map>
|
||||||
|
<key>MeshMaxConcurrentRequests</key>
|
||||||
|
<map>
|
||||||
|
<key>Comment</key>
|
||||||
|
<string>Number of threads to use for loading meshes.</string>
|
||||||
|
<key>Persist</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>Type</key>
|
||||||
|
<string>U32</string>
|
||||||
|
<key>Value</key>
|
||||||
|
<integer>32</integer>
|
||||||
|
</map>
|
||||||
<key>RunBtnState</key>
|
<key>RunBtnState</key>
|
||||||
<map>
|
<map>
|
||||||
<key>Comment</key>
|
<key>Comment</key>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* @file objectSkinV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
attribute vec4 object_weight;
|
||||||
|
|
||||||
|
uniform mat4 matrixPalette[32];
|
||||||
|
|
||||||
|
mat4 getObjectSkinnedTransform()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
vec4 w = fract(object_weight);
|
||||||
|
vec4 index = floor(object_weight);
|
||||||
|
|
||||||
|
float scale = 1.0/(w.x+w.y+w.z+w.w);
|
||||||
|
w *= scale;
|
||||||
|
|
||||||
|
mat4 mat = matrixPalette[int(index.x)]*w.x;
|
||||||
|
mat += matrixPalette[int(index.y)]*w.y;
|
||||||
|
mat += matrixPalette[int(index.z)]*w.z;
|
||||||
|
mat += matrixPalette[int(index.w)]*w.w;
|
||||||
|
|
||||||
|
return mat;
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/**
|
||||||
|
* @file alphaSkinnedV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
void calcAtmospherics(vec3 inPositionEye);
|
||||||
|
|
||||||
|
float calcDirectionalLight(vec3 n, vec3 l);
|
||||||
|
|
||||||
|
vec3 atmosAmbient(vec3 light);
|
||||||
|
vec3 atmosAffectDirectionalLight(float lightIntensity);
|
||||||
|
vec3 scaleDownLight(vec3 light);
|
||||||
|
vec3 scaleUpLight(vec3 light);
|
||||||
|
|
||||||
|
varying vec3 vary_position;
|
||||||
|
varying vec3 vary_ambient;
|
||||||
|
varying vec3 vary_directional;
|
||||||
|
varying vec3 vary_normal;
|
||||||
|
varying vec3 vary_fragcoord;
|
||||||
|
varying vec3 vary_pointlight_col;
|
||||||
|
|
||||||
|
uniform float near_clip;
|
||||||
|
|
||||||
|
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
|
||||||
|
{
|
||||||
|
//get light vector
|
||||||
|
vec3 lv = lp.xyz-v;
|
||||||
|
|
||||||
|
//get distance
|
||||||
|
float d = length(lv);
|
||||||
|
|
||||||
|
float da = 0.0;
|
||||||
|
|
||||||
|
if (d > 0.0 && la > 0.0 && fa > 0.0)
|
||||||
|
{
|
||||||
|
//normalize light vector
|
||||||
|
lv *= 1.0/d;
|
||||||
|
|
||||||
|
//distance attenuation
|
||||||
|
float dist2 = d*d/(la*la);
|
||||||
|
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
|
||||||
|
|
||||||
|
// spotlight coefficient.
|
||||||
|
float spot = max(dot(-ln, lv), is_pointlight);
|
||||||
|
da *= spot*spot; // GL_SPOT_EXPONENT=2
|
||||||
|
|
||||||
|
//angular attenuation
|
||||||
|
da *= calcDirectionalLight(n, lv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return da;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
vec4 pos;
|
||||||
|
vec3 norm;
|
||||||
|
|
||||||
|
mat4 trans = getObjectSkinnedTransform();
|
||||||
|
trans = gl_ModelViewMatrix * trans;
|
||||||
|
|
||||||
|
pos = trans * gl_Vertex;
|
||||||
|
|
||||||
|
norm = gl_Vertex.xyz + gl_Normal.xyz;
|
||||||
|
norm = normalize(( trans*vec4(norm, 1.0) ).xyz-pos.xyz);
|
||||||
|
|
||||||
|
vec4 frag_pos = gl_ProjectionMatrix * pos;
|
||||||
|
gl_Position = frag_pos;
|
||||||
|
|
||||||
|
vary_position = pos.xyz;
|
||||||
|
vary_normal = norm;
|
||||||
|
|
||||||
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
|
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
|
||||||
|
|
||||||
|
// Collect normal lights
|
||||||
|
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a);
|
||||||
|
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a);
|
||||||
|
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a);
|
||||||
|
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a);
|
||||||
|
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a);
|
||||||
|
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a);
|
||||||
|
|
||||||
|
vary_pointlight_col = col.rgb*gl_Color.rgb;
|
||||||
|
|
||||||
|
col.rgb = vec3(0,0,0);
|
||||||
|
|
||||||
|
// Add windlight lights
|
||||||
|
col.rgb = atmosAmbient(vec3(0.));
|
||||||
|
|
||||||
|
vary_ambient = col.rgb*gl_Color.rgb;
|
||||||
|
vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
|
||||||
|
|
||||||
|
col.rgb = min(col.rgb*gl_Color.rgb, 1.0);
|
||||||
|
|
||||||
|
gl_FrontColor = col;
|
||||||
|
|
||||||
|
gl_FogFragCoord = pos.z;
|
||||||
|
|
||||||
|
vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* @file avatarShadowF.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a);
|
||||||
|
gl_FragColor = vec4(1,1,1,1);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* @file attachmentShadowV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//transform vertex
|
||||||
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
mat4 mat = getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
mat = gl_ModelViewMatrix * mat;
|
||||||
|
vec3 pos = (mat*gl_Vertex).xyz;
|
||||||
|
|
||||||
|
gl_FrontColor = gl_Color;
|
||||||
|
|
||||||
|
vec4 p = gl_ProjectionMatrix * vec4(pos, 1.0);
|
||||||
|
p.z = max(p.z, -p.w+0.01);
|
||||||
|
gl_Position = p;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* @file bumpV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
varying vec3 vary_mat0;
|
||||||
|
varying vec3 vary_mat1;
|
||||||
|
varying vec3 vary_mat2;
|
||||||
|
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
mat4 mat = getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
mat = gl_ModelViewMatrix * mat;
|
||||||
|
|
||||||
|
vec3 pos = (mat*gl_Vertex).xyz;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 n = normalize((mat * vec4(gl_Normal.xyz+gl_Vertex.xyz, 1.0)).xyz-pos.xyz);
|
||||||
|
vec3 b = normalize((mat * vec4(gl_MultiTexCoord2.xyz+gl_Vertex.xyz, 1.0)).xyz-pos.xyz);
|
||||||
|
vec3 t = cross(b, n);
|
||||||
|
|
||||||
|
vary_mat0 = vec3(t.x, b.x, n.x);
|
||||||
|
vary_mat1 = vec3(t.y, b.y, n.y);
|
||||||
|
vary_mat2 = vec3(t.z, b.z, n.z);
|
||||||
|
|
||||||
|
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
|
||||||
|
gl_FrontColor = gl_Color;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* @file diffuseSkinnedV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
varying vec3 vary_normal;
|
||||||
|
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
mat4 mat = getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
mat = gl_ModelViewMatrix * mat;
|
||||||
|
vec3 pos = (mat*gl_Vertex).xyz;
|
||||||
|
|
||||||
|
vec4 norm = gl_Vertex;
|
||||||
|
norm.xyz += gl_Normal.xyz;
|
||||||
|
norm.xyz = (mat*norm).xyz;
|
||||||
|
norm.xyz = normalize(norm.xyz-pos.xyz);
|
||||||
|
|
||||||
|
vary_normal = norm.xyz;
|
||||||
|
|
||||||
|
gl_FrontColor = gl_Color;
|
||||||
|
|
||||||
|
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* @file shinySimpleSkinnedV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
void calcAtmospherics(vec3 inPositionEye);
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
attribute vec4 object_weight;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
mat4 mat = getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
mat = gl_ModelViewMatrix * mat;
|
||||||
|
vec3 pos = (mat*gl_Vertex).xyz;
|
||||||
|
|
||||||
|
vec4 norm = gl_Vertex;
|
||||||
|
norm.xyz += gl_Normal.xyz;
|
||||||
|
norm.xyz = (mat*norm).xyz;
|
||||||
|
norm.xyz = normalize(norm.xyz-pos.xyz);
|
||||||
|
|
||||||
|
vec3 ref = reflect(pos.xyz, -norm.xyz);
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||||
|
gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0);
|
||||||
|
|
||||||
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
|
gl_FrontColor = gl_Color;
|
||||||
|
|
||||||
|
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
|
||||||
|
|
||||||
|
gl_FogFragCoord = pos.z;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* @file fullbrightSkinnedV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
void calcAtmospherics(vec3 inPositionEye);
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
attribute vec4 object_weight;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//transform vertex
|
||||||
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
mat4 mat = getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
mat = gl_ModelViewMatrix * mat;
|
||||||
|
vec3 pos = (mat*gl_Vertex).xyz;
|
||||||
|
|
||||||
|
vec4 norm = gl_Vertex;
|
||||||
|
norm.xyz += gl_Normal.xyz;
|
||||||
|
norm.xyz = (mat*norm).xyz;
|
||||||
|
norm.xyz = normalize(norm.xyz-pos.xyz);
|
||||||
|
|
||||||
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
|
gl_FrontColor = gl_Color;
|
||||||
|
|
||||||
|
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
|
||||||
|
|
||||||
|
gl_FogFragCoord = pos.z;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* @file shinySimpleSkinnedV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
|
||||||
|
void calcAtmospherics(vec3 inPositionEye);
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
attribute vec4 object_weight;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
mat4 mat = getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
mat = gl_ModelViewMatrix * mat;
|
||||||
|
vec3 pos = (mat*gl_Vertex).xyz;
|
||||||
|
|
||||||
|
vec4 norm = gl_Vertex;
|
||||||
|
norm.xyz += gl_Normal.xyz;
|
||||||
|
norm.xyz = (mat*norm).xyz;
|
||||||
|
norm.xyz = normalize(norm.xyz-pos.xyz);
|
||||||
|
|
||||||
|
vec3 ref = reflect(pos.xyz, -norm.xyz);
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||||
|
gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0);
|
||||||
|
|
||||||
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
|
vec4 color = calcLighting(pos.xyz, norm.xyz, gl_Color, vec4(0.));
|
||||||
|
gl_FrontColor = color;
|
||||||
|
|
||||||
|
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* @file simpleSkinnedV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
|
||||||
|
void calcAtmospherics(vec3 inPositionEye);
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
attribute vec4 object_weight;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//transform vertex
|
||||||
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
mat4 mat = getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
mat = gl_ModelViewMatrix * mat;
|
||||||
|
vec3 pos = (mat*gl_Vertex).xyz;
|
||||||
|
|
||||||
|
vec4 norm = gl_Vertex;
|
||||||
|
norm.xyz += gl_Normal.xyz;
|
||||||
|
norm.xyz = (mat*norm).xyz;
|
||||||
|
norm.xyz = normalize(norm.xyz-pos.xyz);
|
||||||
|
|
||||||
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
|
vec4 color = calcLighting(pos.xyz, norm.xyz, gl_Color, vec4(0.));
|
||||||
|
gl_FrontColor = color;
|
||||||
|
|
||||||
|
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
|
||||||
|
|
||||||
|
gl_FogFragCoord = pos.z;
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* @file alphaSkinnedV.glsl
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||||
|
* $License$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
|
||||||
|
void calcAtmospherics(vec3 inPositionEye);
|
||||||
|
|
||||||
|
float calcDirectionalLight(vec3 n, vec3 l);
|
||||||
|
mat4 getObjectSkinnedTransform();
|
||||||
|
vec3 atmosAmbient(vec3 light);
|
||||||
|
vec3 atmosAffectDirectionalLight(float lightIntensity);
|
||||||
|
vec3 scaleDownLight(vec3 light);
|
||||||
|
vec3 scaleUpLight(vec3 light);
|
||||||
|
|
||||||
|
varying vec3 vary_ambient;
|
||||||
|
varying vec3 vary_directional;
|
||||||
|
varying vec3 vary_fragcoord;
|
||||||
|
varying vec3 vary_position;
|
||||||
|
varying vec3 vary_pointlight_col;
|
||||||
|
|
||||||
|
uniform float near_clip;
|
||||||
|
uniform float shadow_offset;
|
||||||
|
uniform float shadow_bias;
|
||||||
|
|
||||||
|
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
|
||||||
|
{
|
||||||
|
//get light vector
|
||||||
|
vec3 lv = lp.xyz-v;
|
||||||
|
|
||||||
|
//get distance
|
||||||
|
float d = length(lv);
|
||||||
|
|
||||||
|
float da = 0.0;
|
||||||
|
|
||||||
|
if (d > 0.0 && la > 0.0 && fa > 0.0)
|
||||||
|
{
|
||||||
|
//normalize light vector
|
||||||
|
lv *= 1.0/d;
|
||||||
|
|
||||||
|
//distance attenuation
|
||||||
|
float dist2 = d*d/(la*la);
|
||||||
|
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
|
||||||
|
|
||||||
|
// spotlight coefficient.
|
||||||
|
float spot = max(dot(-ln, lv), is_pointlight);
|
||||||
|
da *= spot*spot; // GL_SPOT_EXPONENT=2
|
||||||
|
|
||||||
|
//angular attenuation
|
||||||
|
da *= calcDirectionalLight(n, lv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return da;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||||
|
|
||||||
|
mat4 mat = getObjectSkinnedTransform();
|
||||||
|
|
||||||
|
mat = gl_ModelViewMatrix * mat;
|
||||||
|
|
||||||
|
vec3 pos = (mat*gl_Vertex).xyz;
|
||||||
|
|
||||||
|
gl_Position = gl_ProjectionMatrix * vec4(pos, 1.0);
|
||||||
|
|
||||||
|
vec4 n = gl_Vertex;
|
||||||
|
n.xyz += gl_Normal.xyz;
|
||||||
|
n.xyz = (mat*n).xyz;
|
||||||
|
n.xyz = normalize(n.xyz-pos.xyz);
|
||||||
|
|
||||||
|
vec3 norm = n.xyz;
|
||||||
|
|
||||||
|
float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
|
||||||
|
vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset;
|
||||||
|
|
||||||
|
calcAtmospherics(pos.xyz);
|
||||||
|
|
||||||
|
//vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
|
||||||
|
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
|
||||||
|
|
||||||
|
// Collect normal lights
|
||||||
|
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a);
|
||||||
|
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a);
|
||||||
|
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a);
|
||||||
|
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a);
|
||||||
|
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a);
|
||||||
|
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a);
|
||||||
|
|
||||||
|
vary_pointlight_col = col.rgb*gl_Color.rgb;
|
||||||
|
|
||||||
|
col.rgb = vec3(0,0,0);
|
||||||
|
|
||||||
|
// Add windlight lights
|
||||||
|
col.rgb = atmosAmbient(vec3(0.));
|
||||||
|
|
||||||
|
vary_ambient = col.rgb*gl_Color.rgb;
|
||||||
|
vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
|
||||||
|
|
||||||
|
col.rgb = min(col.rgb*gl_Color.rgb, 1.0);
|
||||||
|
|
||||||
|
gl_FrontColor = col;
|
||||||
|
|
||||||
|
gl_FogFragCoord = pos.z;
|
||||||
|
|
||||||
|
pos.xyz = (gl_ModelViewProjectionMatrix * gl_Vertex).xyz;
|
||||||
|
vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,346 @@
|
|||||||
|
/**
|
||||||
|
* @file softenLightF.glsl
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
|
||||||
|
* $/LicenseInfo$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
#extension GL_ARB_texture_rectangle : enable
|
||||||
|
|
||||||
|
uniform sampler2DRect diffuseRect;
|
||||||
|
uniform sampler2DRect specularRect;
|
||||||
|
uniform sampler2DRect normalMap;
|
||||||
|
uniform sampler2DRect lightMap;
|
||||||
|
uniform sampler2DRect depthMap;
|
||||||
|
uniform sampler2D noiseMap;
|
||||||
|
uniform samplerCube environmentMap;
|
||||||
|
uniform sampler2D lightFunc;
|
||||||
|
uniform vec3 gi_quad;
|
||||||
|
|
||||||
|
uniform float blur_size;
|
||||||
|
uniform float blur_fidelity;
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
uniform vec4 morphFactor;
|
||||||
|
uniform vec3 camPosLocal;
|
||||||
|
//uniform vec4 camPosWorld;
|
||||||
|
uniform vec4 gamma;
|
||||||
|
uniform vec4 lightnorm;
|
||||||
|
uniform vec4 sunlight_color;
|
||||||
|
uniform vec4 ambient;
|
||||||
|
uniform vec4 blue_horizon;
|
||||||
|
uniform vec4 blue_density;
|
||||||
|
uniform vec4 haze_horizon;
|
||||||
|
uniform vec4 haze_density;
|
||||||
|
uniform vec4 cloud_shadow;
|
||||||
|
uniform vec4 density_multiplier;
|
||||||
|
uniform vec4 distance_multiplier;
|
||||||
|
uniform vec4 max_y;
|
||||||
|
uniform vec4 glow;
|
||||||
|
uniform float scene_light_strength;
|
||||||
|
uniform vec3 env_mat[3];
|
||||||
|
uniform vec4 shadow_clip;
|
||||||
|
uniform mat3 ssao_effect_mat;
|
||||||
|
|
||||||
|
uniform mat4 inv_proj;
|
||||||
|
uniform vec2 screen_res;
|
||||||
|
|
||||||
|
varying vec4 vary_light;
|
||||||
|
varying vec2 vary_fragcoord;
|
||||||
|
|
||||||
|
vec3 vary_PositionEye;
|
||||||
|
|
||||||
|
vec3 vary_SunlitColor;
|
||||||
|
vec3 vary_AmblitColor;
|
||||||
|
vec3 vary_AdditiveColor;
|
||||||
|
vec3 vary_AtmosAttenuation;
|
||||||
|
|
||||||
|
vec4 getPosition_d(vec2 pos_screen, float depth)
|
||||||
|
{
|
||||||
|
vec2 sc = pos_screen.xy*2.0;
|
||||||
|
sc /= screen_res;
|
||||||
|
sc -= vec2(1.0,1.0);
|
||||||
|
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
|
||||||
|
vec4 pos = inv_proj * ndc;
|
||||||
|
pos /= pos.w;
|
||||||
|
pos.w = 1.0;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 getPosition(vec2 pos_screen)
|
||||||
|
{ //get position in screen space (world units) given window coordinate and depth map
|
||||||
|
float depth = texture2DRect(depthMap, pos_screen.xy).a;
|
||||||
|
return getPosition_d(pos_screen, depth);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getPositionEye()
|
||||||
|
{
|
||||||
|
return vary_PositionEye;
|
||||||
|
}
|
||||||
|
vec3 getSunlitColor()
|
||||||
|
{
|
||||||
|
return vary_SunlitColor;
|
||||||
|
}
|
||||||
|
vec3 getAmblitColor()
|
||||||
|
{
|
||||||
|
return vary_AmblitColor;
|
||||||
|
}
|
||||||
|
vec3 getAdditiveColor()
|
||||||
|
{
|
||||||
|
return vary_AdditiveColor;
|
||||||
|
}
|
||||||
|
vec3 getAtmosAttenuation()
|
||||||
|
{
|
||||||
|
return vary_AtmosAttenuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setPositionEye(vec3 v)
|
||||||
|
{
|
||||||
|
vary_PositionEye = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSunlitColor(vec3 v)
|
||||||
|
{
|
||||||
|
vary_SunlitColor = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAmblitColor(vec3 v)
|
||||||
|
{
|
||||||
|
vary_AmblitColor = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAdditiveColor(vec3 v)
|
||||||
|
{
|
||||||
|
vary_AdditiveColor = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAtmosAttenuation(vec3 v)
|
||||||
|
{
|
||||||
|
vary_AtmosAttenuation = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
|
||||||
|
|
||||||
|
vec3 P = inPositionEye;
|
||||||
|
setPositionEye(P);
|
||||||
|
|
||||||
|
//(TERRAIN) limit altitude
|
||||||
|
if (P.y > max_y.x) P *= (max_y.x / P.y);
|
||||||
|
if (P.y < -max_y.x) P *= (-max_y.x / P.y);
|
||||||
|
|
||||||
|
vec3 tmpLightnorm = lightnorm.xyz;
|
||||||
|
|
||||||
|
vec3 Pn = normalize(P);
|
||||||
|
float Plen = length(P);
|
||||||
|
|
||||||
|
vec4 temp1 = vec4(0);
|
||||||
|
vec3 temp2 = vec3(0);
|
||||||
|
vec4 blue_weight;
|
||||||
|
vec4 haze_weight;
|
||||||
|
vec4 sunlight = sunlight_color;
|
||||||
|
vec4 light_atten;
|
||||||
|
|
||||||
|
//sunlight attenuation effect (hue and brightness) due to atmosphere
|
||||||
|
//this is used later for sunlight modulation at various altitudes
|
||||||
|
light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
|
||||||
|
//I had thought blue_density and haze_density should have equal weighting,
|
||||||
|
//but attenuation due to haze_density tends to seem too strong
|
||||||
|
|
||||||
|
temp1 = blue_density + vec4(haze_density.r);
|
||||||
|
blue_weight = blue_density / temp1;
|
||||||
|
haze_weight = vec4(haze_density.r) / temp1;
|
||||||
|
|
||||||
|
//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
|
||||||
|
temp2.y = max(0.0, tmpLightnorm.y);
|
||||||
|
temp2.y = 1. / temp2.y;
|
||||||
|
sunlight *= exp( - light_atten * temp2.y);
|
||||||
|
|
||||||
|
// main atmospheric scattering line integral
|
||||||
|
temp2.z = Plen * density_multiplier.x;
|
||||||
|
|
||||||
|
// Transparency (-> temp1)
|
||||||
|
// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
|
||||||
|
// compiler gets confused.
|
||||||
|
temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
|
||||||
|
|
||||||
|
//final atmosphere attenuation factor
|
||||||
|
setAtmosAttenuation(temp1.rgb);
|
||||||
|
|
||||||
|
//compute haze glow
|
||||||
|
//(can use temp2.x as temp because we haven't used it yet)
|
||||||
|
temp2.x = dot(Pn, tmpLightnorm.xyz);
|
||||||
|
temp2.x = 1. - temp2.x;
|
||||||
|
//temp2.x is 0 at the sun and increases away from sun
|
||||||
|
temp2.x = max(temp2.x, .03); //was glow.y
|
||||||
|
//set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
|
||||||
|
temp2.x *= glow.x;
|
||||||
|
//higher glow.x gives dimmer glow (because next step is 1 / "angle")
|
||||||
|
temp2.x = pow(temp2.x, glow.z);
|
||||||
|
//glow.z should be negative, so we're doing a sort of (1 / "angle") function
|
||||||
|
|
||||||
|
//add "minimum anti-solar illumination"
|
||||||
|
temp2.x += .25;
|
||||||
|
|
||||||
|
//increase ambient when there are more clouds
|
||||||
|
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
|
||||||
|
|
||||||
|
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
|
||||||
|
* // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
|
||||||
|
* // The following line of code performs the equivalent of:
|
||||||
|
* float ambAlpha = tmpAmbient.a;
|
||||||
|
* float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
|
||||||
|
* vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
|
||||||
|
* tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
|
||||||
|
*/
|
||||||
|
tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
|
||||||
|
|
||||||
|
//haze color
|
||||||
|
setAdditiveColor(
|
||||||
|
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
|
||||||
|
+ (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
|
||||||
|
+ tmpAmbient)));
|
||||||
|
|
||||||
|
//brightness of surface both sunlight and ambient
|
||||||
|
setSunlitColor(vec3(sunlight * .5));
|
||||||
|
setAmblitColor(vec3(tmpAmbient * .25));
|
||||||
|
setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 atmosLighting(vec3 light)
|
||||||
|
{
|
||||||
|
light *= getAtmosAttenuation().r;
|
||||||
|
light += getAdditiveColor();
|
||||||
|
return (2.0 * light);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 atmosTransport(vec3 light) {
|
||||||
|
light *= getAtmosAttenuation().r;
|
||||||
|
light += getAdditiveColor() * 2.0;
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
vec3 atmosGetDiffuseSunlightColor()
|
||||||
|
{
|
||||||
|
return getSunlitColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 scaleDownLight(vec3 light)
|
||||||
|
{
|
||||||
|
return (light / scene_light_strength );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 scaleUpLight(vec3 light)
|
||||||
|
{
|
||||||
|
return (light * scene_light_strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 atmosAmbient(vec3 light)
|
||||||
|
{
|
||||||
|
return getAmblitColor() + light / 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 atmosAffectDirectionalLight(float lightIntensity)
|
||||||
|
{
|
||||||
|
return getSunlitColor() * lightIntensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 scaleSoftClip(vec3 light)
|
||||||
|
{
|
||||||
|
//soft clip effect:
|
||||||
|
light = 1. - clamp(light, vec3(0.), vec3(1.));
|
||||||
|
light = 1. - pow(light, gamma.xxx);
|
||||||
|
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 tc = vary_fragcoord.xy;
|
||||||
|
float depth = texture2DRect(depthMap, tc.xy).a;
|
||||||
|
vec3 pos = getPosition_d(tc, depth).xyz;
|
||||||
|
vec3 norm = texture2DRect(normalMap, tc).xyz;
|
||||||
|
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
|
||||||
|
//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
|
||||||
|
|
||||||
|
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
|
||||||
|
|
||||||
|
vec4 diffuse = texture2DRect(diffuseRect, tc);
|
||||||
|
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
|
||||||
|
|
||||||
|
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
|
||||||
|
float scol = max(scol_ambocc.r, diffuse.a);
|
||||||
|
float ambocc = scol_ambocc.g;
|
||||||
|
|
||||||
|
calcAtmospherics(pos.xyz, ambocc);
|
||||||
|
|
||||||
|
vec3 col = atmosAmbient(vec3(0));
|
||||||
|
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
|
||||||
|
|
||||||
|
col *= diffuse.rgb;
|
||||||
|
|
||||||
|
if (spec.a > 0.0) // specular reflection
|
||||||
|
{
|
||||||
|
// the old infinite-sky shiny reflection
|
||||||
|
//
|
||||||
|
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
|
||||||
|
float sa = dot(refnormpersp, vary_light.xyz);
|
||||||
|
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// screen-space cheap fakey reflection map
|
||||||
|
//
|
||||||
|
vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz));
|
||||||
|
depth -= 0.5; // unbias depth
|
||||||
|
// first figure out where we'll make our 2D guess from
|
||||||
|
vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
|
||||||
|
// Offset the guess source a little according to a trivial
|
||||||
|
// checkerboard dither function and spec.a.
|
||||||
|
// This is meant to be similar to sampling a blurred version
|
||||||
|
// of the diffuse map. LOD would be better in that regard.
|
||||||
|
// The goal of the blur is to soften reflections in surfaces
|
||||||
|
// with low shinyness, and also to disguise our lameness.
|
||||||
|
float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0
|
||||||
|
float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5);
|
||||||
|
ref2d += vec2(checkoffset, checkoffset);
|
||||||
|
ref2d += tc.xy; // use as offset from destination
|
||||||
|
// Get attributes from the 2D guess point.
|
||||||
|
// We average two samples of diffuse (not of anything else) per
|
||||||
|
// pixel to try to reduce aliasing some more.
|
||||||
|
vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb +
|
||||||
|
texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
|
||||||
|
float refdepth = texture2DRect(depthMap, ref2d).a;
|
||||||
|
vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
|
||||||
|
float refshad = texture2DRect(lightMap, ref2d).r;
|
||||||
|
vec3 refn = texture2DRect(normalMap, ref2d).rgb;
|
||||||
|
refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
|
||||||
|
refn = normalize(refn);
|
||||||
|
// figure out how appropriate our guess actually was
|
||||||
|
float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
|
||||||
|
// darken reflections from points which face away from the reflected ray - our guess was a back-face
|
||||||
|
//refapprop *= step(dot(refnorm, refn), 0.0);
|
||||||
|
refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
|
||||||
|
// get appropriate light strength for guess-point
|
||||||
|
// reflect light direction to increase the illusion that
|
||||||
|
// these are reflections.
|
||||||
|
vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
|
||||||
|
float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad);
|
||||||
|
// apply sun color to guess-point, dampen according to inappropriateness of guess
|
||||||
|
float refmod = min(refapprop, reflit);
|
||||||
|
vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
|
||||||
|
vec3 ssshiny = (refprod * spec.a);
|
||||||
|
ssshiny *= 0.3; // dampen it even more
|
||||||
|
*/
|
||||||
|
vec3 ssshiny = vec3(0,0,0);
|
||||||
|
|
||||||
|
// add the two types of shiny together
|
||||||
|
col += (ssshiny + dumbshiny) * spec.rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
col = atmosLighting(col);
|
||||||
|
col = scaleSoftClip(col);
|
||||||
|
|
||||||
|
gl_FragColor.rgb = col;
|
||||||
|
gl_FragColor.a = 0.0;
|
||||||
|
}
|
||||||
@@ -730,8 +730,8 @@ void LLPreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
|
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
|
||||||
U32 num_indices = vf.mIndices.size();
|
U32 num_indices = vf.mNumIndices;
|
||||||
U32 num_vertices = vf.mVertices.size();
|
U32 num_vertices = vf.mNumVertices;
|
||||||
|
|
||||||
mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0);
|
mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0);
|
||||||
mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE);
|
mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE);
|
||||||
@@ -747,8 +747,8 @@ void LLPreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
|
|||||||
// build vertices and normals
|
// build vertices and normals
|
||||||
for (U32 i = 0; (S32)i < num_vertices; i++)
|
for (U32 i = 0; (S32)i < num_vertices; i++)
|
||||||
{
|
{
|
||||||
*(vertex_strider++) = vf.mVertices[i].mPosition;
|
(vertex_strider++)->set(vf.mPositions[i].getF32ptr());
|
||||||
LLVector3 normal = vf.mVertices[i].mNormal;
|
LLVector3 normal(vf.mNormals[i].getF32ptr());
|
||||||
normal.normalize();
|
normal.normalize();
|
||||||
*(normal_strider++) = normal;
|
*(normal_strider++) = normal;
|
||||||
}
|
}
|
||||||
@@ -812,7 +812,7 @@ BOOL LLPreviewSculpted::render()
|
|||||||
LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
|
LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
|
||||||
|
|
||||||
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
|
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
|
||||||
U32 num_indices = vf.mIndices.size();
|
U32 num_indices = vf.mNumIndices;
|
||||||
|
|
||||||
mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL);
|
mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL);
|
||||||
|
|
||||||
|
|||||||
281
indra/newview/llaccountingquotamanager.cpp
Normal file
281
indra/newview/llaccountingquotamanager.cpp
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
/**
|
||||||
|
* @file LLAccountingQuotaManager.cpp
|
||||||
|
* @ Handles the setting and accessing for costs associated with mesh
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2011, 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 "llviewerprecompiledheaders.h"
|
||||||
|
#if MESH_ENABLED
|
||||||
|
#include "llaccountingquotamanager.h"
|
||||||
|
#include "llagent.h"
|
||||||
|
#include "llviewerregion.h"
|
||||||
|
#include "llviewerobject.h"
|
||||||
|
#include "llviewerobjectlist.h"
|
||||||
|
#include "llviewerparcelmgr.h"
|
||||||
|
#include "llparcel.h"
|
||||||
|
|
||||||
|
//===============================================================================
|
||||||
|
LLAccountingQuotaManager::LLAccountingQuotaManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
//===============================================================================
|
||||||
|
class LLAccountingQuotaResponder : public LLCurl::Responder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLAccountingQuotaResponder( const LLSD& objectIDs )
|
||||||
|
: mObjectIDs( objectIDs )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearPendingRequests ( void )
|
||||||
|
{
|
||||||
|
for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
|
||||||
|
{
|
||||||
|
LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( iter->asUUID() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void error( U32 statusNum, const std::string& reason )
|
||||||
|
{
|
||||||
|
llwarns << "Transport error "<<reason<<llendl;
|
||||||
|
//prep#do we really want to remove all because of one failure - verify
|
||||||
|
clearPendingRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
void result( const LLSD& content )
|
||||||
|
{
|
||||||
|
if ( !content.isMap() || content.has("error") )
|
||||||
|
{
|
||||||
|
llwarns << "Error on fetched data"<< llendl;
|
||||||
|
//prep#do we really want to remove all because of one failure - verify
|
||||||
|
clearPendingRequests();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Differentiate what the incoming caps could be from the data
|
||||||
|
bool containsParcel = content.has("parcel");
|
||||||
|
bool containsSelection = content.has("selected");
|
||||||
|
|
||||||
|
//Loop over the stored object ids checking against the incoming data
|
||||||
|
for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
|
||||||
|
{
|
||||||
|
LLUUID objectID = iter->asUUID();
|
||||||
|
|
||||||
|
LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( objectID );
|
||||||
|
|
||||||
|
if ( containsParcel )
|
||||||
|
{
|
||||||
|
//Typically should be one
|
||||||
|
S32 dataCount = content["parcel"].size();
|
||||||
|
for(S32 i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
//prep#todo verify that this is safe, otherwise just add a bool
|
||||||
|
LLUUID parcelId;
|
||||||
|
//S32 parcelOwner = 0;
|
||||||
|
if ( content["parcel"][i].has("parcel_id") )
|
||||||
|
{
|
||||||
|
parcelId = content["parcel"][i]["parcel_id"].asUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
//if ( content["parcel"][i].has("parcel_owner") )
|
||||||
|
//{
|
||||||
|
// parcelOwner = content["parcel"][i]["parcel_owner"].asInteger();
|
||||||
|
//}
|
||||||
|
|
||||||
|
F32 ownerRenderCost = 0;
|
||||||
|
F32 ownerPhysicsCost = 0;
|
||||||
|
F32 ownerNetworkCost = 0;
|
||||||
|
F32 ownerSimulationCost = 0;
|
||||||
|
|
||||||
|
F32 groupRenderCost = 0;
|
||||||
|
F32 groupPhysicsCost = 0;
|
||||||
|
F32 groupNetworkCost = 0;
|
||||||
|
F32 groupSimulationCost = 0;
|
||||||
|
|
||||||
|
F32 otherRenderCost = 0;
|
||||||
|
F32 otherPhysicsCost = 0;
|
||||||
|
F32 otherNetworkCost = 0;
|
||||||
|
F32 otherSimulationCost = 0;
|
||||||
|
|
||||||
|
F32 tempRenderCost = 0;
|
||||||
|
F32 tempPhysicsCost = 0;
|
||||||
|
F32 tempNetworkCost = 0;
|
||||||
|
F32 tempSimulationCost = 0;
|
||||||
|
|
||||||
|
F32 selectedRenderCost = 0;
|
||||||
|
F32 selectedPhysicsCost = 0;
|
||||||
|
F32 selectedNetworkCost = 0;
|
||||||
|
F32 selectedSimulationCost = 0;
|
||||||
|
|
||||||
|
F32 parcelCapacity = 0;
|
||||||
|
|
||||||
|
if ( content["parcel"][i].has("capacity") )
|
||||||
|
{
|
||||||
|
parcelCapacity = content["parcel"][i].has("capacity");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( content["parcel"][i].has("owner") )
|
||||||
|
{
|
||||||
|
ownerRenderCost = content["parcel"][i]["owner"]["rendering"].asReal();
|
||||||
|
ownerPhysicsCost = content["parcel"][i]["owner"]["physics"].asReal();
|
||||||
|
ownerNetworkCost = content["parcel"][i]["owner"]["streaming"].asReal();
|
||||||
|
ownerSimulationCost = content["parcel"][i]["owner"]["simulation"].asReal();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( content["parcel"][i].has("group") )
|
||||||
|
{
|
||||||
|
groupRenderCost = content["parcel"][i]["group"]["rendering"].asReal();
|
||||||
|
groupPhysicsCost = content["parcel"][i]["group"]["physics"].asReal();
|
||||||
|
groupNetworkCost = content["parcel"][i]["group"]["streaming"].asReal();
|
||||||
|
groupSimulationCost = content["parcel"][i]["group"]["simulation"].asReal();
|
||||||
|
|
||||||
|
}
|
||||||
|
if ( content["parcel"][i].has("other") )
|
||||||
|
{
|
||||||
|
otherRenderCost = content["parcel"][i]["other"]["rendering"].asReal();
|
||||||
|
otherPhysicsCost = content["parcel"][i]["other"]["physics"].asReal();
|
||||||
|
otherNetworkCost = content["parcel"][i]["other"]["streaming"].asReal();
|
||||||
|
otherSimulationCost = content["parcel"][i]["other"]["simulation"].asReal();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( content["parcel"][i].has("temp") )
|
||||||
|
{
|
||||||
|
tempRenderCost = content["parcel"][i]["total"]["rendering"].asReal();
|
||||||
|
tempPhysicsCost = content["parcel"][i]["total"]["physics"].asReal();
|
||||||
|
tempNetworkCost = content["parcel"][i]["total"]["streaming"].asReal();
|
||||||
|
tempSimulationCost = content["parcel"][i]["total"]["simulation"].asReal();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( content["parcel"][i].has("selected") )
|
||||||
|
{
|
||||||
|
selectedRenderCost = content["parcel"][i]["total"]["rendering"].asReal();
|
||||||
|
selectedPhysicsCost = content["parcel"][i]["total"]["physics"].asReal();
|
||||||
|
selectedNetworkCost = content["parcel"][i]["total"]["streaming"].asReal();
|
||||||
|
selectedSimulationCost = content["parcel"][i]["total"]["simulation"].asReal();
|
||||||
|
}
|
||||||
|
|
||||||
|
ParcelQuota parcelQuota( ownerRenderCost, ownerPhysicsCost, ownerNetworkCost, ownerSimulationCost,
|
||||||
|
groupRenderCost, groupPhysicsCost, groupNetworkCost, groupSimulationCost,
|
||||||
|
otherRenderCost, otherPhysicsCost, otherNetworkCost, otherSimulationCost,
|
||||||
|
tempRenderCost, tempPhysicsCost, tempNetworkCost, tempSimulationCost,
|
||||||
|
selectedRenderCost, selectedPhysicsCost, selectedNetworkCost, selectedSimulationCost,
|
||||||
|
parcelCapacity );
|
||||||
|
//Update the Parcel
|
||||||
|
LLParcel* pParcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
|
||||||
|
if ( pParcel )
|
||||||
|
{
|
||||||
|
pParcel->updateQuota( objectID, parcelQuota );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if ( containsSelection )
|
||||||
|
{
|
||||||
|
S32 dataCount = content["selected"].size();
|
||||||
|
for(S32 i = 0; i < dataCount; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
F32 renderCost = 0;
|
||||||
|
F32 physicsCost = 0;
|
||||||
|
F32 networkCost = 0;
|
||||||
|
F32 simulationCost = 0;
|
||||||
|
|
||||||
|
LLUUID objectId;
|
||||||
|
|
||||||
|
objectId = content["selected"][i]["local_id"].asUUID();
|
||||||
|
renderCost = content["selected"][i]["rendering"].asReal();
|
||||||
|
physicsCost = content["selected"][i]["physics"].asReal();
|
||||||
|
networkCost = content["selected"][i]["streaming"].asReal();
|
||||||
|
simulationCost = content["selected"][i]["simulation"].asReal();
|
||||||
|
|
||||||
|
SelectionQuota selectionQuota( objectId, renderCost, physicsCost, networkCost, simulationCost );
|
||||||
|
|
||||||
|
//Update the objects
|
||||||
|
gObjectList.updateQuota( objectId, selectionQuota );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Nothing in string
|
||||||
|
LLAccountingQuotaManager::getInstance()->removePendingObjectQuota( objectID );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//List of posted objects
|
||||||
|
LLSD mObjectIDs;
|
||||||
|
};
|
||||||
|
//===============================================================================
|
||||||
|
void LLAccountingQuotaManager::fetchQuotas( const std::string& url )
|
||||||
|
{
|
||||||
|
// Invoking system must have already determined capability availability
|
||||||
|
if ( !url.empty() )
|
||||||
|
{
|
||||||
|
LLSD objectList;
|
||||||
|
U32 objectIndex = 0;
|
||||||
|
IDIt IDIter = mUpdateObjectQuota.begin();
|
||||||
|
IDIt IDIterEnd = mUpdateObjectQuota.end();
|
||||||
|
|
||||||
|
for ( ; IDIter != IDIterEnd; ++IDIter )
|
||||||
|
{
|
||||||
|
// Check to see if a request for this object has already been made.
|
||||||
|
if ( mPendingObjectQuota.find( *IDIter ) == mPendingObjectQuota.end() )
|
||||||
|
{
|
||||||
|
mPendingObjectQuota.insert( *IDIter );
|
||||||
|
objectList[objectIndex++] = *IDIter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mUpdateObjectQuota.clear();
|
||||||
|
|
||||||
|
//Post results
|
||||||
|
if ( objectList.size() > 0 )
|
||||||
|
{
|
||||||
|
LLSD dataToPost = LLSD::emptyMap();
|
||||||
|
dataToPost["object_ids"] = objectList;
|
||||||
|
LLHTTPClient::post( url, dataToPost, new LLAccountingQuotaResponder( objectList ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//url was empty - warn & continue
|
||||||
|
llwarns<<"Supplied url is empty "<<llendl;
|
||||||
|
mUpdateObjectQuota.clear();
|
||||||
|
mPendingObjectQuota.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//===============================================================================
|
||||||
|
void LLAccountingQuotaManager::updateObjectCost( const LLUUID& objectID )
|
||||||
|
{
|
||||||
|
mUpdateObjectQuota.insert( objectID );
|
||||||
|
}
|
||||||
|
//===============================================================================
|
||||||
|
void LLAccountingQuotaManager::removePendingObjectQuota( const LLUUID& objectID )
|
||||||
|
{
|
||||||
|
mPendingObjectQuota.erase( objectID );
|
||||||
|
}
|
||||||
|
//===============================================================================
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
55
indra/newview/llaccountingquotamanager.h
Normal file
55
indra/newview/llaccountingquotamanager.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* @file lllAccountingQuotaManager.h
|
||||||
|
* @
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||||
|
* Second Life Viewer Source Code
|
||||||
|
* Copyright (C) 2011, 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_ACCOUNTINGQUOTAMANAGER_H
|
||||||
|
#define LL_ACCOUNTINGQUOTAMANAGER_H
|
||||||
|
//===============================================================================
|
||||||
|
#include "llaccountingquota.h"
|
||||||
|
//===============================================================================
|
||||||
|
class LLAccountingQuotaManager : public LLSingleton<LLAccountingQuotaManager>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Ctor
|
||||||
|
LLAccountingQuotaManager();
|
||||||
|
//Store an object that will be eventually fetched
|
||||||
|
void updateObjectCost( const LLUUID& objectID );
|
||||||
|
//Request quotas for object list
|
||||||
|
void fetchQuotas( const std::string& url );
|
||||||
|
//Delete a specific object from the pending list
|
||||||
|
void removePendingObjectQuota( const LLUUID& objectID );
|
||||||
|
|
||||||
|
private:
|
||||||
|
//Set of objects that need to update their cost
|
||||||
|
std::set<LLUUID> mUpdateObjectQuota;
|
||||||
|
//During fetchQuota we move object into a the pending set to signify that
|
||||||
|
//a fetch has been instigated.
|
||||||
|
std::set<LLUUID> mPendingObjectQuota;
|
||||||
|
typedef std::set<LLUUID>::iterator IDIt;
|
||||||
|
};
|
||||||
|
//===============================================================================
|
||||||
|
|
||||||
|
#endif // LLACCOUNTINGQUOTAMANAGER
|
||||||
|
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "llagentaccess.h"
|
#include "llagentaccess.h"
|
||||||
#include "llagentcamera.h"
|
#include "llagentcamera.h"
|
||||||
#include "llagentwearables.h"
|
#include "llagentwearables.h"
|
||||||
|
#include "llagentui.h"
|
||||||
#include "llanimationstates.h"
|
#include "llanimationstates.h"
|
||||||
#include "llcallingcard.h"
|
#include "llcallingcard.h"
|
||||||
#include "llconsole.h"
|
#include "llconsole.h"
|
||||||
@@ -2518,61 +2519,6 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// utility to build a location string
|
|
||||||
void LLAgent::buildLocationString(std::string& str)
|
|
||||||
{
|
|
||||||
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
|
|
||||||
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
|
|
||||||
{
|
|
||||||
str = RlvStrings::getString(RLV_STRING_HIDDEN);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// [/RLVa:KB]
|
|
||||||
|
|
||||||
const LLVector3& agent_pos_region = getPositionAgent();
|
|
||||||
S32 pos_x = S32(agent_pos_region.mV[VX]);
|
|
||||||
S32 pos_y = S32(agent_pos_region.mV[VY]);
|
|
||||||
S32 pos_z = S32(agent_pos_region.mV[VZ]);
|
|
||||||
|
|
||||||
// Round the numbers based on the velocity
|
|
||||||
LLVector3 agent_velocity = getVelocity();
|
|
||||||
F32 velocity_mag_sq = agent_velocity.magVecSquared();
|
|
||||||
|
|
||||||
const F32 FLY_CUTOFF = 6.f; // meters/sec
|
|
||||||
const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
|
|
||||||
const F32 WALK_CUTOFF = 1.5f; // meters/sec
|
|
||||||
const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
|
|
||||||
|
|
||||||
if (velocity_mag_sq > FLY_CUTOFF_SQ)
|
|
||||||
{
|
|
||||||
pos_x -= pos_x % 4;
|
|
||||||
pos_y -= pos_y % 4;
|
|
||||||
}
|
|
||||||
else if (velocity_mag_sq > WALK_CUTOFF_SQ)
|
|
||||||
{
|
|
||||||
pos_x -= pos_x % 2;
|
|
||||||
pos_y -= pos_y % 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a defult name and description for the landmark
|
|
||||||
std::string buffer;
|
|
||||||
if( LLViewerParcelMgr::getInstance()->getAgentParcelName().empty() )
|
|
||||||
{
|
|
||||||
// the parcel doesn't have a name
|
|
||||||
buffer = llformat("%.32s (%d, %d, %d)",
|
|
||||||
getRegion()->getName().c_str(),
|
|
||||||
pos_x, pos_y, pos_z);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// the parcel has a name, so include it in the landmark name
|
|
||||||
buffer = llformat("%.32s, %.32s (%d, %d, %d)",
|
|
||||||
LLViewerParcelMgr::getInstance()->getAgentParcelName().c_str(),
|
|
||||||
getRegion()->getName().c_str(),
|
|
||||||
pos_x, pos_y, pos_z);
|
|
||||||
}
|
|
||||||
str = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLQuaternion LLAgent::getHeadRotation()
|
LLQuaternion LLAgent::getHeadRotation()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -253,7 +253,6 @@ public:
|
|||||||
const LLHost& getRegionHost() const;
|
const LLHost& getRegionHost() const;
|
||||||
BOOL inPrelude();
|
BOOL inPrelude();
|
||||||
std::string getSLURL() const; //Return uri for current region
|
std::string getSLURL() const; //Return uri for current region
|
||||||
void buildLocationString(std::string& str); //Build a description string for current location
|
|
||||||
|
|
||||||
// <edit>
|
// <edit>
|
||||||
struct SHLureRequest
|
struct SHLureRequest
|
||||||
|
|||||||
@@ -573,7 +573,9 @@ BOOL LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance)
|
|||||||
BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars)
|
BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars)
|
||||||
|
|
||||||
if (!mFocusObject || mFocusObject->isDead() ||
|
if (!mFocusObject || mFocusObject->isDead() ||
|
||||||
//mFocusObject->isMesh() ||
|
#if MESH_ENABLED
|
||||||
|
mFocusObject->isMesh() ||
|
||||||
|
#endif //MESH_ENABLED
|
||||||
gSavedSettings.getBOOL("DisableCameraConstraints"))
|
gSavedSettings.getBOOL("DisableCameraConstraints"))
|
||||||
{
|
{
|
||||||
obj_min_distance = 0.f;
|
obj_min_distance = 0.f;
|
||||||
|
|||||||
184
indra/newview/llagentui.cpp
Normal file
184
indra/newview/llagentui.cpp
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/**
|
||||||
|
* @file llagentui.cpp
|
||||||
|
* @brief Utility methods to process agent's data as slurl's etc. before displaying
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2009&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 "llviewerprecompiledheaders.h"
|
||||||
|
|
||||||
|
#include "llagentui.h"
|
||||||
|
|
||||||
|
// Library includes
|
||||||
|
#include "llparcel.h"
|
||||||
|
|
||||||
|
// Viewer includes
|
||||||
|
#include "llagent.h"
|
||||||
|
#include "llviewercontrol.h"
|
||||||
|
#include "llviewerregion.h"
|
||||||
|
#include "llviewerparcelmgr.h"
|
||||||
|
// [RLVa:KB] - Checked: 2010-09-27 (RLVa-1.1.3b)
|
||||||
|
#include "rlvhandler.h"
|
||||||
|
// [/RLVa:KB]
|
||||||
|
|
||||||
|
//static
|
||||||
|
void LLAgentUI::buildFullname(std::string& name)
|
||||||
|
{
|
||||||
|
if (isAgentAvatarValid())
|
||||||
|
name = gAgent.getAvatarObject()->getFullname();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
//static
|
||||||
|
void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /*= true*//*)
|
||||||
|
{
|
||||||
|
LLSLURL return_slurl;
|
||||||
|
LLViewerRegion *regionp = gAgent.getRegion();
|
||||||
|
if (regionp)
|
||||||
|
{
|
||||||
|
return_slurl = LLSLURL(regionp->getName(), gAgent.getPositionGlobal());
|
||||||
|
}
|
||||||
|
slurl = return_slurl;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//static
|
||||||
|
BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius)
|
||||||
|
{
|
||||||
|
F32 delta_x = gAgent.getPositionAgent().mV[VX] - pole.mV[VX];
|
||||||
|
F32 delta_y = gAgent.getPositionAgent().mV[VY] - pole.mV[VY];
|
||||||
|
|
||||||
|
return sqrt( delta_x* delta_x + delta_y* delta_y ) < radius;
|
||||||
|
}
|
||||||
|
BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region)
|
||||||
|
{
|
||||||
|
// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a)
|
||||||
|
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC))
|
||||||
|
{
|
||||||
|
str = RlvStrings::getString(RLV_STRING_HIDDEN);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
// [/RLVa:KB]
|
||||||
|
LLViewerRegion* region = gAgent.getRegion();
|
||||||
|
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
||||||
|
|
||||||
|
if (!region || !parcel) return FALSE;
|
||||||
|
|
||||||
|
S32 pos_x = S32(agent_pos_region.mV[VX]);
|
||||||
|
S32 pos_y = S32(agent_pos_region.mV[VY]);
|
||||||
|
S32 pos_z = S32(agent_pos_region.mV[VZ]);
|
||||||
|
|
||||||
|
// Round the numbers based on the velocity
|
||||||
|
F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();
|
||||||
|
|
||||||
|
const F32 FLY_CUTOFF = 6.f; // meters/sec
|
||||||
|
const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
|
||||||
|
const F32 WALK_CUTOFF = 1.5f; // meters/sec
|
||||||
|
const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
|
||||||
|
|
||||||
|
if (velocity_mag_sq > FLY_CUTOFF_SQ)
|
||||||
|
{
|
||||||
|
pos_x -= pos_x % 4;
|
||||||
|
pos_y -= pos_y % 4;
|
||||||
|
}
|
||||||
|
else if (velocity_mag_sq > WALK_CUTOFF_SQ)
|
||||||
|
{
|
||||||
|
pos_x -= pos_x % 2;
|
||||||
|
pos_y -= pos_y % 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a default name and description for the landmark
|
||||||
|
std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
|
||||||
|
std::string region_name = region->getName();
|
||||||
|
std::string sim_access_string = region->getSimAccessString();
|
||||||
|
std::string buffer;
|
||||||
|
if( parcel_name.empty() )
|
||||||
|
{
|
||||||
|
// the parcel doesn't have a name
|
||||||
|
switch (fmt)
|
||||||
|
{
|
||||||
|
case LOCATION_FORMAT_LANDMARK:
|
||||||
|
buffer = llformat("%.100s", region_name.c_str());
|
||||||
|
break;
|
||||||
|
case LOCATION_FORMAT_NORMAL:
|
||||||
|
buffer = llformat("%s", region_name.c_str());
|
||||||
|
break;
|
||||||
|
case LOCATION_FORMAT_NO_COORDS:
|
||||||
|
buffer = llformat("%s%s%s",
|
||||||
|
region_name.c_str(),
|
||||||
|
sim_access_string.empty() ? "" : " - ",
|
||||||
|
sim_access_string.c_str());
|
||||||
|
break;
|
||||||
|
case LOCATION_FORMAT_NO_MATURITY:
|
||||||
|
buffer = llformat("%s (%d, %d, %d)",
|
||||||
|
region_name.c_str(),
|
||||||
|
pos_x, pos_y, pos_z);
|
||||||
|
break;
|
||||||
|
case LOCATION_FORMAT_FULL:
|
||||||
|
buffer = llformat("%s (%d, %d, %d)%s%s",
|
||||||
|
region_name.c_str(),
|
||||||
|
pos_x, pos_y, pos_z,
|
||||||
|
sim_access_string.empty() ? "" : " - ",
|
||||||
|
sim_access_string.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the parcel has a name, so include it in the landmark name
|
||||||
|
switch (fmt)
|
||||||
|
{
|
||||||
|
case LOCATION_FORMAT_LANDMARK:
|
||||||
|
buffer = llformat("%.100s", parcel_name.c_str());
|
||||||
|
break;
|
||||||
|
case LOCATION_FORMAT_NORMAL:
|
||||||
|
buffer = llformat("%s, %s", parcel_name.c_str(), region_name.c_str());
|
||||||
|
break;
|
||||||
|
case LOCATION_FORMAT_NO_MATURITY:
|
||||||
|
buffer = llformat("%s, %s (%d, %d, %d)",
|
||||||
|
parcel_name.c_str(),
|
||||||
|
region_name.c_str(),
|
||||||
|
pos_x, pos_y, pos_z);
|
||||||
|
break;
|
||||||
|
case LOCATION_FORMAT_NO_COORDS:
|
||||||
|
buffer = llformat("%s, %s%s%s",
|
||||||
|
parcel_name.c_str(),
|
||||||
|
region_name.c_str(),
|
||||||
|
sim_access_string.empty() ? "" : " - ",
|
||||||
|
sim_access_string.c_str());
|
||||||
|
break;
|
||||||
|
case LOCATION_FORMAT_FULL:
|
||||||
|
buffer = llformat("%s, %s (%d, %d, %d)%s%s",
|
||||||
|
parcel_name.c_str(),
|
||||||
|
region_name.c_str(),
|
||||||
|
pos_x, pos_y, pos_z,
|
||||||
|
sim_access_string.empty() ? "" : " - ",
|
||||||
|
sim_access_string.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str = buffer;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt)
|
||||||
|
{
|
||||||
|
return buildLocationString(str,fmt, gAgent.getPositionAgent());
|
||||||
|
}
|
||||||
58
indra/newview/llagentui.h
Normal file
58
indra/newview/llagentui.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* @file llagentui.h
|
||||||
|
* @brief Utility methods to process agent's data as slurl's etc. before displaying
|
||||||
|
*
|
||||||
|
* $LicenseInfo:firstyear=2009&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 LLAGENTUI_H
|
||||||
|
#define LLAGENTUI_H
|
||||||
|
|
||||||
|
class LLSLURL;
|
||||||
|
|
||||||
|
class LLAgentUI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum ELocationFormat
|
||||||
|
{
|
||||||
|
LOCATION_FORMAT_NORMAL, // Parcel
|
||||||
|
LOCATION_FORMAT_LANDMARK, // Parcel, Region
|
||||||
|
LOCATION_FORMAT_NO_MATURITY, // Parcel, Region (x, y, z)
|
||||||
|
LOCATION_FORMAT_NO_COORDS, // Parcel, Region - Maturity
|
||||||
|
LOCATION_FORMAT_FULL, // Parcel, Region (x, y, z) - Maturity
|
||||||
|
};
|
||||||
|
|
||||||
|
static void buildFullname(std::string &name);
|
||||||
|
|
||||||
|
static void buildSLURL(LLSLURL& slurl, const bool escaped = true);
|
||||||
|
//build location string using the current position of gAgent.
|
||||||
|
static BOOL buildLocationString(std::string& str, ELocationFormat fmt = LOCATION_FORMAT_LANDMARK);
|
||||||
|
//build location string using a region position of the avatar.
|
||||||
|
static BOOL buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region);
|
||||||
|
/**
|
||||||
|
* @brief Check whether the agent is in neighborhood of the pole Within same region
|
||||||
|
* @return true if the agent is in neighborhood.
|
||||||
|
*/
|
||||||
|
static BOOL checkAgentDistance(const LLVector3& local_pole, F32 radius);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //LLAGENTUI_H
|
||||||
@@ -52,6 +52,9 @@
|
|||||||
#include "llwindow.h"
|
#include "llwindow.h"
|
||||||
#include "llviewerstats.h"
|
#include "llviewerstats.h"
|
||||||
#include "llmd5.h"
|
#include "llmd5.h"
|
||||||
|
#if MESH_ENABLED
|
||||||
|
#include "llmeshrepository.h"
|
||||||
|
#endif //MESH_ENABLED
|
||||||
#include "llpumpio.h"
|
#include "llpumpio.h"
|
||||||
#include "llimpanel.h"
|
#include "llimpanel.h"
|
||||||
#include "llmimetypes.h"
|
#include "llmimetypes.h"
|
||||||
@@ -1116,6 +1119,9 @@ bool LLAppViewer::mainLoop()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if MESH_ENABLED
|
||||||
|
gMeshRepo.update() ;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
|
if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
|
||||||
(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
|
(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
|
||||||
{
|
{
|
||||||
@@ -1239,6 +1245,11 @@ bool LLAppViewer::cleanup()
|
|||||||
|
|
||||||
llinfos << "Cleaning Up" << llendflush;
|
llinfos << "Cleaning Up" << llendflush;
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
// shut down mesh streamer
|
||||||
|
gMeshRepo.shutdown();
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
// Must clean up texture references before viewer window is destroyed.
|
// Must clean up texture references before viewer window is destroyed.
|
||||||
if(LLHUDManager::instanceExists())
|
if(LLHUDManager::instanceExists())
|
||||||
{
|
{
|
||||||
@@ -1661,6 +1672,11 @@ bool LLAppViewer::initThreads()
|
|||||||
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true);
|
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true);
|
||||||
LLImage::initClass();
|
LLImage::initClass();
|
||||||
|
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
// Mesh streaming and caching
|
||||||
|
gMeshRepo.init();
|
||||||
|
#endif //MESH_ENABLED
|
||||||
// *FIX: no error handling here!
|
// *FIX: no error handling here!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2618,7 +2634,7 @@ void LLAppViewer::handleViewerCrash()
|
|||||||
gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
|
gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
|
||||||
gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
|
gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
|
||||||
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
|
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
|
||||||
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) getCurrentRSS() >> 10;
|
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
|
||||||
gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
|
gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
|
||||||
gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
|
gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
|
||||||
|
|
||||||
|
|||||||
@@ -269,6 +269,9 @@ public:
|
|||||||
REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR,
|
REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR,
|
||||||
REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR,
|
REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR,
|
||||||
REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_VOLUME,
|
REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_VOLUME,
|
||||||
|
#if MESH_ENABLED
|
||||||
|
REBUILD_RIGGED = 0x00008000,
|
||||||
|
#endif //MESH_ENABLED
|
||||||
ON_SHIFT_LIST = 0x00010000,
|
ON_SHIFT_LIST = 0x00010000,
|
||||||
BLOCKER = 0x00020000,
|
BLOCKER = 0x00020000,
|
||||||
ACTIVE = 0x00040000,
|
ACTIVE = 0x00040000,
|
||||||
@@ -280,6 +283,9 @@ public:
|
|||||||
CLEAR_INVISIBLE = 0x01000000, // clear FORCE_INVISIBLE next draw frame
|
CLEAR_INVISIBLE = 0x01000000, // clear FORCE_INVISIBLE next draw frame
|
||||||
REBUILD_SHADOW = 0x02000000,
|
REBUILD_SHADOW = 0x02000000,
|
||||||
HAS_ALPHA = 0x04000000,
|
HAS_ALPHA = 0x04000000,
|
||||||
|
#if MESH_ENABLED
|
||||||
|
RIGGED = 0x08000000,
|
||||||
|
#endif //MESH_ENABLED
|
||||||
PARTITION_MOVE = 0x10000000,
|
PARTITION_MOVE = 0x10000000,
|
||||||
} EDrawableFlags;
|
} EDrawableFlags;
|
||||||
|
|
||||||
|
|||||||
@@ -471,6 +471,8 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
|
|||||||
{
|
{
|
||||||
applyModelMatrix(params);
|
applyModelMatrix(params);
|
||||||
|
|
||||||
|
bool tex_setup = false;
|
||||||
|
|
||||||
if (texture)
|
if (texture)
|
||||||
{
|
{
|
||||||
if (params.mTexture.notNull())
|
if (params.mTexture.notNull())
|
||||||
@@ -479,6 +481,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
|
|||||||
gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
|
gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
|
||||||
if (params.mTextureMatrix)
|
if (params.mTextureMatrix)
|
||||||
{
|
{
|
||||||
|
tex_setup = true;
|
||||||
glMatrixMode(GL_TEXTURE);
|
glMatrixMode(GL_TEXTURE);
|
||||||
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
|
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
|
||||||
gPipeline.mTextureMatrixOps++;
|
gPipeline.mTextureMatrixOps++;
|
||||||
@@ -501,7 +504,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
|
|||||||
gPipeline.addTrianglesDrawn(params.mCount/3);
|
gPipeline.addTrianglesDrawn(params.mCount/3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.mTextureMatrix && texture && params.mTexture.notNull())
|
if (tex_setup)
|
||||||
{
|
{
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|||||||
@@ -324,7 +324,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
|||||||
|
|
||||||
LLRenderPass::applyModelMatrix(params);
|
LLRenderPass::applyModelMatrix(params);
|
||||||
|
|
||||||
{
|
|
||||||
if (params.mFullbright)
|
if (params.mFullbright)
|
||||||
{
|
{
|
||||||
// Turn off lighting if it hasn't already been so.
|
// Turn off lighting if it hasn't already been so.
|
||||||
@@ -394,6 +393,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
|||||||
params.mGroup->rebuildMesh();
|
params.mGroup->rebuildMesh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tex_setup = false;
|
||||||
|
|
||||||
if (params.mTexture.notNull())
|
if (params.mTexture.notNull())
|
||||||
{
|
{
|
||||||
@@ -404,13 +404,13 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
|||||||
}
|
}
|
||||||
if (params.mTextureMatrix)
|
if (params.mTextureMatrix)
|
||||||
{
|
{
|
||||||
|
tex_setup = true;
|
||||||
gGL.getTexUnit(0)->activate();
|
gGL.getTexUnit(0)->activate();
|
||||||
glMatrixMode(GL_TEXTURE);
|
glMatrixMode(GL_TEXTURE);
|
||||||
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
|
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
|
||||||
gPipeline.mTextureMatrixOps++;
|
gPipeline.mTextureMatrixOps++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
params.mVertexBuffer->setBuffer(mask);
|
params.mVertexBuffer->setBuffer(mask);
|
||||||
params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||||
gPipeline.addTrianglesDrawn(params.mCount/3);
|
gPipeline.addTrianglesDrawn(params.mCount/3);
|
||||||
@@ -435,7 +435,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
|||||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.mTextureMatrix && params.mTexture.notNull())
|
if (tex_setup)
|
||||||
{
|
{
|
||||||
gGL.getTexUnit(0)->activate();
|
gGL.getTexUnit(0)->activate();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,12 @@
|
|||||||
#include "lldrawpool.h"
|
#include "lldrawpool.h"
|
||||||
|
|
||||||
class LLVOAvatar;
|
class LLVOAvatar;
|
||||||
|
class LLGLSLShader;
|
||||||
|
class LLFace;
|
||||||
|
class LLMeshSkinInfo;
|
||||||
|
class LLVolume;
|
||||||
|
class LLVolumeFace;
|
||||||
|
|
||||||
|
|
||||||
class LLDrawPoolAvatar : public LLFacePool
|
class LLDrawPoolAvatar : public LLFacePool
|
||||||
{
|
{
|
||||||
@@ -103,6 +109,105 @@ public:
|
|||||||
void endDeferredRigid();
|
void endDeferredRigid();
|
||||||
void endDeferredSkinned();
|
void endDeferredSkinned();
|
||||||
|
|
||||||
|
void beginPostDeferredAlpha();
|
||||||
|
void endPostDeferredAlpha();
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
void beginRiggedSimple();
|
||||||
|
void beginRiggedFullbright();
|
||||||
|
void beginRiggedFullbrightShiny();
|
||||||
|
void beginRiggedShinySimple();
|
||||||
|
void beginRiggedAlpha();
|
||||||
|
void beginRiggedFullbrightAlpha();
|
||||||
|
void beginRiggedGlow();
|
||||||
|
void beginDeferredRiggedAlpha();
|
||||||
|
|
||||||
|
void endRiggedSimple();
|
||||||
|
void endRiggedFullbright();
|
||||||
|
void endRiggedFullbrightShiny();
|
||||||
|
void endRiggedShinySimple();
|
||||||
|
void endRiggedAlpha();
|
||||||
|
void endRiggedFullbrightAlpha();
|
||||||
|
void endRiggedGlow();
|
||||||
|
void endDeferredRiggedAlpha();
|
||||||
|
|
||||||
|
void beginDeferredRiggedSimple();
|
||||||
|
void beginDeferredRiggedBump();
|
||||||
|
|
||||||
|
void endDeferredRiggedSimple();
|
||||||
|
void endDeferredRiggedBump();
|
||||||
|
|
||||||
|
void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
|
||||||
|
LLFace* facep,
|
||||||
|
const LLMeshSkinInfo* skin,
|
||||||
|
LLVolume* volume,
|
||||||
|
const LLVolumeFace& vol_face);
|
||||||
|
|
||||||
|
void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false);
|
||||||
|
void renderRiggedSimple(LLVOAvatar* avatar);
|
||||||
|
void renderRiggedAlpha(LLVOAvatar* avatar);
|
||||||
|
void renderRiggedFullbrightAlpha(LLVOAvatar* avatar);
|
||||||
|
void renderRiggedFullbright(LLVOAvatar* avatar);
|
||||||
|
void renderRiggedShinySimple(LLVOAvatar* avatar);
|
||||||
|
void renderRiggedFullbrightShiny(LLVOAvatar* avatar);
|
||||||
|
void renderRiggedGlow(LLVOAvatar* avatar);
|
||||||
|
void renderDeferredRiggedSimple(LLVOAvatar* avatar);
|
||||||
|
void renderDeferredRiggedBump(LLVOAvatar* avatar);
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RIGGED_SIMPLE = 0,
|
||||||
|
RIGGED_FULLBRIGHT,
|
||||||
|
RIGGED_SHINY,
|
||||||
|
RIGGED_FULLBRIGHT_SHINY,
|
||||||
|
RIGGED_GLOW,
|
||||||
|
RIGGED_ALPHA,
|
||||||
|
RIGGED_FULLBRIGHT_ALPHA,
|
||||||
|
RIGGED_DEFERRED_BUMP,
|
||||||
|
RIGGED_DEFERRED_SIMPLE,
|
||||||
|
NUM_RIGGED_PASSES,
|
||||||
|
RIGGED_UNKNOWN,
|
||||||
|
} eRiggedPass;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
RIGGED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX |
|
||||||
|
LLVertexBuffer::MAP_NORMAL |
|
||||||
|
LLVertexBuffer::MAP_TEXCOORD0 |
|
||||||
|
LLVertexBuffer::MAP_COLOR |
|
||||||
|
LLVertexBuffer::MAP_WEIGHT4,
|
||||||
|
RIGGED_FULLBRIGHT_MASK = LLVertexBuffer::MAP_VERTEX |
|
||||||
|
LLVertexBuffer::MAP_TEXCOORD0 |
|
||||||
|
LLVertexBuffer::MAP_COLOR |
|
||||||
|
LLVertexBuffer::MAP_WEIGHT4,
|
||||||
|
RIGGED_SHINY_MASK = RIGGED_SIMPLE_MASK,
|
||||||
|
RIGGED_FULLBRIGHT_SHINY_MASK = RIGGED_SIMPLE_MASK,
|
||||||
|
RIGGED_GLOW_MASK = LLVertexBuffer::MAP_VERTEX |
|
||||||
|
LLVertexBuffer::MAP_TEXCOORD0 |
|
||||||
|
LLVertexBuffer::MAP_WEIGHT4,
|
||||||
|
RIGGED_ALPHA_MASK = RIGGED_SIMPLE_MASK,
|
||||||
|
RIGGED_FULLBRIGHT_ALPHA_MASK = RIGGED_FULLBRIGHT_MASK,
|
||||||
|
RIGGED_DEFERRED_BUMP_MASK = LLVertexBuffer::MAP_VERTEX |
|
||||||
|
LLVertexBuffer::MAP_NORMAL |
|
||||||
|
LLVertexBuffer::MAP_TEXCOORD0 |
|
||||||
|
LLVertexBuffer::MAP_BINORMAL |
|
||||||
|
LLVertexBuffer::MAP_COLOR |
|
||||||
|
LLVertexBuffer::MAP_WEIGHT4,
|
||||||
|
RIGGED_DEFERRED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX |
|
||||||
|
LLVertexBuffer::MAP_NORMAL |
|
||||||
|
LLVertexBuffer::MAP_TEXCOORD0 |
|
||||||
|
LLVertexBuffer::MAP_COLOR |
|
||||||
|
LLVertexBuffer::MAP_WEIGHT4,
|
||||||
|
} eRiggedDataMask;
|
||||||
|
|
||||||
|
void addRiggedFace(LLFace* facep, U32 type);
|
||||||
|
void removeRiggedFace(LLFace* facep);
|
||||||
|
|
||||||
|
std::vector<LLFace*> mRiggedFace[NUM_RIGGED_PASSES];
|
||||||
|
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
/*virtual*/ LLViewerTexture *getDebugTexture();
|
/*virtual*/ LLViewerTexture *getDebugTexture();
|
||||||
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
|
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
|
||||||
|
|
||||||
@@ -110,6 +215,9 @@ public:
|
|||||||
|
|
||||||
static BOOL sSkipOpaque;
|
static BOOL sSkipOpaque;
|
||||||
static BOOL sSkipTransparent;
|
static BOOL sSkipTransparent;
|
||||||
|
static S32 sDiffuseChannel;
|
||||||
|
|
||||||
|
static LLGLSLShader* sVertexProgram;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LLVertexBufferAvatar : public LLVertexBuffer
|
class LLVertexBufferAvatar : public LLVertexBuffer
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ void LLDrawPoolSky::prerender()
|
|||||||
void LLDrawPoolSky::render(S32 pass)
|
void LLDrawPoolSky::render(S32 pass)
|
||||||
{
|
{
|
||||||
gGL.flush();
|
gGL.flush();
|
||||||
|
|
||||||
if (mDrawFace.empty())
|
if (mDrawFace.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -222,6 +222,8 @@ void LLDrawPoolTerrain::render(S32 pass)
|
|||||||
sShader->unbind();
|
sShader->unbind();
|
||||||
sShader = &gObjectFullbrightProgram;
|
sShader = &gObjectFullbrightProgram;
|
||||||
sShader->bind();
|
sShader->bind();
|
||||||
|
LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glPolygonOffset(-1.0f, -1.0f);
|
||||||
renderOwnership();
|
renderOwnership();
|
||||||
sShader = old_shader;
|
sShader = old_shader;
|
||||||
sShader->bind();
|
sShader->bind();
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include "llmatrix4a.h"
|
#include "llmatrix4a.h"
|
||||||
#include "v3color.h"
|
#include "v3color.h"
|
||||||
|
|
||||||
|
#include "lldrawpoolavatar.h"
|
||||||
#include "lldrawpoolbump.h"
|
#include "lldrawpoolbump.h"
|
||||||
#include "llgl.h"
|
#include "llgl.h"
|
||||||
#include "llrender.h"
|
#include "llrender.h"
|
||||||
@@ -153,6 +154,9 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
|
|||||||
{
|
{
|
||||||
mLastUpdateTime = gFrameTimeSeconds;
|
mLastUpdateTime = gFrameTimeSeconds;
|
||||||
mLastMoveTime = 0.f;
|
mLastMoveTime = 0.f;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
mLastSkinTime = gFrameTimeSeconds;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
mVSize = 0.f;
|
mVSize = 0.f;
|
||||||
mPixelArea = 16.f;
|
mPixelArea = 16.f;
|
||||||
mState = GLOBAL;
|
mState = GLOBAL;
|
||||||
@@ -205,7 +209,17 @@ void LLFace::destroy()
|
|||||||
|
|
||||||
if (mDrawPoolp)
|
if (mDrawPoolp)
|
||||||
{
|
{
|
||||||
mDrawPoolp->removeFace(this);
|
#if MESH_ENABLED
|
||||||
|
if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR)
|
||||||
|
{
|
||||||
|
((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
{
|
||||||
|
mDrawPoolp->removeFace(this);
|
||||||
|
}
|
||||||
|
|
||||||
mDrawPoolp = NULL;
|
mDrawPoolp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,6 +381,24 @@ void LLFace::setSize(S32 num_vertices, const S32 num_indices, bool align)
|
|||||||
llassert(verify());
|
llassert(verify());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LLFace::setGeomIndex(U16 idx)
|
||||||
|
{
|
||||||
|
if (mGeomIndex != idx)
|
||||||
|
{
|
||||||
|
mGeomIndex = idx;
|
||||||
|
mVertexBuffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLFace::setIndicesIndex(S32 idx)
|
||||||
|
{
|
||||||
|
if (mIndicesIndex != idx)
|
||||||
|
{
|
||||||
|
mIndicesIndex = idx;
|
||||||
|
mVertexBuffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
U16 LLFace::getGeometryAvatar(
|
U16 LLFace::getGeometryAvatar(
|
||||||
@@ -532,11 +564,40 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
|
|||||||
}
|
}
|
||||||
|
|
||||||
glColor4fv(color.mV);
|
glColor4fv(color.mV);
|
||||||
mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
|
#if MESH_ENABLED
|
||||||
#if !LL_RELEASE_FOR_DOWNLOAD
|
if (mDrawablep->isState(LLDrawable::RIGGED))
|
||||||
LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
|
{
|
||||||
#endif
|
LLVOVolume* volume = mDrawablep->getVOVolume();
|
||||||
mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
|
if (volume)
|
||||||
|
{
|
||||||
|
LLRiggedVolume* rigged = volume->getRiggedVolume();
|
||||||
|
if (rigged)
|
||||||
|
{
|
||||||
|
LLGLEnable offset(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glPolygonOffset(-1.f, -1.f);
|
||||||
|
glMultMatrixf((F32*) volume->getRelativeXform().mMatrix);
|
||||||
|
const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset());
|
||||||
|
LLVertexBuffer::unbind();
|
||||||
|
glVertexPointer(3, GL_FLOAT, 16, vol_face.mPositions);
|
||||||
|
if (vol_face.mTexCoords)
|
||||||
|
{
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords);
|
||||||
|
}
|
||||||
|
glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
{
|
||||||
|
mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
|
||||||
|
#if !LL_RELEASE_FOR_DOWNLOAD
|
||||||
|
LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
|
||||||
|
#endif
|
||||||
|
mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
|
||||||
|
}
|
||||||
|
|
||||||
gGL.popMatrix();
|
gGL.popMatrix();
|
||||||
}
|
}
|
||||||
@@ -715,7 +776,11 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
|
|||||||
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
|
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
|
||||||
|
|
||||||
//get bounding box
|
//get bounding box
|
||||||
if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
|
if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION
|
||||||
|
#if MESH_ENABLED
|
||||||
|
| LLDrawable::REBUILD_RIGGED
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
))
|
||||||
{
|
{
|
||||||
//VECTORIZE THIS
|
//VECTORIZE THIS
|
||||||
LLMatrix4a mat_vert;
|
LLMatrix4a mat_vert;
|
||||||
@@ -924,10 +989,8 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po
|
|||||||
{
|
{
|
||||||
const LLMatrix4& vol_mat = getWorldMatrix();
|
const LLMatrix4& vol_mat = getWorldMatrix();
|
||||||
const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
|
const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
|
||||||
LLVector4a normal4a;
|
const LLVector4a& normal4a = vf.mNormals[0];
|
||||||
normal4a.load3(vf.mVertices[0].mNormal.mV);
|
const LLVector4a& binormal4a = vf.mBinormals[0];
|
||||||
LLVector4a binormal4a;
|
|
||||||
binormal4a.load3(vf.mVertices[0].mBinormal.mV);
|
|
||||||
LLVector2 projected_binormal;
|
LLVector2 projected_binormal;
|
||||||
planarProjection(projected_binormal, normal4a, *vf.mCenter, binormal4a);
|
planarProjection(projected_binormal, normal4a, *vf.mCenter, binormal4a);
|
||||||
projected_binormal -= LLVector2(0.5f, 0.5f); // this normally happens in xform()
|
projected_binormal -= LLVector2(0.5f, 0.5f); // this normally happens in xform()
|
||||||
@@ -1041,14 +1104,14 @@ bool LLFace::canRenderAsMask()
|
|||||||
|
|
||||||
BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
||||||
const S32 &f,
|
const S32 &f,
|
||||||
const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
|
const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in,
|
||||||
const U16 &index_offset,
|
const U16 &index_offset,
|
||||||
bool force_rebuild)
|
bool force_rebuild)
|
||||||
{
|
{
|
||||||
llassert(verify());
|
llassert(verify());
|
||||||
const LLVolumeFace &vf = volume.getVolumeFace(f);
|
const LLVolumeFace &vf = volume.getVolumeFace(f);
|
||||||
S32 num_vertices = (S32)vf.mVertices.size();
|
S32 num_vertices = (S32)vf.mNumVertices;
|
||||||
S32 num_indices = (S32)vf.mIndices.size();
|
S32 num_indices = (S32) vf.mNumIndices;
|
||||||
|
|
||||||
if (mVertexBuffer.notNull())
|
if (mVertexBuffer.notNull())
|
||||||
{
|
{
|
||||||
@@ -1080,8 +1143,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||||||
LLStrider<LLColor4U> colors;
|
LLStrider<LLColor4U> colors;
|
||||||
LLStrider<LLVector3> binormals;
|
LLStrider<LLVector3> binormals;
|
||||||
LLStrider<U16> indicesp;
|
LLStrider<U16> indicesp;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
LLStrider<LLVector4> weights;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
|
BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
|
||||||
|
|
||||||
BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();
|
BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();
|
||||||
LLVector3 scale;
|
LLVector3 scale;
|
||||||
@@ -1094,43 +1160,20 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||||||
scale = mVObjp->getScale();
|
scale = mVObjp->getScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION);
|
bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION);
|
||||||
BOOL rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR);
|
bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR);
|
||||||
BOOL rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);
|
bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);
|
||||||
BOOL rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
|
bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
|
||||||
BOOL rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL);
|
bool rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL);
|
||||||
|
#if MESH_ENABLED
|
||||||
|
bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
const LLTextureEntry *tep = mVObjp->getTE(f);
|
const LLTextureEntry *tep = mVObjp->getTE(f);
|
||||||
if (!tep) rebuild_color = FALSE; // can't get color when tep is NULL
|
if (!tep) rebuild_color = FALSE; // can't get color when tep is NULL
|
||||||
U8 bump_code = tep ? tep->getBumpmap() : 0;
|
U8 bump_code = tep ? tep->getBumpmap() : 0;
|
||||||
|
|
||||||
if (rebuild_pos)
|
|
||||||
{
|
|
||||||
mVertexBuffer->getVertexStrider(vertices, mGeomIndex);
|
|
||||||
}
|
|
||||||
if (rebuild_normal)
|
|
||||||
{
|
|
||||||
mVertexBuffer->getNormalStrider(normals, mGeomIndex);
|
|
||||||
}
|
|
||||||
if (rebuild_binormal)
|
|
||||||
{
|
|
||||||
mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rebuild_tcoord)
|
|
||||||
{
|
|
||||||
mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
|
|
||||||
if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
|
|
||||||
{
|
|
||||||
mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rebuild_color)
|
|
||||||
{
|
|
||||||
mVertexBuffer->getColorStrider(colors, mGeomIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0;
|
|
||||||
|
|
||||||
BOOL is_static = mDrawablep->isStatic();
|
BOOL is_static = mDrawablep->isStatic();
|
||||||
BOOL is_global = is_static;
|
BOOL is_global = is_static;
|
||||||
@@ -1146,59 +1189,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||||||
clearState(GLOBAL);
|
clearState(GLOBAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVector2 tmin, tmax;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (rebuild_tcoord)
|
|
||||||
{
|
|
||||||
if (tep)
|
|
||||||
{
|
|
||||||
r = tep->getRotation();
|
|
||||||
os = tep->mOffsetS;
|
|
||||||
ot = tep->mOffsetT;
|
|
||||||
ms = tep->mScaleS;
|
|
||||||
mt = tep->mScaleT;
|
|
||||||
cos_ang = cos(r);
|
|
||||||
sin_ang = sin(r);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cos_ang = 1.0f;
|
|
||||||
sin_ang = 0.0f;
|
|
||||||
os = 0.0f;
|
|
||||||
ot = 0.0f;
|
|
||||||
ms = 1.0f;
|
|
||||||
mt = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
U8 tex_mode = 0;
|
|
||||||
|
|
||||||
if (isState(TEXTURE_ANIM))
|
|
||||||
{
|
|
||||||
LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;
|
|
||||||
tex_mode = vobj->mTexAnimMode;
|
|
||||||
|
|
||||||
if (!tex_mode)
|
|
||||||
{
|
|
||||||
clearState(TEXTURE_ANIM);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
os = ot = 0.f;
|
|
||||||
r = 0.f;
|
|
||||||
cos_ang = 1.f;
|
|
||||||
sin_ang = 0.f;
|
|
||||||
ms = mt = 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getVirtualSize() >= MIN_TEX_ANIM_SIZE)
|
|
||||||
{ //don't override texture transform during tc bake
|
|
||||||
tex_mode = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LLColor4U color = (tep ? LLColor4U(tep->getColor()) : LLColor4U::white);
|
LLColor4U color = (tep ? LLColor4U(tep->getColor()) : LLColor4U::white);
|
||||||
|
|
||||||
if (rebuild_color) // FALSE if tep == NULL
|
if (rebuild_color) // FALSE if tep == NULL
|
||||||
@@ -1226,168 +1216,396 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
|||||||
mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
|
mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
|
||||||
for (U32 i = 0; i < (U32) num_indices; i++)
|
for (U32 i = 0; i < (U32) num_indices; i++)
|
||||||
{
|
{
|
||||||
*indicesp++ = vf.mIndices[i] + index_offset;
|
indicesp[i] = vf.mIndices[i] + index_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//mVertexBuffer->setBuffer(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LLMatrix4a mat_normal;
|
||||||
|
mat_normal.loadu(mat_norm_in);
|
||||||
|
|
||||||
//bump setup
|
//if it's not fullbright and has no normals, bake sunlight based on face normal
|
||||||
LLVector3 binormal_dir( -sin_ang, cos_ang, 0 );
|
//bool bake_sunlight = !getTextureEntry()->getFullbright() &&
|
||||||
LLVector3 bump_s_primary_light_ray;
|
// !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
|
||||||
LLVector3 bump_t_primary_light_ray;
|
|
||||||
|
|
||||||
LLQuaternion bump_quat;
|
F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0;
|
||||||
if (mDrawablep->isActive())
|
|
||||||
|
if (rebuild_tcoord)
|
||||||
{
|
{
|
||||||
bump_quat = LLQuaternion(mDrawablep->getRenderMatrix());
|
bool do_xform;
|
||||||
}
|
|
||||||
|
|
||||||
if (bump_code)
|
if (tep)
|
||||||
{
|
|
||||||
mVObjp->getVolume()->genBinormals(f);
|
|
||||||
F32 offset_multiple;
|
|
||||||
switch( bump_code )
|
|
||||||
{
|
{
|
||||||
case BE_NO_BUMP:
|
r = tep->getRotation();
|
||||||
offset_multiple = 0.f;
|
os = tep->mOffsetS;
|
||||||
break;
|
ot = tep->mOffsetT;
|
||||||
case BE_BRIGHTNESS:
|
ms = tep->mScaleS;
|
||||||
case BE_DARKNESS:
|
mt = tep->mScaleT;
|
||||||
if( mTexture.notNull() && mTexture->hasGLTexture())
|
cos_ang = cos(r);
|
||||||
|
sin_ang = sin(r);
|
||||||
|
|
||||||
|
if (cos_ang != 1.f ||
|
||||||
|
sin_ang != 0.f ||
|
||||||
|
os != 0.f ||
|
||||||
|
ot != 0.f ||
|
||||||
|
ms != 1.f ||
|
||||||
|
mt != 1.f)
|
||||||
{
|
{
|
||||||
// Offset by approximately one texel
|
do_xform = true;
|
||||||
S32 cur_discard = mTexture->getDiscardLevel();
|
|
||||||
S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() );
|
|
||||||
max_size <<= cur_discard;
|
|
||||||
const F32 ARTIFICIAL_OFFSET = 2.f;
|
|
||||||
offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offset_multiple = 1.f/256;
|
do_xform = false;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
else
|
||||||
default: // Standard bumpmap textures. Assumed to be 256x256
|
{
|
||||||
offset_multiple = 1.f / 256;
|
do_xform = false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
F32 s_scale = 1.f;
|
//bump setup
|
||||||
F32 t_scale = 1.f;
|
LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f );
|
||||||
if( tep )
|
LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f);
|
||||||
|
LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f);
|
||||||
|
|
||||||
|
LLQuaternion bump_quat;
|
||||||
|
if (mDrawablep->isActive())
|
||||||
{
|
{
|
||||||
tep->getScale( &s_scale, &t_scale );
|
bump_quat = LLQuaternion(mDrawablep->getRenderMatrix());
|
||||||
}
|
}
|
||||||
// Use the nudged south when coming from above sun angle, such
|
|
||||||
// that emboss mapping always shows up on the upward faces of cubes when
|
|
||||||
// it's noon (since a lot of builders build with the sun forced to noon).
|
|
||||||
LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir;
|
|
||||||
LLVector3 moon_ray = gSky.getMoonDirection();
|
|
||||||
LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray;
|
|
||||||
|
|
||||||
bump_s_primary_light_ray = offset_multiple * s_scale * primary_light_ray;
|
if (bump_code)
|
||||||
bump_t_primary_light_ray = offset_multiple * t_scale * primary_light_ray;
|
|
||||||
}
|
|
||||||
|
|
||||||
U8 texgen = getTextureEntry()->getTexGen();
|
|
||||||
if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT)
|
|
||||||
{ //planar texgen needs binormals
|
|
||||||
mVObjp->getVolume()->genBinormals(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVector4a scalea;
|
|
||||||
scalea.load3(scale.mV);
|
|
||||||
|
|
||||||
for (S32 i = 0; i < num_vertices; i++)
|
|
||||||
{
|
|
||||||
if (rebuild_tcoord)
|
|
||||||
{
|
{
|
||||||
LLVector2 tc = vf.mVertices[i].mTexCoord;
|
mVObjp->getVolume()->genBinormals(f);
|
||||||
|
F32 offset_multiple;
|
||||||
if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
|
switch( bump_code )
|
||||||
{
|
{
|
||||||
LLVector4a vec;
|
case BE_NO_BUMP:
|
||||||
vec.load3(vf.mVertices[i].mPosition.mV);
|
offset_multiple = 0.f;
|
||||||
vec.mul(scalea);
|
break;
|
||||||
LLVector4a norm;
|
case BE_BRIGHTNESS:
|
||||||
norm.load3(vf.mVertices[i].mNormal.mV);
|
case BE_DARKNESS:
|
||||||
|
if( mTexture.notNull() && mTexture->hasGLTexture())
|
||||||
switch (texgen)
|
|
||||||
{
|
{
|
||||||
case LLTextureEntry::TEX_GEN_PLANAR:
|
// Offset by approximately one texel
|
||||||
planarProjection(tc, norm, *(vf.mCenter), vec);
|
S32 cur_discard = mTexture->getDiscardLevel();
|
||||||
break;
|
S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() );
|
||||||
case LLTextureEntry::TEX_GEN_SPHERICAL:
|
max_size <<= cur_discard;
|
||||||
sphericalProjection(tc, norm, *(vf.mCenter), vec);
|
const F32 ARTIFICIAL_OFFSET = 2.f;
|
||||||
break;
|
offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size;
|
||||||
case LLTextureEntry::TEX_GEN_CYLINDRICAL:
|
|
||||||
cylindricalProjection(tc, norm, *(vf.mCenter), vec);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset_multiple = 1.f/256;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // Standard bumpmap textures. Assumed to be 256x256
|
||||||
|
offset_multiple = 1.f / 256;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tex_mode && mTextureMatrix)
|
F32 s_scale = 1.f;
|
||||||
|
F32 t_scale = 1.f;
|
||||||
|
if( tep )
|
||||||
{
|
{
|
||||||
LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
|
tep->getScale( &s_scale, &t_scale );
|
||||||
tmp = tmp * *mTextureMatrix;
|
}
|
||||||
tc.mV[0] = tmp.mV[0];
|
// Use the nudged south when coming from above sun angle, such
|
||||||
tc.mV[1] = tmp.mV[1];
|
// that emboss mapping always shows up on the upward faces of cubes when
|
||||||
|
// it's noon (since a lot of builders build with the sun forced to noon).
|
||||||
|
LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir;
|
||||||
|
LLVector3 moon_ray = gSky.getMoonDirection();
|
||||||
|
LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray;
|
||||||
|
|
||||||
|
bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV);
|
||||||
|
bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV);
|
||||||
|
}
|
||||||
|
|
||||||
|
U8 texgen = getTextureEntry()->getTexGen();
|
||||||
|
if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT)
|
||||||
|
{ //planar texgen needs binormals
|
||||||
|
mVObjp->getVolume()->genBinormals(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
U8 tex_mode = 0;
|
||||||
|
|
||||||
|
if (isState(TEXTURE_ANIM))
|
||||||
|
{
|
||||||
|
LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp;
|
||||||
|
tex_mode = vobj->mTexAnimMode;
|
||||||
|
|
||||||
|
if (!tex_mode)
|
||||||
|
{
|
||||||
|
clearState(TEXTURE_ANIM);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
|
os = ot = 0.f;
|
||||||
|
r = 0.f;
|
||||||
|
cos_ang = 1.f;
|
||||||
|
sin_ang = 0.f;
|
||||||
|
ms = mt = 1.f;
|
||||||
|
|
||||||
|
do_xform = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*tex_coords++ = tc;
|
if (getVirtualSize() >= MIN_TEX_ANIM_SIZE)
|
||||||
|
{ //don't override texture transform during tc bake
|
||||||
|
tex_mode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
|
LLVector4a scalea;
|
||||||
|
scalea.load3(scale.mV);
|
||||||
|
|
||||||
|
bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
|
||||||
|
bool do_tex_mat = tex_mode && mTextureMatrix;
|
||||||
|
|
||||||
|
if (!do_bump)
|
||||||
|
{ //not in atlas or not bump mapped, might be able to do a cheap update
|
||||||
|
mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
|
||||||
|
|
||||||
|
if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
|
||||||
{
|
{
|
||||||
LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal;
|
if (!do_tex_mat)
|
||||||
|
|
||||||
LLMatrix3 tangent_to_object;
|
|
||||||
tangent_to_object.setRows(tangent, vf.mVertices[i].mBinormal, vf.mVertices[i].mNormal);
|
|
||||||
LLVector3 binormal = binormal_dir * tangent_to_object;
|
|
||||||
binormal = binormal * mat_normal;
|
|
||||||
|
|
||||||
if (mDrawablep->isActive())
|
|
||||||
{
|
{
|
||||||
binormal *= bump_quat;
|
/*if (!do_xform)
|
||||||
|
{
|
||||||
|
LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, num_vertices*2*sizeof(F32));
|
||||||
|
}
|
||||||
|
else*/
|
||||||
|
{
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
LLVector2 tc(vf.mTexCoords[i]);
|
||||||
|
if(do_xform)
|
||||||
|
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
|
||||||
|
*tex_coords++ = tc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //do tex mat, no texgen, no atlas, no bump
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
LLVector2 tc(vf.mTexCoords[i]);
|
||||||
|
//LLVector4a& norm = vf.mNormals[i];
|
||||||
|
//LLVector4a& center = *(vf.mCenter);
|
||||||
|
|
||||||
|
LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
|
||||||
|
tmp = tmp * *mTextureMatrix;
|
||||||
|
tc.mV[0] = tmp.mV[0];
|
||||||
|
tc.mV[1] = tmp.mV[1];
|
||||||
|
*tex_coords++ = tc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //no bump, no atlas, tex gen planar
|
||||||
|
if (do_tex_mat)
|
||||||
|
{
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
LLVector2 tc(vf.mTexCoords[i]);
|
||||||
|
LLVector4a& norm = vf.mNormals[i];
|
||||||
|
LLVector4a& center = *(vf.mCenter);
|
||||||
|
LLVector4a vec = vf.mPositions[i];
|
||||||
|
vec.mul(scalea);
|
||||||
|
planarProjection(tc, norm, center, vec);
|
||||||
|
|
||||||
|
LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
|
||||||
|
tmp = tmp * *mTextureMatrix;
|
||||||
|
tc.mV[0] = tmp.mV[0];
|
||||||
|
tc.mV[1] = tmp.mV[1];
|
||||||
|
|
||||||
|
*tex_coords++ = tc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
LLVector2 tc(vf.mTexCoords[i]);
|
||||||
|
LLVector4a& norm = vf.mNormals[i];
|
||||||
|
LLVector4a& center = *(vf.mCenter);
|
||||||
|
LLVector4a vec = vf.mPositions[i];
|
||||||
|
vec.mul(scalea);
|
||||||
|
planarProjection(tc, norm, center, vec);
|
||||||
|
|
||||||
|
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
|
||||||
|
|
||||||
|
*tex_coords++ = tc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mVertexBuffer->setBuffer(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ //either bump mapped or in atlas, just do the whole expensive loop
|
||||||
|
mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex);
|
||||||
|
|
||||||
|
std::vector<LLVector2> bump_tc;
|
||||||
|
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
LLVector2 tc(vf.mTexCoords[i]);
|
||||||
|
|
||||||
|
LLVector4a& norm = vf.mNormals[i];
|
||||||
|
|
||||||
|
LLVector4a& center = *(vf.mCenter);
|
||||||
|
|
||||||
|
if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
|
||||||
|
{
|
||||||
|
LLVector4a vec = vf.mPositions[i];
|
||||||
|
|
||||||
|
vec.mul(scalea);
|
||||||
|
|
||||||
|
switch (texgen)
|
||||||
|
{
|
||||||
|
case LLTextureEntry::TEX_GEN_PLANAR:
|
||||||
|
planarProjection(tc, norm, center, vec);
|
||||||
|
break;
|
||||||
|
case LLTextureEntry::TEX_GEN_SPHERICAL:
|
||||||
|
sphericalProjection(tc, norm, center, vec);
|
||||||
|
break;
|
||||||
|
case LLTextureEntry::TEX_GEN_CYLINDRICAL:
|
||||||
|
cylindricalProjection(tc, norm, center, vec);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binormal.normVec();
|
if (tex_mode && mTextureMatrix)
|
||||||
tc += LLVector2( bump_s_primary_light_ray * tangent, bump_t_primary_light_ray * binormal );
|
{
|
||||||
|
LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
|
||||||
|
tmp = tmp * *mTextureMatrix;
|
||||||
|
tc.mV[0] = tmp.mV[0];
|
||||||
|
tc.mV[1] = tmp.mV[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
|
||||||
|
}
|
||||||
|
|
||||||
*tex_coords2++ = tc;
|
|
||||||
|
*tex_coords++ = tc;
|
||||||
|
if (do_bump)
|
||||||
|
{
|
||||||
|
bump_tc.push_back(tc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//mVertexBuffer->setBuffer(0);
|
||||||
|
|
||||||
|
|
||||||
|
if (do_bump)
|
||||||
|
{
|
||||||
|
mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex);
|
||||||
|
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
LLVector4a tangent;
|
||||||
|
tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]);
|
||||||
|
|
||||||
|
LLMatrix4a tangent_to_object;
|
||||||
|
tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]);
|
||||||
|
LLVector4a t;
|
||||||
|
tangent_to_object.rotate(binormal_dir, t);
|
||||||
|
LLVector4a binormal;
|
||||||
|
mat_normal.rotate(t, binormal);
|
||||||
|
|
||||||
|
//VECTORIZE THIS
|
||||||
|
if (mDrawablep->isActive())
|
||||||
|
{
|
||||||
|
LLVector3 t;
|
||||||
|
t.set(binormal.getF32ptr());
|
||||||
|
t *= bump_quat;
|
||||||
|
binormal.load3(t.mV);
|
||||||
|
}
|
||||||
|
|
||||||
|
binormal.normalize3fast();
|
||||||
|
LLVector2 tc = bump_tc[i];
|
||||||
|
tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
|
||||||
|
|
||||||
|
*tex_coords2++ = tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//mVertexBuffer->setBuffer(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (rebuild_pos)
|
if (rebuild_pos)
|
||||||
|
{
|
||||||
|
mVertexBuffer->getVertexStrider(vertices, mGeomIndex);
|
||||||
|
LLMatrix4a mat_vert;
|
||||||
|
mat_vert.loadu(mat_vert_in);
|
||||||
|
|
||||||
|
LLVector4a* src = vf.mPositions;
|
||||||
|
LLVector4a position;
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
{
|
{
|
||||||
*vertices++ = vf.mVertices[i].mPosition * mat_vert;
|
mat_vert.affineTransform(src[i], position);
|
||||||
|
vertices[i].set(position.getF32ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebuild_normal)
|
|
||||||
{
|
|
||||||
LLVector3 normal = vf.mVertices[i].mNormal * mat_normal;
|
|
||||||
normal.normVec();
|
|
||||||
|
|
||||||
*normals++ = normal;
|
//mVertexBuffer->setBuffer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rebuild_normal)
|
||||||
|
{
|
||||||
|
mVertexBuffer->getNormalStrider(normals, mGeomIndex);
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
LLVector4a normal;
|
||||||
|
mat_normal.rotate(vf.mNormals[i], normal);
|
||||||
|
normal.normalize3fast();
|
||||||
|
normals[i].set(normal.getF32ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebuild_binormal)
|
//mVertexBuffer->setBuffer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rebuild_binormal)
|
||||||
|
{
|
||||||
|
mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
{
|
{
|
||||||
LLVector3 binormal = vf.mVertices[i].mBinormal * mat_normal;
|
LLVector4a binormal;
|
||||||
binormal.normVec();
|
mat_normal.rotate(vf.mBinormals[i], binormal);
|
||||||
*binormals++ = binormal;
|
binormal.normalize3fast();
|
||||||
|
binormals[i].set(binormal.getF32ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebuild_color)
|
//mVertexBuffer->setBuffer(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
if (rebuild_weights && vf.mWeights)
|
||||||
|
{
|
||||||
|
mVertexBuffer->getWeight4Strider(weights, mGeomIndex);
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
{
|
{
|
||||||
*colors++ = color;
|
weights[i].set(vf.mWeights[i].getF32ptr());
|
||||||
}
|
}
|
||||||
|
//mVertexBuffer->setBuffer(0);
|
||||||
|
}
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
|
if (rebuild_color)
|
||||||
|
{
|
||||||
|
mVertexBuffer->getColorStrider(colors, mGeomIndex);
|
||||||
|
for (S32 i = 0; i < num_vertices; i++)
|
||||||
|
{
|
||||||
|
colors[i] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
//mVertexBuffer->setBuffer(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebuild_tcoord)
|
if (rebuild_tcoord)
|
||||||
@@ -1802,3 +2020,68 @@ void LLFace::clearVertexBuffer()
|
|||||||
mLastVertexBuffer = NULL;
|
mLastVertexBuffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
//static
|
||||||
|
U32 LLFace::getRiggedDataMask(U32 type)
|
||||||
|
{
|
||||||
|
static const U32 rigged_data_mask[] = {
|
||||||
|
LLDrawPoolAvatar::RIGGED_SIMPLE_MASK,
|
||||||
|
LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK,
|
||||||
|
LLDrawPoolAvatar::RIGGED_SHINY_MASK,
|
||||||
|
LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK,
|
||||||
|
LLDrawPoolAvatar::RIGGED_GLOW_MASK,
|
||||||
|
LLDrawPoolAvatar::RIGGED_ALPHA_MASK,
|
||||||
|
LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK,
|
||||||
|
LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK,
|
||||||
|
LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK,
|
||||||
|
};
|
||||||
|
|
||||||
|
llassert(type < sizeof(rigged_data_mask)/sizeof(U32));
|
||||||
|
|
||||||
|
return rigged_data_mask[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
U32 LLFace::getRiggedVertexBufferDataMask() const
|
||||||
|
{
|
||||||
|
U32 data_mask = 0;
|
||||||
|
for (U32 i = 0; i < mRiggedIndex.size(); ++i)
|
||||||
|
{
|
||||||
|
if (mRiggedIndex[i] > -1)
|
||||||
|
{
|
||||||
|
data_mask |= LLFace::getRiggedDataMask(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
S32 LLFace::getRiggedIndex(U32 type) const
|
||||||
|
{
|
||||||
|
if (mRiggedIndex.empty())
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
llassert(type < mRiggedIndex.size());
|
||||||
|
|
||||||
|
return mRiggedIndex[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLFace::setRiggedIndex(U32 type, S32 index)
|
||||||
|
{
|
||||||
|
if (mRiggedIndex.empty())
|
||||||
|
{
|
||||||
|
mRiggedIndex.resize(LLDrawPoolAvatar::NUM_RIGGED_PASSES);
|
||||||
|
for (U32 i = 0; i < mRiggedIndex.size(); ++i)
|
||||||
|
{
|
||||||
|
mRiggedIndex[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
llassert(type < mRiggedIndex.size());
|
||||||
|
|
||||||
|
mRiggedIndex[type] = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //MESH_ENABLED
|
||||||
@@ -83,6 +83,9 @@ public:
|
|||||||
HUD_RENDER = 0x0008,
|
HUD_RENDER = 0x0008,
|
||||||
USE_FACE_COLOR = 0x0010,
|
USE_FACE_COLOR = 0x0010,
|
||||||
TEXTURE_ANIM = 0x0020,
|
TEXTURE_ANIM = 0x0020,
|
||||||
|
#if MESH_ENABLED
|
||||||
|
RIGGED = 0x0040,
|
||||||
|
#endif //MESH_ENABLED
|
||||||
};
|
};
|
||||||
|
|
||||||
static void initClass();
|
static void initClass();
|
||||||
@@ -202,8 +205,8 @@ public:
|
|||||||
BOOL verify(const U32* indices_array = NULL) const;
|
BOOL verify(const U32* indices_array = NULL) const;
|
||||||
void printDebugInfo() const;
|
void printDebugInfo() const;
|
||||||
|
|
||||||
void setGeomIndex(U16 idx) { mGeomIndex = idx; }
|
void setGeomIndex(U16 idx);
|
||||||
void setIndicesIndex(S32 idx) { mIndicesIndex = idx; }
|
void setIndicesIndex(S32 idx);
|
||||||
void setDrawInfo(LLDrawInfo* draw_info);
|
void setDrawInfo(LLDrawInfo* draw_info);
|
||||||
|
|
||||||
F32 getTextureVirtualSize() ;
|
F32 getTextureVirtualSize() ;
|
||||||
@@ -212,6 +215,13 @@ public:
|
|||||||
void setVertexBuffer(LLVertexBuffer* buffer);
|
void setVertexBuffer(LLVertexBuffer* buffer);
|
||||||
void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL
|
void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL
|
||||||
LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; }
|
LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; }
|
||||||
|
#if MESH_ENABLED
|
||||||
|
U32 getRiggedVertexBufferDataMask() const;
|
||||||
|
S32 getRiggedIndex(U32 type) const;
|
||||||
|
void setRiggedIndex(U32 type, S32 index);
|
||||||
|
|
||||||
|
static U32 getRiggedDataMask(U32 type);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
public: //aligned members
|
public: //aligned members
|
||||||
LLVector4a mExtents[2];
|
LLVector4a mExtents[2];
|
||||||
|
|
||||||
@@ -229,6 +239,9 @@ public:
|
|||||||
LLVector2 mTexExtents[2];
|
LLVector2 mTexExtents[2];
|
||||||
F32 mDistance;
|
F32 mDistance;
|
||||||
F32 mLastUpdateTime;
|
F32 mLastUpdateTime;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
F32 mLastSkinTime;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
F32 mLastMoveTime;
|
F32 mLastMoveTime;
|
||||||
LLMatrix4* mTextureMatrix;
|
LLMatrix4* mTextureMatrix;
|
||||||
LLDrawInfo* mDrawInfo;
|
LLDrawInfo* mDrawInfo;
|
||||||
@@ -264,6 +277,10 @@ private:
|
|||||||
S32 mTEOffset;
|
S32 mTEOffset;
|
||||||
|
|
||||||
S32 mReferenceIndex;
|
S32 mReferenceIndex;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
std::vector<S32> mRiggedIndex;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
F32 mVSize;
|
F32 mVSize;
|
||||||
F32 mPixelArea;
|
F32 mPixelArea;
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,11 @@ static struct ft_display_info ft_display_table[] =
|
|||||||
{ LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 },
|
{ LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 },
|
||||||
{ LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 1 },
|
{ LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 1 },
|
||||||
{ LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 },
|
{ LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 },
|
||||||
|
#if MESH_ENABLED
|
||||||
|
{ LLFastTimer::FTM_UPDATE_RIGGED_VOLUME," Rigged", &LLColor4::red3, 0 },
|
||||||
|
{ LLFastTimer::FTM_SKIN_RIGGED, " Skin", &LLColor4::green1, 0 },
|
||||||
|
{ LLFastTimer::FTM_RIGGED_OCTREE, " Octree", &LLColor4::green5, 0 },
|
||||||
|
#endif //MESH_ENABLED
|
||||||
{ LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 },
|
{ LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 },
|
||||||
{ LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 },
|
{ LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 },
|
||||||
{ LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 },
|
{ LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 },
|
||||||
@@ -155,6 +160,12 @@ static struct ft_display_info ft_display_table[] =
|
|||||||
{ LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 },
|
{ LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 },
|
||||||
{ LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 },
|
{ LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 },
|
||||||
{ LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 },
|
{ LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 },
|
||||||
|
#if MESH_ENABLED
|
||||||
|
{ LLFastTimer::FTM_MESH_UPDATE, " Mesh Update", &LLColor4::orange4, 0 },
|
||||||
|
{ LLFastTimer::FTM_MESH_LOCK1, " Lock 1", &LLColor4::orange5, 0 },
|
||||||
|
{ LLFastTimer::FTM_MESH_LOCK2, " Lock 2", &LLColor4::orange6, 0 },
|
||||||
|
{ LLFastTimer::FTM_LOAD_MESH_LOD, " Load LOD", &LLColor4::yellow3, 0 },
|
||||||
|
#endif //MESH_ENABLED
|
||||||
{ LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 },
|
{ LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 },
|
||||||
{ LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 },
|
{ LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 },
|
||||||
{ LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 },
|
{ LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 },
|
||||||
|
|||||||
@@ -348,24 +348,7 @@ bool LLFloaterImagePreview::loadImage(const std::string& src_filename)
|
|||||||
{
|
{
|
||||||
std::string exten = gDirUtilp->getExtension(src_filename);
|
std::string exten = gDirUtilp->getExtension(src_filename);
|
||||||
|
|
||||||
U32 codec = IMG_CODEC_INVALID;
|
U32 codec = LLImageBase::getCodecFromExtension(exten);
|
||||||
std::string temp_str;
|
|
||||||
if( exten == "bmp")
|
|
||||||
{
|
|
||||||
codec = IMG_CODEC_BMP;
|
|
||||||
}
|
|
||||||
else if( exten == "tga")
|
|
||||||
{
|
|
||||||
codec = IMG_CODEC_TGA;
|
|
||||||
}
|
|
||||||
else if( exten == "jpg" || exten == "jpeg")
|
|
||||||
{
|
|
||||||
codec = IMG_CODEC_JPEG;
|
|
||||||
}
|
|
||||||
else if( exten == "png" )
|
|
||||||
{
|
|
||||||
codec = IMG_CODEC_PNG;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
|
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
|
||||||
|
|
||||||
@@ -854,8 +837,8 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
|
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
|
||||||
U32 num_indices = vf.mIndices.size();
|
U32 num_indices = vf.mNumIndices;
|
||||||
U32 num_vertices = vf.mVertices.size();
|
U32 num_vertices = vf.mNumVertices;
|
||||||
|
|
||||||
mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0);
|
mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0);
|
||||||
mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE);
|
mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE);
|
||||||
@@ -869,12 +852,12 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance)
|
|||||||
mVertexBuffer->getIndexStrider(index_strider);
|
mVertexBuffer->getIndexStrider(index_strider);
|
||||||
|
|
||||||
// build vertices and normals
|
// build vertices and normals
|
||||||
for (U32 i = 0; (S32)i < num_vertices; i++)
|
for (U32 i = 0; (U32)i < num_vertices; i++)
|
||||||
{
|
{
|
||||||
*(vertex_strider++) = vf.mVertices[i].mPosition;
|
(vertex_strider++)->set(vf.mPositions[i].getF32ptr());
|
||||||
LLVector3 normal = vf.mVertices[i].mNormal;
|
LLVector4a normal(vf.mNormals[i]);
|
||||||
normal.normalize();
|
normal.normalize3fast();
|
||||||
*(normal_strider++) = normal;
|
(normal_strider++)->set(normal.getF32ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
// build indices
|
// build indices
|
||||||
@@ -936,7 +919,7 @@ BOOL LLImagePreviewSculpted::render()
|
|||||||
LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
|
LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE);
|
||||||
|
|
||||||
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
|
const LLVolumeFace &vf = mVolume->getVolumeFace(0);
|
||||||
U32 num_indices = vf.mIndices.size();
|
U32 num_indices = (U32)vf.mNumIndices;
|
||||||
|
|
||||||
mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL);
|
mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL);
|
||||||
|
|
||||||
@@ -949,7 +932,6 @@ BOOL LLImagePreviewSculpted::render()
|
|||||||
mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0);
|
mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0);
|
||||||
|
|
||||||
gGL.popMatrix();
|
gGL.popMatrix();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
#include "llfloaterlandmark.h"
|
#include "llfloaterlandmark.h"
|
||||||
|
|
||||||
#include "llagent.h"
|
#include "llagent.h"
|
||||||
|
#include "llagentui.h"
|
||||||
#include "llcheckboxctrl.h"
|
#include "llcheckboxctrl.h"
|
||||||
#include "llviewerparcelmgr.h"
|
#include "llviewerparcelmgr.h"
|
||||||
#include "llfolderview.h"
|
#include "llfolderview.h"
|
||||||
@@ -299,14 +300,15 @@ void LLFloaterLandmark::onBtnNew(void* userdata)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLUUID folder_id;
|
std::string landmark_name, landmark_desc;
|
||||||
folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
|
|
||||||
std::string pos_string;
|
LLAgentUI::buildLocationString(landmark_name, LLAgentUI::LOCATION_FORMAT_LANDMARK);
|
||||||
gAgent.buildLocationString(pos_string);
|
LLAgentUI::buildLocationString(landmark_desc, LLAgentUI::LOCATION_FORMAT_FULL);
|
||||||
|
const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
|
||||||
|
|
||||||
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
|
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
|
||||||
folder_id, LLTransactionID::tnull,
|
folder_id, LLTransactionID::tnull,
|
||||||
pos_string, pos_string, // name, desc
|
landmark_name, landmark_desc, // name, desc
|
||||||
LLAssetType::AT_LANDMARK,
|
LLAssetType::AT_LANDMARK,
|
||||||
LLInventoryType::IT_LANDMARK,
|
LLInventoryType::IT_LANDMARK,
|
||||||
NOT_WEARABLE, PERM_ALL,
|
NOT_WEARABLE, PERM_ALL,
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
#include "lltoolfocus.h"
|
#include "lltoolfocus.h"
|
||||||
#include "lltoolmgr.h"
|
#include "lltoolmgr.h"
|
||||||
#include "llworld.h"
|
#include "llworld.h"
|
||||||
|
#include "llagentui.h"
|
||||||
|
|
||||||
#include "llgl.h"
|
#include "llgl.h"
|
||||||
#include "llglheaders.h"
|
#include "llglheaders.h"
|
||||||
@@ -975,9 +976,9 @@ void LLSnapshotLivePreview::saveTexture()
|
|||||||
{
|
{
|
||||||
LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
|
LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE);
|
||||||
std::string pos_string;
|
std::string pos_string;
|
||||||
gAgent.buildLocationString(pos_string);
|
LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL);
|
||||||
std::string who_took_it;
|
std::string who_took_it;
|
||||||
gAgent.buildFullname(who_took_it);
|
LLAgentUI::buildFullname(who_took_it);
|
||||||
LLAssetStorage::LLStoreAssetCallback callback = NULL;
|
LLAssetStorage::LLStoreAssetCallback callback = NULL;
|
||||||
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
|
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
|
||||||
void *userdata = NULL;
|
void *userdata = NULL;
|
||||||
|
|||||||
@@ -81,9 +81,14 @@
|
|||||||
#include "llviewercontrol.h"
|
#include "llviewercontrol.h"
|
||||||
#include "llviewerjoystick.h"
|
#include "llviewerjoystick.h"
|
||||||
#include "lluictrlfactory.h"
|
#include "lluictrlfactory.h"
|
||||||
|
#if MESH_ENABLED
|
||||||
|
#include "llaccountingquotamanager.h"
|
||||||
|
#include "llmeshrepository.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "qtoolalign.h" //Thank Qarl!
|
#include "qtoolalign.h" //Thank Qarl!
|
||||||
|
|
||||||
|
|
||||||
// Globals
|
// Globals
|
||||||
LLFloaterTools *gFloaterTools = NULL;
|
LLFloaterTools *gFloaterTools = NULL;
|
||||||
|
|
||||||
@@ -511,9 +516,23 @@ void LLFloaterTools::refresh()
|
|||||||
childSetTextArg("link_num_obj_count", "[DESC]", desc_string);
|
childSetTextArg("link_num_obj_count", "[DESC]", desc_string);
|
||||||
childSetTextArg("link_num_obj_count", "[NUM]", value_string);
|
childSetTextArg("link_num_obj_count", "[NUM]", value_string);
|
||||||
|
|
||||||
std::string prim_count_string;
|
LLStringUtil::format_map_t selection_args;
|
||||||
LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount());
|
selection_args["COUNT"] = llformat("%.1d", (S32)prim_count);
|
||||||
childSetTextArg("prim_count", "[COUNT]", prim_count_string);
|
#if MESH_ENABLED
|
||||||
|
if(gMeshRepo.meshRezEnabled())
|
||||||
|
{
|
||||||
|
F32 link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectCost();
|
||||||
|
LLStringUtil::format_map_t prim_equiv_args;
|
||||||
|
prim_equiv_args["SEL_WEIGHT"] = llformat("%.1d", (S32)link_cost);
|
||||||
|
selection_args["PE_STRING"] = getString("status_selectprimequiv", prim_equiv_args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
{
|
||||||
|
selection_args["PE_STRING"] = "";
|
||||||
|
}
|
||||||
|
std::string prim_count_string = getString("status_selectcount",selection_args);
|
||||||
|
childSetText("prim_count", prim_count_string);
|
||||||
|
|
||||||
// Refresh child tabs
|
// Refresh child tabs
|
||||||
mPanelPermissions->refresh();
|
mPanelPermissions->refresh();
|
||||||
|
|||||||
@@ -58,11 +58,15 @@
|
|||||||
#include "llui.h"
|
#include "llui.h"
|
||||||
#include "llviewercamera.h"
|
#include "llviewercamera.h"
|
||||||
#include "llviewerobject.h"
|
#include "llviewerobject.h"
|
||||||
|
#include "llviewerregion.h"
|
||||||
#include "llviewerwindow.h"
|
#include "llviewerwindow.h"
|
||||||
#include "llhudrender.h"
|
#include "llhudrender.h"
|
||||||
#include "llworld.h"
|
#include "llworld.h"
|
||||||
#include "v2math.h"
|
#include "v2math.h"
|
||||||
#include "llvoavatar.h"
|
#include "llvoavatar.h"
|
||||||
|
#if MESH_ENABLED
|
||||||
|
#include "llmeshrepository.h"
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
|
|
||||||
const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f;
|
const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f;
|
||||||
@@ -91,6 +95,25 @@ const LLManip::EManipPart MANIPULATOR_IDS[NUM_MANIPULATORS] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
F32 get_default_max_prim_scale(bool is_flora)
|
||||||
|
{
|
||||||
|
// a bit of a hack, but if it's foilage, we don't want to use the
|
||||||
|
// new larger scale which would result in giant trees and grass
|
||||||
|
#if MESH_ENABLED
|
||||||
|
if (gMeshRepo.meshRezEnabled() &&
|
||||||
|
!is_flora)
|
||||||
|
{
|
||||||
|
return DEFAULT_MAX_PRIM_SCALE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return DEFAULT_MAX_PRIM_SCALE_NO_MESH;
|
||||||
|
}
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
#if !MESH_ENABLED
|
||||||
|
return DEFAULT_MAX_PRIM_SCALE;
|
||||||
|
#endif //!MESH_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void LLManipScale::setUniform(BOOL b)
|
void LLManipScale::setUniform(BOOL b)
|
||||||
@@ -953,8 +976,8 @@ void LLManipScale::dragCorner( S32 x, S32 y )
|
|||||||
mInSnapRegime = FALSE;
|
mInSnapRegime = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
F32 max_scale_factor = DEFAULT_MAX_PRIM_SCALE / MIN_PRIM_SCALE;
|
F32 max_scale_factor = get_default_max_prim_scale() / MIN_PRIM_SCALE;
|
||||||
F32 min_scale_factor = MIN_PRIM_SCALE / DEFAULT_MAX_PRIM_SCALE;
|
F32 min_scale_factor = MIN_PRIM_SCALE / get_default_max_prim_scale();
|
||||||
|
|
||||||
// find max and min scale factors that will make biggest object hit max absolute scale and smallest object hit min absolute scale
|
// find max and min scale factors that will make biggest object hit max absolute scale and smallest object hit min absolute scale
|
||||||
for (LLObjectSelection::iterator iter = mObjectSelection->begin();
|
for (LLObjectSelection::iterator iter = mObjectSelection->begin();
|
||||||
@@ -966,7 +989,7 @@ void LLManipScale::dragCorner( S32 x, S32 y )
|
|||||||
{
|
{
|
||||||
const LLVector3& scale = selectNode->mSavedScale;
|
const LLVector3& scale = selectNode->mSavedScale;
|
||||||
|
|
||||||
F32 cur_max_scale_factor = llmin( DEFAULT_MAX_PRIM_SCALE / scale.mV[VX], DEFAULT_MAX_PRIM_SCALE / scale.mV[VY], DEFAULT_MAX_PRIM_SCALE / scale.mV[VZ] );
|
F32 cur_max_scale_factor = llmin( get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VX], get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VY], get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VZ] );
|
||||||
max_scale_factor = llmin( max_scale_factor, cur_max_scale_factor );
|
max_scale_factor = llmin( max_scale_factor, cur_max_scale_factor );
|
||||||
|
|
||||||
F32 cur_min_scale_factor = llmax( MIN_PRIM_SCALE / scale.mV[VX], MIN_PRIM_SCALE / scale.mV[VY], MIN_PRIM_SCALE / scale.mV[VZ] );
|
F32 cur_min_scale_factor = llmax( MIN_PRIM_SCALE / scale.mV[VX], MIN_PRIM_SCALE / scale.mV[VY], MIN_PRIM_SCALE / scale.mV[VZ] );
|
||||||
@@ -1263,7 +1286,7 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto
|
|||||||
|
|
||||||
F32 denom = axis * dir_local;
|
F32 denom = axis * dir_local;
|
||||||
F32 desired_delta_size = is_approx_zero(denom) ? 0.f : (delta_local_mag / denom); // in meters
|
F32 desired_delta_size = is_approx_zero(denom) ? 0.f : (delta_local_mag / denom); // in meters
|
||||||
F32 desired_scale = llclamp(selectNode->mSavedScale.mV[axis_index] + desired_delta_size, MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE);
|
F32 desired_scale = llclamp(selectNode->mSavedScale.mV[axis_index] + desired_delta_size, MIN_PRIM_SCALE, get_default_max_prim_scale(LLPickInfo::isFlora(cur)));
|
||||||
// propagate scale constraint back to position offset
|
// propagate scale constraint back to position offset
|
||||||
desired_delta_size = desired_scale - selectNode->mSavedScale.mV[axis_index]; // propagate constraint back to position
|
desired_delta_size = desired_scale - selectNode->mSavedScale.mV[axis_index]; // propagate constraint back to position
|
||||||
|
|
||||||
@@ -1964,7 +1987,7 @@ F32 LLManipScale::partToMaxScale( S32 part, const LLBBox &bbox ) const
|
|||||||
max_extent = bbox_extents.mV[i];
|
max_extent = bbox_extents.mV[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
max_scale_factor = bbox_extents.magVec() * DEFAULT_MAX_PRIM_SCALE / max_extent;
|
max_scale_factor = bbox_extents.magVec() * get_default_max_prim_scale() / max_extent;
|
||||||
|
|
||||||
if (getUniform())
|
if (getUniform())
|
||||||
{
|
{
|
||||||
@@ -1979,7 +2002,7 @@ F32 LLManipScale::partToMinScale( S32 part, const LLBBox &bbox ) const
|
|||||||
{
|
{
|
||||||
LLVector3 bbox_extents = unitVectorToLocalBBoxExtent( partToUnitVector( part ), bbox );
|
LLVector3 bbox_extents = unitVectorToLocalBBoxExtent( partToUnitVector( part ), bbox );
|
||||||
bbox_extents.abs();
|
bbox_extents.abs();
|
||||||
F32 min_extent = DEFAULT_MAX_PRIM_SCALE;
|
F32 min_extent = get_default_max_prim_scale();
|
||||||
for (U32 i = VX; i <= VZ; i++)
|
for (U32 i = VX; i <= VZ; i++)
|
||||||
{
|
{
|
||||||
if (bbox_extents.mV[i] > 0.f && bbox_extents.mV[i] < min_extent)
|
if (bbox_extents.mV[i] > 0.f && bbox_extents.mV[i] < min_extent)
|
||||||
|
|||||||
@@ -45,6 +45,9 @@
|
|||||||
#include "llviewerobject.h"
|
#include "llviewerobject.h"
|
||||||
#include "llbbox.h"
|
#include "llbbox.h"
|
||||||
|
|
||||||
|
|
||||||
|
F32 get_default_max_prim_scale(bool is_flora = false);
|
||||||
|
|
||||||
class LLToolComposite;
|
class LLToolComposite;
|
||||||
class LLColor4;
|
class LLColor4;
|
||||||
|
|
||||||
|
|||||||
3594
indra/newview/llmeshrepository.cpp
Normal file
3594
indra/newview/llmeshrepository.cpp
Normal file
File diff suppressed because it is too large
Load Diff
590
indra/newview/llmeshrepository.h
Normal file
590
indra/newview/llmeshrepository.h
Normal file
@@ -0,0 +1,590 @@
|
|||||||
|
/**
|
||||||
|
* @file llmeshrepository.h
|
||||||
|
* @brief Client-side repository of mesh assets.
|
||||||
|
*
|
||||||
|
* $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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LL_MESH_REPOSITORY_H
|
||||||
|
#define LL_MESH_REPOSITORY_H
|
||||||
|
|
||||||
|
#include "llassettype.h"
|
||||||
|
#include "llmodel.h"
|
||||||
|
#include "lluuid.h"
|
||||||
|
#include "llviewertexture.h"
|
||||||
|
#include "llvolume.h"
|
||||||
|
|
||||||
|
#if MESH_IMPORT
|
||||||
|
#define LLCONVEXDECOMPINTER_STATIC 1
|
||||||
|
|
||||||
|
#include "llconvexdecomposition.h"
|
||||||
|
#endif //MESH_IMPORT
|
||||||
|
|
||||||
|
#if !MESH_IMPORT
|
||||||
|
//Placeholder structs from LLConvexDecomposition.h:
|
||||||
|
struct LLCDMeshData
|
||||||
|
{
|
||||||
|
enum IndexType
|
||||||
|
{
|
||||||
|
INT_16,
|
||||||
|
INT_32
|
||||||
|
};
|
||||||
|
|
||||||
|
const float* mVertexBase;
|
||||||
|
int mVertexStrideBytes;
|
||||||
|
int mNumVertices;
|
||||||
|
const void* mIndexBase;
|
||||||
|
IndexType mIndexType;
|
||||||
|
int mIndexStrideBytes;
|
||||||
|
int mNumTriangles;
|
||||||
|
};
|
||||||
|
struct LLCDHull
|
||||||
|
{
|
||||||
|
const float* mVertexBase;
|
||||||
|
int mVertexStrideBytes;
|
||||||
|
int mNumVertices;
|
||||||
|
};
|
||||||
|
#endif //!MESH_IMPORT
|
||||||
|
|
||||||
|
class LLVOVolume;
|
||||||
|
class LLMeshResponder;
|
||||||
|
class LLCurlRequest;
|
||||||
|
class LLMutex;
|
||||||
|
class LLCondition;
|
||||||
|
class LLVFS;
|
||||||
|
class LLMeshRepository;
|
||||||
|
|
||||||
|
class LLMeshUploadData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLPointer<LLModel> mBaseModel;
|
||||||
|
LLPointer<LLModel> mModel[5];
|
||||||
|
LLUUID mUUID;
|
||||||
|
U32 mRetries;
|
||||||
|
std::string mRSVP;
|
||||||
|
std::string mAssetData;
|
||||||
|
LLSD mPostData;
|
||||||
|
|
||||||
|
LLMeshUploadData()
|
||||||
|
{
|
||||||
|
mRetries = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LLTextureUploadData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLViewerFetchedTexture* mTexture;
|
||||||
|
LLUUID mUUID;
|
||||||
|
std::string mRSVP;
|
||||||
|
std::string mLabel;
|
||||||
|
U32 mRetries;
|
||||||
|
std::string mAssetData;
|
||||||
|
LLSD mPostData;
|
||||||
|
|
||||||
|
LLTextureUploadData()
|
||||||
|
{
|
||||||
|
mRetries = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLTextureUploadData(LLViewerFetchedTexture* texture, std::string& label)
|
||||||
|
: mTexture(texture), mLabel(label)
|
||||||
|
{
|
||||||
|
mRetries = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::map<std::string, LLSD> decomp_params;
|
||||||
|
|
||||||
|
class Request : public LLRefCount
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//input params
|
||||||
|
S32* mDecompID;
|
||||||
|
std::string mStage;
|
||||||
|
std::vector<LLVector3> mPositions;
|
||||||
|
std::vector<U16> mIndices;
|
||||||
|
decomp_params mParams;
|
||||||
|
|
||||||
|
//output state
|
||||||
|
std::string mStatusMessage;
|
||||||
|
std::vector<LLModel::PhysicsMesh> mHullMesh;
|
||||||
|
LLModel::convex_hull_decomposition mHull;
|
||||||
|
|
||||||
|
//status message callback, called from decomposition thread
|
||||||
|
virtual S32 statusCallback(const char* status, S32 p1, S32 p2) = 0;
|
||||||
|
|
||||||
|
//completed callback, called from the main thread
|
||||||
|
virtual void completed() = 0;
|
||||||
|
|
||||||
|
virtual void setStatusMessage(const std::string& msg);
|
||||||
|
|
||||||
|
bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//internal use
|
||||||
|
LLVector3 mBBox[2] ;
|
||||||
|
F32 mTriangleAreaThreshold ;
|
||||||
|
|
||||||
|
void assignData(LLModel* mdl) ;
|
||||||
|
void updateTriangleAreaThreshold() ;
|
||||||
|
bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ;
|
||||||
|
};
|
||||||
|
|
||||||
|
LLCondition* mSignal;
|
||||||
|
LLMutex* mMutex;
|
||||||
|
|
||||||
|
bool mInited;
|
||||||
|
bool mQuitting;
|
||||||
|
bool mDone;
|
||||||
|
|
||||||
|
LLPhysicsDecomp();
|
||||||
|
~LLPhysicsDecomp();
|
||||||
|
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
void submitRequest(Request* request);
|
||||||
|
static S32 llcdCallback(const char*, S32, S32);
|
||||||
|
void cancel();
|
||||||
|
|
||||||
|
void setMeshData(LLCDMeshData& mesh, bool vertex_based);
|
||||||
|
void doDecomposition();
|
||||||
|
void doDecompositionSingleHull();
|
||||||
|
|
||||||
|
virtual void run();
|
||||||
|
|
||||||
|
void completeCurrent();
|
||||||
|
void notifyCompleted();
|
||||||
|
|
||||||
|
std::map<std::string, S32> mStageID;
|
||||||
|
|
||||||
|
typedef std::queue<LLPointer<Request> > request_queue;
|
||||||
|
request_queue mRequestQ;
|
||||||
|
|
||||||
|
LLPointer<Request> mCurRequest;
|
||||||
|
|
||||||
|
std::queue<LLPointer<Request> > mCompletedQ;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class LLMeshRepoThread : public LLThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static S32 sActiveHeaderRequests;
|
||||||
|
static S32 sActiveLODRequests;
|
||||||
|
static U32 sMaxConcurrentRequests;
|
||||||
|
|
||||||
|
LLCurlRequest* mCurlRequest;
|
||||||
|
LLMutex* mMutex;
|
||||||
|
LLMutex* mHeaderMutex;
|
||||||
|
LLCondition* mSignal;
|
||||||
|
|
||||||
|
bool mWaiting;
|
||||||
|
|
||||||
|
//map of known mesh headers
|
||||||
|
typedef std::map<LLUUID, LLSD> mesh_header_map;
|
||||||
|
mesh_header_map mMeshHeader;
|
||||||
|
|
||||||
|
std::map<LLUUID, U32> mMeshHeaderSize;
|
||||||
|
|
||||||
|
class HeaderRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const LLVolumeParams mMeshParams;
|
||||||
|
|
||||||
|
HeaderRequest(const LLVolumeParams& mesh_params)
|
||||||
|
: mMeshParams(mesh_params)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const HeaderRequest& rhs) const
|
||||||
|
{
|
||||||
|
return mMeshParams < rhs.mMeshParams;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LODRequest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLVolumeParams mMeshParams;
|
||||||
|
S32 mLOD;
|
||||||
|
F32 mScore;
|
||||||
|
|
||||||
|
LODRequest(const LLVolumeParams& mesh_params, S32 lod)
|
||||||
|
: mMeshParams(mesh_params), mLOD(lod), mScore(0.f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CompareScoreGreater
|
||||||
|
{
|
||||||
|
bool operator()(const LODRequest& lhs, const LODRequest& rhs)
|
||||||
|
{
|
||||||
|
return lhs.mScore > rhs.mScore; // greatest = first
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LoadedMesh
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLPointer<LLVolume> mVolume;
|
||||||
|
LLVolumeParams mMeshParams;
|
||||||
|
S32 mLOD;
|
||||||
|
|
||||||
|
LoadedMesh(LLVolume* volume, const LLVolumeParams& mesh_params, S32 lod)
|
||||||
|
: mVolume(volume), mMeshParams(mesh_params), mLOD(lod)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//set of requested skin info
|
||||||
|
std::set<LLUUID> mSkinRequests;
|
||||||
|
|
||||||
|
//queue of completed skin info requests
|
||||||
|
std::queue<LLMeshSkinInfo> mSkinInfoQ;
|
||||||
|
|
||||||
|
//set of requested decompositions
|
||||||
|
std::set<LLUUID> mDecompositionRequests;
|
||||||
|
|
||||||
|
//set of requested physics shapes
|
||||||
|
std::set<LLUUID> mPhysicsShapeRequests;
|
||||||
|
|
||||||
|
//queue of completed Decomposition info requests
|
||||||
|
std::queue<LLModel::Decomposition*> mDecompositionQ;
|
||||||
|
|
||||||
|
//queue of requested headers
|
||||||
|
std::queue<HeaderRequest> mHeaderReqQ;
|
||||||
|
|
||||||
|
//queue of requested LODs
|
||||||
|
std::queue<LODRequest> mLODReqQ;
|
||||||
|
|
||||||
|
//queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD)
|
||||||
|
std::queue<LODRequest> mUnavailableQ;
|
||||||
|
|
||||||
|
//queue of successfully loaded meshes
|
||||||
|
std::queue<LoadedMesh> mLoadedQ;
|
||||||
|
|
||||||
|
//map of pending header requests and currently desired LODs
|
||||||
|
typedef std::map<LLVolumeParams, std::vector<S32> > pending_lod_map;
|
||||||
|
pending_lod_map mPendingLOD;
|
||||||
|
|
||||||
|
static std::string constructUrl(LLUUID mesh_id);
|
||||||
|
|
||||||
|
LLMeshRepoThread();
|
||||||
|
~LLMeshRepoThread();
|
||||||
|
|
||||||
|
virtual void run();
|
||||||
|
|
||||||
|
void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
|
||||||
|
bool fetchMeshHeader(const LLVolumeParams& mesh_params);
|
||||||
|
bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
|
||||||
|
bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
|
||||||
|
bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);
|
||||||
|
bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
|
||||||
|
bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
|
||||||
|
bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size);
|
||||||
|
LLSD& getMeshHeader(const LLUUID& mesh_id);
|
||||||
|
|
||||||
|
void notifyLoadedMeshes();
|
||||||
|
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
|
||||||
|
|
||||||
|
void loadMeshSkinInfo(const LLUUID& mesh_id);
|
||||||
|
void loadMeshDecomposition(const LLUUID& mesh_id);
|
||||||
|
void loadMeshPhysicsShape(const LLUUID& mesh_id);
|
||||||
|
|
||||||
|
//send request for skin info, returns true if header info exists
|
||||||
|
// (should hold onto mesh_id and try again later if header info does not exist)
|
||||||
|
bool fetchMeshSkinInfo(const LLUUID& mesh_id);
|
||||||
|
|
||||||
|
//send request for decomposition, returns true if header info exists
|
||||||
|
// (should hold onto mesh_id and try again later if header info does not exist)
|
||||||
|
bool fetchMeshDecomposition(const LLUUID& mesh_id);
|
||||||
|
|
||||||
|
//send request for PhysicsShape, returns true if header info exists
|
||||||
|
// (should hold onto mesh_id and try again later if header info does not exist)
|
||||||
|
bool fetchMeshPhysicsShape(const LLUUID& mesh_id);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#if MESH_IMPORT
|
||||||
|
class LLMeshUploadThread : public LLThread
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request.
|
||||||
|
|
||||||
|
public:
|
||||||
|
class DecompRequest : public LLPhysicsDecomp::Request
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLPointer<LLModel> mModel;
|
||||||
|
LLPointer<LLModel> mBaseModel;
|
||||||
|
|
||||||
|
LLMeshUploadThread* mThread;
|
||||||
|
|
||||||
|
DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread);
|
||||||
|
|
||||||
|
S32 statusCallback(const char* status, S32 p1, S32 p2) { return 1; }
|
||||||
|
void completed();
|
||||||
|
};
|
||||||
|
|
||||||
|
LLPointer<DecompRequest> mFinalDecomp;
|
||||||
|
bool mPhysicsComplete;
|
||||||
|
|
||||||
|
typedef std::map<LLPointer<LLModel>, std::vector<LLVector3> > hull_map;
|
||||||
|
hull_map mHullMap;
|
||||||
|
|
||||||
|
typedef std::vector<LLModelInstance> instance_list;
|
||||||
|
instance_list mInstanceList;
|
||||||
|
|
||||||
|
typedef std::map<LLPointer<LLModel>, instance_list> instance_map;
|
||||||
|
instance_map mInstance;
|
||||||
|
|
||||||
|
LLMutex* mMutex;
|
||||||
|
LLCurlRequest* mCurlRequest;
|
||||||
|
S32 mPendingUploads;
|
||||||
|
LLVector3 mOrigin;
|
||||||
|
bool mFinished;
|
||||||
|
bool mUploadTextures;
|
||||||
|
bool mUploadSkin;
|
||||||
|
bool mUploadJoints;
|
||||||
|
BOOL mDiscarded ;
|
||||||
|
|
||||||
|
LLHost mHost;
|
||||||
|
std::string mWholeModelFeeCapability;
|
||||||
|
std::string mWholeModelUploadURL;
|
||||||
|
|
||||||
|
LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures,
|
||||||
|
bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true,
|
||||||
|
LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
|
||||||
|
~LLMeshUploadThread();
|
||||||
|
|
||||||
|
bool finished() { return mFinished; }
|
||||||
|
virtual void run();
|
||||||
|
void preStart();
|
||||||
|
void discard() ;
|
||||||
|
BOOL isDiscarded();
|
||||||
|
|
||||||
|
void generateHulls();
|
||||||
|
|
||||||
|
void doWholeModelUpload();
|
||||||
|
void requestWholeModelFee();
|
||||||
|
|
||||||
|
void wholeModelToLLSD(LLSD& dest, bool include_textures);
|
||||||
|
|
||||||
|
void decomposeMeshMatrix(LLMatrix4& transformation,
|
||||||
|
LLVector3& result_pos,
|
||||||
|
LLQuaternion& result_rot,
|
||||||
|
LLVector3& result_scale);
|
||||||
|
|
||||||
|
void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
|
||||||
|
void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
|
||||||
|
LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
|
||||||
|
|
||||||
|
bool mDoUpload; // if FALSE only model data will be requested, otherwise the model will be uploaded
|
||||||
|
};
|
||||||
|
#endif //MESH_IMPORT
|
||||||
|
|
||||||
|
class LLMeshRepository
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
//metrics
|
||||||
|
static U32 sBytesReceived;
|
||||||
|
static U32 sHTTPRequestCount;
|
||||||
|
static U32 sHTTPRetryCount;
|
||||||
|
static U32 sCacheBytesRead;
|
||||||
|
static U32 sCacheBytesWritten;
|
||||||
|
static U32 sPeakKbps;
|
||||||
|
|
||||||
|
static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1);
|
||||||
|
|
||||||
|
LLMeshRepository();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void shutdown();
|
||||||
|
S32 update() ;
|
||||||
|
|
||||||
|
//mesh management functions
|
||||||
|
S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);
|
||||||
|
|
||||||
|
void notifyLoadedMeshes();
|
||||||
|
void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume);
|
||||||
|
void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod);
|
||||||
|
void notifySkinInfoReceived(LLMeshSkinInfo& info);
|
||||||
|
void notifyDecompositionReceived(LLModel::Decomposition* info);
|
||||||
|
|
||||||
|
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
|
||||||
|
static S32 getActualMeshLOD(LLSD& header, S32 lod);
|
||||||
|
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj);
|
||||||
|
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
|
||||||
|
void fetchPhysicsShape(const LLUUID& mesh_id);
|
||||||
|
bool hasPhysicsShape(const LLUUID& mesh_id);
|
||||||
|
|
||||||
|
void buildHull(const LLVolumeParams& params, S32 detail);
|
||||||
|
void buildPhysicsMesh(LLModel::Decomposition& decomp);
|
||||||
|
|
||||||
|
bool meshUploadEnabled();
|
||||||
|
bool meshRezEnabled();
|
||||||
|
|
||||||
|
|
||||||
|
LLSD& getMeshHeader(const LLUUID& mesh_id);
|
||||||
|
|
||||||
|
#if MESH_IMPORT
|
||||||
|
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
|
||||||
|
bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true,
|
||||||
|
LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
|
||||||
|
#endif //MESH_IMPORT
|
||||||
|
|
||||||
|
S32 getMeshSize(const LLUUID& mesh_id, S32 lod);
|
||||||
|
|
||||||
|
typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map;
|
||||||
|
mesh_load_map mLoadingMeshes[4];
|
||||||
|
|
||||||
|
typedef std::map<LLUUID, LLMeshSkinInfo> skin_map;
|
||||||
|
skin_map mSkinMap;
|
||||||
|
|
||||||
|
typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map;
|
||||||
|
decomposition_map mDecompositionMap;
|
||||||
|
|
||||||
|
LLMutex* mMeshMutex;
|
||||||
|
|
||||||
|
std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
|
||||||
|
|
||||||
|
//list of mesh ids awaiting skin info
|
||||||
|
typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map;
|
||||||
|
skin_load_map mLoadingSkins;
|
||||||
|
|
||||||
|
//list of mesh ids that need to send skin info fetch requests
|
||||||
|
std::queue<LLUUID> mPendingSkinRequests;
|
||||||
|
|
||||||
|
//list of mesh ids awaiting decompositions
|
||||||
|
std::set<LLUUID> mLoadingDecompositions;
|
||||||
|
|
||||||
|
//list of mesh ids that need to send decomposition fetch requests
|
||||||
|
std::queue<LLUUID> mPendingDecompositionRequests;
|
||||||
|
|
||||||
|
//list of mesh ids awaiting physics shapes
|
||||||
|
std::set<LLUUID> mLoadingPhysicsShapes;
|
||||||
|
|
||||||
|
//list of mesh ids that need to send physics shape fetch requests
|
||||||
|
std::queue<LLUUID> mPendingPhysicsShapeRequests;
|
||||||
|
|
||||||
|
U32 mMeshThreadCount;
|
||||||
|
|
||||||
|
#if MESH_IMPORT
|
||||||
|
void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header);
|
||||||
|
#endif //MESH_IMPORT
|
||||||
|
|
||||||
|
LLMeshRepoThread* mThread;
|
||||||
|
#if MESH_IMPORT
|
||||||
|
std::vector<LLMeshUploadThread*> mUploads;
|
||||||
|
std::vector<LLMeshUploadThread*> mUploadWaitList;
|
||||||
|
#endif //MESH_IMPORT
|
||||||
|
|
||||||
|
LLPhysicsDecomp* mDecompThread;
|
||||||
|
|
||||||
|
class inventory_data
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LLSD mPostData;
|
||||||
|
LLSD mResponse;
|
||||||
|
|
||||||
|
inventory_data(const LLSD& data, const LLSD& content)
|
||||||
|
: mPostData(data), mResponse(content)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::queue<inventory_data> mInventoryQ;
|
||||||
|
|
||||||
|
std::queue<LLSD> mUploadErrorQ;
|
||||||
|
|
||||||
|
void uploadError(LLSD& args);
|
||||||
|
void updateInventory(inventory_data data);
|
||||||
|
|
||||||
|
std::string mGetMeshCapability;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern LLMeshRepository gMeshRepo;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -726,7 +726,7 @@ void LLPanelObject::getState( )
|
|||||||
BOOL enabled = FALSE;
|
BOOL enabled = FALSE;
|
||||||
BOOL hole_enabled = FALSE;
|
BOOL hole_enabled = FALSE;
|
||||||
F32 scale_x=1.f, scale_y=1.f;
|
F32 scale_x=1.f, scale_y=1.f;
|
||||||
|
BOOL isMesh = FALSE;
|
||||||
if( !objectp || !objectp->getVolume() || !editable || !single_volume)
|
if( !objectp || !objectp->getVolume() || !editable || !single_volume)
|
||||||
{
|
{
|
||||||
// Clear out all geometry fields.
|
// Clear out all geometry fields.
|
||||||
@@ -1391,15 +1391,9 @@ void LLPanelObject::getState( )
|
|||||||
mCtrlSculptTexture->setVisible(sculpt_texture_visible);
|
mCtrlSculptTexture->setVisible(sculpt_texture_visible);
|
||||||
mLabelSculptType->setVisible(sculpt_texture_visible);
|
mLabelSculptType->setVisible(sculpt_texture_visible);
|
||||||
mCtrlSculptType->setVisible(sculpt_texture_visible);
|
mCtrlSculptType->setVisible(sculpt_texture_visible);
|
||||||
mCtrlSculptMirror->setVisible(sculpt_texture_visible);
|
|
||||||
mCtrlSculptInvert->setVisible(sculpt_texture_visible);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// sculpt texture
|
// sculpt texture
|
||||||
|
|
||||||
if (selected_item == MI_SCULPT)
|
if (selected_item == MI_SCULPT)
|
||||||
{
|
{
|
||||||
LLUUID id;
|
LLUUID id;
|
||||||
@@ -1413,36 +1407,37 @@ void LLPanelObject::getState( )
|
|||||||
mSculptTextureRevert = sculpt_params->getSculptTexture();
|
mSculptTextureRevert = sculpt_params->getSculptTexture();
|
||||||
mSculptTypeRevert = sculpt_params->getSculptType();
|
mSculptTypeRevert = sculpt_params->getSculptType();
|
||||||
}
|
}
|
||||||
|
U8 sculpt_type = sculpt_params->getSculptType();
|
||||||
|
U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
|
||||||
|
BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
|
||||||
|
BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
|
LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
|
||||||
if(mTextureCtrl)
|
if(mTextureCtrl)
|
||||||
{
|
{
|
||||||
mTextureCtrl->setTentative(FALSE);
|
mTextureCtrl->setTentative(FALSE);
|
||||||
mTextureCtrl->setEnabled(editable);
|
mTextureCtrl->setEnabled(editable && !isMesh);
|
||||||
if (editable)
|
if (editable)
|
||||||
mTextureCtrl->setImageAssetID(sculpt_params->getSculptTexture());
|
mTextureCtrl->setImageAssetID(sculpt_params->getSculptTexture());
|
||||||
else
|
else
|
||||||
mTextureCtrl->setImageAssetID(LLUUID::null);
|
mTextureCtrl->setImageAssetID(LLUUID::null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mComboBaseType->setEnabled(!isMesh);
|
||||||
|
|
||||||
|
|
||||||
U8 sculpt_type = sculpt_params->getSculptType();
|
|
||||||
U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
|
|
||||||
BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
|
|
||||||
BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
|
|
||||||
|
|
||||||
if (mCtrlSculptType)
|
if (mCtrlSculptType)
|
||||||
{
|
{
|
||||||
mCtrlSculptType->setCurrentByIndex(sculpt_stitching);
|
mCtrlSculptType->setCurrentByIndex(sculpt_stitching);
|
||||||
mCtrlSculptType->setEnabled(editable);
|
mCtrlSculptType->setEnabled(editable && !isMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCtrlSculptMirror)
|
if (mCtrlSculptMirror)
|
||||||
{
|
{
|
||||||
mCtrlSculptMirror->set(sculpt_mirror);
|
mCtrlSculptMirror->set(sculpt_mirror);
|
||||||
mCtrlSculptMirror->setEnabled(editable);
|
mCtrlSculptMirror->setEnabled(editable && !isMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCtrlSculptInvert)
|
if (mCtrlSculptInvert)
|
||||||
@@ -1455,18 +1450,16 @@ void LLPanelObject::getState( )
|
|||||||
{
|
{
|
||||||
mLabelSculptType->setEnabled(TRUE);
|
mLabelSculptType->setEnabled(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mSculptTextureRevert = LLUUID::null;
|
mSculptTextureRevert = LLUUID::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCtrlSculptMirror->setVisible(sculpt_texture_visible && !isMesh);
|
||||||
|
mCtrlSculptInvert->setVisible(sculpt_texture_visible && !isMesh);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -2254,6 +2247,20 @@ void LLPanelObject::sendSculpt()
|
|||||||
if (mCtrlSculptType)
|
if (mCtrlSculptType)
|
||||||
sculpt_type |= mCtrlSculptType->getCurrentIndex();
|
sculpt_type |= mCtrlSculptType->getCurrentIndex();
|
||||||
|
|
||||||
|
bool enabled = true;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
enabled = sculpt_type != LL_SCULPT_TYPE_MESH;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
|
if (mCtrlSculptMirror)
|
||||||
|
{
|
||||||
|
mCtrlSculptMirror->setEnabled(enabled ? TRUE : FALSE);
|
||||||
|
}
|
||||||
|
if (mCtrlSculptInvert)
|
||||||
|
{
|
||||||
|
mCtrlSculptInvert->setEnabled(enabled ? TRUE : FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
if ((mCtrlSculptMirror) && (mCtrlSculptMirror->get()))
|
if ((mCtrlSculptMirror) && (mCtrlSculptMirror->get()))
|
||||||
sculpt_type |= LL_SCULPT_FLAG_MIRROR;
|
sculpt_type |= LL_SCULPT_FLAG_MIRROR;
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,11 @@
|
|||||||
#include "lldrawpool.h"
|
#include "lldrawpool.h"
|
||||||
#include "lluictrlfactory.h"
|
#include "lluictrlfactory.h"
|
||||||
#include "lltexturectrl.h"
|
#include "lltexturectrl.h"
|
||||||
|
#if MESH_ENABLED
|
||||||
|
// For mesh physics
|
||||||
|
#include "llviewercontrol.h"
|
||||||
|
#include "llmeshrepository.h"
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
// "Features" Tab
|
// "Features" Tab
|
||||||
|
|
||||||
@@ -87,21 +92,21 @@ BOOL LLPanelVolume::postBuild()
|
|||||||
{
|
{
|
||||||
childSetCommitCallback("Flexible1D Checkbox Ctrl",onCommitIsFlexible,this);
|
childSetCommitCallback("Flexible1D Checkbox Ctrl",onCommitIsFlexible,this);
|
||||||
childSetCommitCallback("FlexNumSections",onCommitFlexible,this);
|
childSetCommitCallback("FlexNumSections",onCommitFlexible,this);
|
||||||
childSetValidate("FlexNumSections",precommitValidate);
|
getChild<LLUICtrl>("FlexNumSections")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("FlexGravity",onCommitFlexible,this);
|
childSetCommitCallback("FlexGravity",onCommitFlexible,this);
|
||||||
childSetValidate("FlexGravity",precommitValidate);
|
getChild<LLUICtrl>("FlexGravity")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("FlexFriction",onCommitFlexible,this);
|
childSetCommitCallback("FlexFriction",onCommitFlexible,this);
|
||||||
childSetValidate("FlexFriction",precommitValidate);
|
getChild<LLUICtrl>("FlexFriction")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("FlexWind",onCommitFlexible,this);
|
childSetCommitCallback("FlexWind",onCommitFlexible,this);
|
||||||
childSetValidate("FlexWind",precommitValidate);
|
getChild<LLUICtrl>("FlexWind")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("FlexTension",onCommitFlexible,this);
|
childSetCommitCallback("FlexTension",onCommitFlexible,this);
|
||||||
childSetValidate("FlexTension",precommitValidate);
|
getChild<LLUICtrl>("FlexTension")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("FlexForceX",onCommitFlexible,this);
|
childSetCommitCallback("FlexForceX",onCommitFlexible,this);
|
||||||
childSetValidate("FlexForceX",precommitValidate);
|
getChild<LLUICtrl>("FlexForceX")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("FlexForceY",onCommitFlexible,this);
|
childSetCommitCallback("FlexForceY",onCommitFlexible,this);
|
||||||
childSetValidate("FlexForceY",precommitValidate);
|
getChild<LLUICtrl>("FlexForceY")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("FlexForceZ",onCommitFlexible,this);
|
childSetCommitCallback("FlexForceZ",onCommitFlexible,this);
|
||||||
childSetValidate("FlexForceZ",precommitValidate);
|
getChild<LLUICtrl>("FlexForceZ")->setValidateBeforeCommit(precommitValidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LIGHT Parameters
|
// LIGHT Parameters
|
||||||
@@ -123,20 +128,47 @@ BOOL LLPanelVolume::postBuild()
|
|||||||
}
|
}
|
||||||
|
|
||||||
childSetCommitCallback("Light Intensity",onCommitLight,this);
|
childSetCommitCallback("Light Intensity",onCommitLight,this);
|
||||||
childSetValidate("Light Intensity",precommitValidate);
|
getChild<LLUICtrl>("Light Intensity")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("Light Radius",onCommitLight,this);
|
childSetCommitCallback("Light Radius",onCommitLight,this);
|
||||||
childSetValidate("Light Radius",precommitValidate);
|
getChild<LLUICtrl>("Light Radius")->setValidateBeforeCommit(precommitValidate);
|
||||||
childSetCommitCallback("Light Falloff",onCommitLight,this);
|
childSetCommitCallback("Light Falloff",onCommitLight,this);
|
||||||
childSetValidate("Light Falloff",precommitValidate);
|
getChild<LLUICtrl>("Light Falloff")->setValidateBeforeCommit(precommitValidate);
|
||||||
|
|
||||||
childSetCommitCallback("Light FOV", onCommitLight, this);
|
childSetCommitCallback("Light FOV", onCommitLight, this);
|
||||||
childSetValidate("Light FOV", precommitValidate);
|
getChild<LLUICtrl>("Light FOV")->setValidateBeforeCommit( precommitValidate);
|
||||||
childSetCommitCallback("Light Focus", onCommitLight, this);
|
childSetCommitCallback("Light Focus", onCommitLight, this);
|
||||||
childSetValidate("Light Focus", precommitValidate);
|
getChild<LLUICtrl>("Light Focus")->setValidateBeforeCommit( precommitValidate);
|
||||||
childSetCommitCallback("Light Ambiance", onCommitLight, this);
|
childSetCommitCallback("Light Ambiance", onCommitLight, this);
|
||||||
childSetValidate("Light Ambiance", precommitValidate);
|
getChild<LLUICtrl>("Light Ambiance")->setValidateBeforeCommit( precommitValidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
// PHYSICS Parameters
|
||||||
|
{
|
||||||
|
// Label
|
||||||
|
mComboPhysicsShapeLabel = getChild<LLTextBox>("label physicsshapetype");
|
||||||
|
|
||||||
|
// PhysicsShapeType combobox
|
||||||
|
mComboPhysicsShapeType = getChild<LLComboBox>("Physics Shape Type Combo Ctrl");
|
||||||
|
mComboPhysicsShapeType->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsShapeType, this, _1, mComboPhysicsShapeType));
|
||||||
|
|
||||||
|
// PhysicsGravity
|
||||||
|
mSpinPhysicsGravity = getChild<LLSpinCtrl>("Physics Gravity");
|
||||||
|
mSpinPhysicsGravity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsGravity, this, _1, mSpinPhysicsGravity));
|
||||||
|
|
||||||
|
// PhysicsFriction
|
||||||
|
mSpinPhysicsFriction = getChild<LLSpinCtrl>("Physics Friction");
|
||||||
|
mSpinPhysicsFriction->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsFriction, this, _1, mSpinPhysicsFriction));
|
||||||
|
|
||||||
|
// PhysicsDensity
|
||||||
|
mSpinPhysicsDensity = getChild<LLSpinCtrl>("Physics Density");
|
||||||
|
mSpinPhysicsDensity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsDensity, this, _1, mSpinPhysicsDensity));
|
||||||
|
|
||||||
|
// PhysicsRestitution
|
||||||
|
mSpinPhysicsRestitution = getChild<LLSpinCtrl>("Physics Restitution");
|
||||||
|
mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution));
|
||||||
|
}
|
||||||
|
#endif //MESH_ENABLED
|
||||||
// Start with everyone disabled
|
// Start with everyone disabled
|
||||||
clearCtrls();
|
clearCtrls();
|
||||||
|
|
||||||
@@ -212,25 +244,25 @@ void LLPanelVolume::getState( )
|
|||||||
// Select Single Message
|
// Select Single Message
|
||||||
if (single_volume)
|
if (single_volume)
|
||||||
{
|
{
|
||||||
childSetVisible("edit_object",true);
|
getChildView("edit_object")->setVisible(true);
|
||||||
childSetEnabled("edit_object",true);
|
getChildView("edit_object")->setEnabled(true);
|
||||||
childSetVisible("select_single",false);
|
getChildView("select_single")->setVisible(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
childSetVisible("edit_object",false);
|
getChildView("edit_object")->setVisible(false);
|
||||||
childSetVisible("select_single",true);
|
getChildView("select_single")->setVisible(true);
|
||||||
childSetEnabled("select_single",true);
|
getChildView("select_single")->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Light properties
|
// Light properties
|
||||||
BOOL is_light = volobjp && volobjp->getIsLight();
|
BOOL is_light = volobjp && volobjp->getIsLight();
|
||||||
childSetValue("Light Checkbox Ctrl",is_light);
|
getChild<LLUICtrl>("Light Checkbox Ctrl")->setValue(is_light);
|
||||||
childSetEnabled("Light Checkbox Ctrl",editable && single_volume && volobjp);
|
getChildView("Light Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp);
|
||||||
|
|
||||||
if (is_light && editable && single_volume)
|
if (is_light && editable && single_volume)
|
||||||
{
|
{
|
||||||
childSetEnabled("label color",true);
|
getChildView("label color")->setEnabled(true);
|
||||||
//mLabelColor ->setEnabled( TRUE );
|
//mLabelColor ->setEnabled( TRUE );
|
||||||
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
|
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
|
||||||
if(LightColorSwatch)
|
if(LightColorSwatch)
|
||||||
@@ -248,22 +280,23 @@ void LLPanelVolume::getState( )
|
|||||||
LightTextureCtrl->setValid(TRUE);
|
LightTextureCtrl->setValid(TRUE);
|
||||||
LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID());
|
LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID());
|
||||||
}
|
}
|
||||||
childSetEnabled("Light Intensity",true);
|
|
||||||
childSetEnabled("Light Radius",true);
|
|
||||||
childSetEnabled("Light Falloff",true);
|
|
||||||
|
|
||||||
childSetEnabled("Light FOV",true);
|
getChildView("Light Intensity")->setEnabled(true);
|
||||||
childSetEnabled("Light Focus",true);
|
getChildView("Light Radius")->setEnabled(true);
|
||||||
childSetEnabled("Light Ambiance",true);
|
getChildView("Light Falloff")->setEnabled(true);
|
||||||
|
|
||||||
childSetValue("Light Intensity",volobjp->getLightIntensity());
|
getChildView("Light FOV")->setEnabled(true);
|
||||||
childSetValue("Light Radius",volobjp->getLightRadius());
|
getChildView("Light Focus")->setEnabled(true);
|
||||||
childSetValue("Light Falloff",volobjp->getLightFalloff());
|
getChildView("Light Ambiance")->setEnabled(true);
|
||||||
|
|
||||||
|
getChild<LLUICtrl>("Light Intensity")->setValue(volobjp->getLightIntensity());
|
||||||
|
getChild<LLUICtrl>("Light Radius")->setValue(volobjp->getLightRadius());
|
||||||
|
getChild<LLUICtrl>("Light Falloff")->setValue(volobjp->getLightFalloff());
|
||||||
|
|
||||||
LLVector3 params = volobjp->getSpotLightParams();
|
LLVector3 params = volobjp->getSpotLightParams();
|
||||||
childSetValue("Light FOV",params.mV[0]);
|
getChild<LLUICtrl>("Light FOV")->setValue(params.mV[0]);
|
||||||
childSetValue("Light Focus",params.mV[1]);
|
getChild<LLUICtrl>("Light Focus")->setValue(params.mV[1]);
|
||||||
childSetValue("Light Ambiance",params.mV[2]);
|
getChild<LLUICtrl>("Light Ambiance")->setValue(params.mV[2]);
|
||||||
|
|
||||||
mLightSavedColor = volobjp->getLightColor();
|
mLightSavedColor = volobjp->getLightColor();
|
||||||
}
|
}
|
||||||
@@ -273,7 +306,7 @@ void LLPanelVolume::getState( )
|
|||||||
getChild<LLSpinCtrl>("Light Radius", true)->clear();
|
getChild<LLSpinCtrl>("Light Radius", true)->clear();
|
||||||
getChild<LLSpinCtrl>("Light Falloff", true)->clear();
|
getChild<LLSpinCtrl>("Light Falloff", true)->clear();
|
||||||
|
|
||||||
childSetEnabled("label color",false);
|
getChildView("label color")->setEnabled(false);
|
||||||
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
|
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
|
||||||
if(LightColorSwatch)
|
if(LightColorSwatch)
|
||||||
{
|
{
|
||||||
@@ -287,56 +320,61 @@ void LLPanelVolume::getState( )
|
|||||||
LightTextureCtrl->setEnabled(FALSE);
|
LightTextureCtrl->setEnabled(FALSE);
|
||||||
LightTextureCtrl->setValid(FALSE);
|
LightTextureCtrl->setValid(FALSE);
|
||||||
}
|
}
|
||||||
childSetEnabled("Light Intensity",false);
|
|
||||||
childSetEnabled("Light Radius",false);
|
|
||||||
childSetEnabled("Light Falloff",false);
|
|
||||||
|
|
||||||
childSetEnabled("Light FOV",false);
|
getChildView("Light Intensity")->setEnabled(false);
|
||||||
childSetEnabled("Light Focus",false);
|
getChildView("Light Radius")->setEnabled(false);
|
||||||
childSetEnabled("Light Ambiance",false);
|
getChildView("Light Falloff")->setEnabled(false);
|
||||||
|
|
||||||
|
getChildView("Light FOV")->setEnabled(false);
|
||||||
|
getChildView("Light Focus")->setEnabled(false);
|
||||||
|
getChildView("Light Ambiance")->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flexible properties
|
// Flexible properties
|
||||||
BOOL is_flexible = volobjp && volobjp->isFlexible();
|
BOOL is_flexible = volobjp && volobjp->isFlexible();
|
||||||
childSetValue("Flexible1D Checkbox Ctrl",is_flexible);
|
getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->setValue(is_flexible);
|
||||||
if (is_flexible || (volobjp && volobjp->canBeFlexible()))
|
if (is_flexible || (volobjp && volobjp->canBeFlexible()))
|
||||||
{
|
{
|
||||||
childSetEnabled("Flexible1D Checkbox Ctrl", editable && single_volume && volobjp);
|
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp
|
||||||
|
#if MESH_ENABLED
|
||||||
|
&& !volobjp->isMesh()
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
childSetEnabled("Flexible1D Checkbox Ctrl", false);
|
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);
|
||||||
}
|
}
|
||||||
if (is_flexible && editable && single_volume)
|
if (is_flexible && editable && single_volume)
|
||||||
{
|
{
|
||||||
childSetVisible("FlexNumSections",true);
|
getChildView("FlexNumSections")->setVisible(true);
|
||||||
childSetVisible("FlexGravity",true);
|
getChildView("FlexGravity")->setVisible(true);
|
||||||
childSetVisible("FlexTension",true);
|
getChildView("FlexTension")->setVisible(true);
|
||||||
childSetVisible("FlexFriction",true);
|
getChildView("FlexFriction")->setVisible(true);
|
||||||
childSetVisible("FlexWind",true);
|
getChildView("FlexWind")->setVisible(true);
|
||||||
childSetVisible("FlexForceX",true);
|
getChildView("FlexForceX")->setVisible(true);
|
||||||
childSetVisible("FlexForceY",true);
|
getChildView("FlexForceY")->setVisible(true);
|
||||||
childSetVisible("FlexForceZ",true);
|
getChildView("FlexForceZ")->setVisible(true);
|
||||||
|
|
||||||
childSetEnabled("FlexNumSections",true);
|
getChildView("FlexNumSections")->setEnabled(true);
|
||||||
childSetEnabled("FlexGravity",true);
|
getChildView("FlexGravity")->setEnabled(true);
|
||||||
childSetEnabled("FlexTension",true);
|
getChildView("FlexTension")->setEnabled(true);
|
||||||
childSetEnabled("FlexFriction",true);
|
getChildView("FlexFriction")->setEnabled(true);
|
||||||
childSetEnabled("FlexWind",true);
|
getChildView("FlexWind")->setEnabled(true);
|
||||||
childSetEnabled("FlexForceX",true);
|
getChildView("FlexForceX")->setEnabled(true);
|
||||||
childSetEnabled("FlexForceY",true);
|
getChildView("FlexForceY")->setEnabled(true);
|
||||||
childSetEnabled("FlexForceZ",true);
|
getChildView("FlexForceZ")->setEnabled(true);
|
||||||
|
|
||||||
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
|
LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
|
||||||
|
|
||||||
childSetValue("FlexNumSections",(F32)attributes->getSimulateLOD());
|
getChild<LLUICtrl>("FlexNumSections")->setValue((F32)attributes->getSimulateLOD());
|
||||||
childSetValue("FlexGravity",attributes->getGravity());
|
getChild<LLUICtrl>("FlexGravity")->setValue(attributes->getGravity());
|
||||||
childSetValue("FlexTension",attributes->getTension());
|
getChild<LLUICtrl>("FlexTension")->setValue(attributes->getTension());
|
||||||
childSetValue("FlexFriction",attributes->getAirFriction());
|
getChild<LLUICtrl>("FlexFriction")->setValue(attributes->getAirFriction());
|
||||||
childSetValue("FlexWind",attributes->getWindSensitivity());
|
getChild<LLUICtrl>("FlexWind")->setValue(attributes->getWindSensitivity());
|
||||||
childSetValue("FlexForceX",attributes->getUserForce().mV[VX]);
|
getChild<LLUICtrl>("FlexForceX")->setValue(attributes->getUserForce().mV[VX]);
|
||||||
childSetValue("FlexForceY",attributes->getUserForce().mV[VY]);
|
getChild<LLUICtrl>("FlexForceY")->setValue(attributes->getUserForce().mV[VY]);
|
||||||
childSetValue("FlexForceZ",attributes->getUserForce().mV[VZ]);
|
getChild<LLUICtrl>("FlexForceZ")->setValue(attributes->getUserForce().mV[VZ]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -349,22 +387,73 @@ void LLPanelVolume::getState( )
|
|||||||
getChild<LLSpinCtrl>("FlexForceY", true)->clear();
|
getChild<LLSpinCtrl>("FlexForceY", true)->clear();
|
||||||
getChild<LLSpinCtrl>("FlexForceZ", true)->clear();
|
getChild<LLSpinCtrl>("FlexForceZ", true)->clear();
|
||||||
|
|
||||||
childSetEnabled("FlexNumSections",false);
|
getChildView("FlexNumSections")->setEnabled(false);
|
||||||
childSetEnabled("FlexGravity",false);
|
getChildView("FlexGravity")->setEnabled(false);
|
||||||
childSetEnabled("FlexTension",false);
|
getChildView("FlexTension")->setEnabled(false);
|
||||||
childSetEnabled("FlexFriction",false);
|
getChildView("FlexFriction")->setEnabled(false);
|
||||||
childSetEnabled("FlexWind",false);
|
getChildView("FlexWind")->setEnabled(false);
|
||||||
childSetEnabled("FlexForceX",false);
|
getChildView("FlexForceX")->setEnabled(false);
|
||||||
childSetEnabled("FlexForceY",false);
|
getChildView("FlexForceY")->setEnabled(false);
|
||||||
childSetEnabled("FlexForceZ",false);
|
getChildView("FlexForceZ")->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
// Physics properties
|
||||||
|
|
||||||
|
mComboPhysicsShapeLabel->setEnabled(editable);
|
||||||
|
mSpinPhysicsGravity->set(objectp->getPhysicsGravity());
|
||||||
|
mSpinPhysicsGravity->setEnabled(editable);
|
||||||
|
|
||||||
|
mSpinPhysicsFriction->set(objectp->getPhysicsFriction());
|
||||||
|
mSpinPhysicsFriction->setEnabled(editable);
|
||||||
|
|
||||||
|
mSpinPhysicsDensity->set(objectp->getPhysicsDensity());
|
||||||
|
mSpinPhysicsDensity->setEnabled(editable);
|
||||||
|
|
||||||
|
mSpinPhysicsRestitution->set(objectp->getPhysicsRestitution());
|
||||||
|
mSpinPhysicsRestitution->setEnabled(editable);
|
||||||
|
|
||||||
|
// update the physics shape combo to include allowed physics shapes
|
||||||
|
mComboPhysicsShapeType->removeall();
|
||||||
|
mComboPhysicsShapeType->add(getString("None"), LLSD(1));
|
||||||
|
|
||||||
|
BOOL isMesh = FALSE;
|
||||||
|
LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
|
||||||
|
if (sculpt_params)
|
||||||
|
{
|
||||||
|
U8 sculpt_type = sculpt_params->getSculptType();
|
||||||
|
U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
|
||||||
|
isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isMesh && objectp)
|
||||||
|
{
|
||||||
|
const LLVolumeParams &volume_params = objectp->getVolume()->getParams();
|
||||||
|
LLUUID mesh_id = volume_params.getSculptID();
|
||||||
|
if(gMeshRepo.hasPhysicsShape(mesh_id))
|
||||||
|
{
|
||||||
|
// if a mesh contains an uploaded or decomposed physics mesh,
|
||||||
|
// allow 'Prim'
|
||||||
|
mComboPhysicsShapeType->add(getString("Prim"), LLSD(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// simple prims always allow physics shape prim
|
||||||
|
mComboPhysicsShapeType->add(getString("Prim"), LLSD(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
mComboPhysicsShapeType->add(getString("Convex Hull"), LLSD(2));
|
||||||
|
mComboPhysicsShapeType->setValue(LLSD(objectp->getPhysicsShapeType()));
|
||||||
|
mComboPhysicsShapeType->setEnabled(editable);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
mObject = objectp;
|
mObject = objectp;
|
||||||
mRootObject = root_objectp;
|
mRootObject = root_objectp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
BOOL LLPanelVolume::precommitValidate( LLUICtrl* ctrl, void* userdata )
|
BOOL LLPanelVolume::precommitValidate(LLUICtrl* ctrl,void* userdata)
|
||||||
{
|
{
|
||||||
// TODO: Richard will fill this in later.
|
// TODO: Richard will fill this in later.
|
||||||
return TRUE; // FALSE means that validation failed and new value should not be commited.
|
return TRUE; // FALSE means that validation failed and new value should not be commited.
|
||||||
@@ -386,11 +475,32 @@ void LLPanelVolume::refresh()
|
|||||||
|
|
||||||
BOOL visible = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE;
|
BOOL visible = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE;
|
||||||
|
|
||||||
childSetVisible("label texture", visible);
|
getChildView("label texture")->setVisible( visible);
|
||||||
childSetVisible("Light FOV", visible);
|
getChildView("Light FOV")->setVisible( visible);
|
||||||
childSetVisible("Light Focus", visible);
|
getChildView("Light Focus")->setVisible( visible);
|
||||||
childSetVisible("Light Ambiance", visible);
|
getChildView("Light Ambiance")->setVisible( visible);
|
||||||
childSetVisible("light texture control", visible);
|
getChildView("light texture control")->setVisible( visible);
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
bool enable_mesh = false;
|
||||||
|
|
||||||
|
LLSD sim_features;
|
||||||
|
LLViewerRegion *region = gAgent.getRegion();
|
||||||
|
if(region)
|
||||||
|
{
|
||||||
|
LLSD sim_features;
|
||||||
|
region->getSimulatorFeatures(sim_features);
|
||||||
|
enable_mesh = sim_features.has("PhysicsShapeTypes");
|
||||||
|
}
|
||||||
|
getChildView("label physicsshapetype")->setVisible(enable_mesh);
|
||||||
|
getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh);
|
||||||
|
getChildView("Physics Gravity")->setVisible(enable_mesh);
|
||||||
|
getChildView("Physics Friction")->setVisible(enable_mesh);
|
||||||
|
getChildView("Physics Density")->setVisible(enable_mesh);
|
||||||
|
getChildView("Physics Restitution")->setVisible(enable_mesh);
|
||||||
|
|
||||||
|
/* TODO: add/remove individual physics shape types as per the PhysicsShapeTypes simulator features */
|
||||||
|
#endif //MESH_ENABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -404,12 +514,12 @@ void LLPanelVolume::clearCtrls()
|
|||||||
{
|
{
|
||||||
LLPanel::clearCtrls();
|
LLPanel::clearCtrls();
|
||||||
|
|
||||||
childSetEnabled("select_single",false);
|
getChildView("select_single")->setEnabled(false);
|
||||||
childSetVisible("select_single",true);
|
getChildView("select_single")->setVisible(true);
|
||||||
childSetEnabled("edit_object",false);
|
getChildView("edit_object")->setEnabled(false);
|
||||||
childSetVisible("edit_object",false);
|
getChildView("edit_object")->setVisible(false);
|
||||||
childSetEnabled("Light Checkbox Ctrl",false);
|
getChildView("Light Checkbox Ctrl")->setEnabled(false);
|
||||||
childSetEnabled("label color",false);
|
getChildView("label color")->setEnabled(false);
|
||||||
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
|
LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
|
||||||
if(LightColorSwatch)
|
if(LightColorSwatch)
|
||||||
{
|
{
|
||||||
@@ -424,19 +534,26 @@ void LLPanelVolume::clearCtrls()
|
|||||||
LightTextureCtrl->setValid( FALSE );
|
LightTextureCtrl->setValid( FALSE );
|
||||||
}
|
}
|
||||||
|
|
||||||
childSetEnabled("Light Intensity",false);
|
getChildView("Light Intensity")->setEnabled(false);
|
||||||
childSetEnabled("Light Radius",false);
|
getChildView("Light Radius")->setEnabled(false);
|
||||||
childSetEnabled("Light Falloff",false);
|
getChildView("Light Falloff")->setEnabled(false);
|
||||||
|
|
||||||
childSetEnabled("Flexible1D Checkbox Ctrl",false);
|
getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);
|
||||||
childSetEnabled("FlexNumSections",false);
|
getChildView("FlexNumSections")->setEnabled(false);
|
||||||
childSetEnabled("FlexGravity",false);
|
getChildView("FlexGravity")->setEnabled(false);
|
||||||
childSetEnabled("FlexTension",false);
|
getChildView("FlexTension")->setEnabled(false);
|
||||||
childSetEnabled("FlexFriction",false);
|
getChildView("FlexFriction")->setEnabled(false);
|
||||||
childSetEnabled("FlexWind",false);
|
getChildView("FlexWind")->setEnabled(false);
|
||||||
childSetEnabled("FlexForceX",false);
|
getChildView("FlexForceX")->setEnabled(false);
|
||||||
childSetEnabled("FlexForceY",false);
|
getChildView("FlexForceY")->setEnabled(false);
|
||||||
childSetEnabled("FlexForceZ",false);
|
getChildView("FlexForceZ")->setEnabled(false);
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
mSpinPhysicsGravity->setEnabled(FALSE);
|
||||||
|
mSpinPhysicsFriction->setEnabled(FALSE);
|
||||||
|
mSpinPhysicsDensity->setEnabled(FALSE);
|
||||||
|
mSpinPhysicsRestitution->setEnabled(FALSE);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -452,7 +569,7 @@ void LLPanelVolume::sendIsLight()
|
|||||||
}
|
}
|
||||||
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
||||||
|
|
||||||
BOOL value = childGetValue("Light Checkbox Ctrl");
|
BOOL value = getChild<LLUICtrl>("Light Checkbox Ctrl")->getValue();
|
||||||
volobjp->setIsLight(value);
|
volobjp->setIsLight(value);
|
||||||
llinfos << "update light sent" << llendl;
|
llinfos << "update light sent" << llendl;
|
||||||
}
|
}
|
||||||
@@ -466,7 +583,7 @@ void LLPanelVolume::sendIsFlexible()
|
|||||||
}
|
}
|
||||||
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
||||||
|
|
||||||
BOOL is_flexible = childGetValue("Flexible1D Checkbox Ctrl");
|
BOOL is_flexible = getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->getValue();
|
||||||
//BOOL is_flexible = mCheckFlexible1D->get();
|
//BOOL is_flexible = mCheckFlexible1D->get();
|
||||||
|
|
||||||
if (is_flexible)
|
if (is_flexible)
|
||||||
@@ -489,6 +606,50 @@ void LLPanelVolume::sendIsFlexible()
|
|||||||
llinfos << "update flexible sent" << llendl;
|
llinfos << "update flexible sent" << llendl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MESH_ENABLED
|
||||||
|
void LLPanelVolume::sendPhysicsShapeType(LLUICtrl* ctrl, void* userdata)
|
||||||
|
{
|
||||||
|
U8 type = ctrl->getValue().asInteger();
|
||||||
|
LLSelectMgr::getInstance()->selectionSetPhysicsType(type);
|
||||||
|
|
||||||
|
refreshCost();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLPanelVolume::sendPhysicsGravity(LLUICtrl* ctrl, void* userdata)
|
||||||
|
{
|
||||||
|
F32 val = ctrl->getValue().asReal();
|
||||||
|
LLSelectMgr::getInstance()->selectionSetGravity(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLPanelVolume::sendPhysicsFriction(LLUICtrl* ctrl, void* userdata)
|
||||||
|
{
|
||||||
|
F32 val = ctrl->getValue().asReal();
|
||||||
|
LLSelectMgr::getInstance()->selectionSetFriction(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLPanelVolume::sendPhysicsRestitution(LLUICtrl* ctrl, void* userdata)
|
||||||
|
{
|
||||||
|
F32 val = ctrl->getValue().asReal();
|
||||||
|
LLSelectMgr::getInstance()->selectionSetRestitution(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLPanelVolume::sendPhysicsDensity(LLUICtrl* ctrl, void* userdata)
|
||||||
|
{
|
||||||
|
F32 val = ctrl->getValue().asReal();
|
||||||
|
LLSelectMgr::getInstance()->selectionSetDensity(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LLPanelVolume::refreshCost()
|
||||||
|
{
|
||||||
|
LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
|
||||||
|
|
||||||
|
if (obj)
|
||||||
|
{
|
||||||
|
obj->getObjectCost();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
void LLPanelVolume::onLightCancelColor(LLUICtrl* ctrl, void* userdata)
|
void LLPanelVolume::onLightCancelColor(LLUICtrl* ctrl, void* userdata)
|
||||||
{
|
{
|
||||||
LLPanelVolume* self = (LLPanelVolume*) userdata;
|
LLPanelVolume* self = (LLPanelVolume*) userdata;
|
||||||
@@ -531,6 +692,7 @@ void LLPanelVolume::onLightSelectColor(LLUICtrl* ctrl, void* userdata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LLPanelVolume::onLightSelectTexture(LLUICtrl* ctrl, void* userdata)
|
void LLPanelVolume::onLightSelectTexture(LLUICtrl* ctrl, void* userdata)
|
||||||
{
|
{
|
||||||
LLPanelVolume* self = (LLPanelVolume*) userdata;
|
LLPanelVolume* self = (LLPanelVolume*) userdata;
|
||||||
@@ -550,6 +712,7 @@ void LLPanelVolume::onLightSelectTexture(LLUICtrl* ctrl, void* userdata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
|
void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
|
||||||
{
|
{
|
||||||
@@ -562,9 +725,9 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
|
|||||||
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
LLVOVolume *volobjp = (LLVOVolume *)objectp;
|
||||||
|
|
||||||
|
|
||||||
volobjp->setLightIntensity((F32)self->childGetValue("Light Intensity").asReal());
|
volobjp->setLightIntensity((F32)self->getChild<LLUICtrl>("Light Intensity")->getValue().asReal());
|
||||||
volobjp->setLightRadius((F32)self->childGetValue("Light Radius").asReal());
|
volobjp->setLightRadius((F32)self->getChild<LLUICtrl>("Light Radius")->getValue().asReal());
|
||||||
volobjp->setLightFalloff((F32)self->childGetValue("Light Falloff").asReal());
|
volobjp->setLightFalloff((F32)self->getChild<LLUICtrl>("Light Falloff")->getValue().asReal());
|
||||||
|
|
||||||
LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch");
|
LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch");
|
||||||
if(LightColorSwatch)
|
if(LightColorSwatch)
|
||||||
@@ -632,14 +795,14 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata )
|
|||||||
new_attributes = *attributes;
|
new_attributes = *attributes;
|
||||||
|
|
||||||
|
|
||||||
new_attributes.setSimulateLOD(self->childGetValue("FlexNumSections").asInteger());//(S32)self->mSpinSections->get());
|
new_attributes.setSimulateLOD(self->getChild<LLUICtrl>("FlexNumSections")->getValue().asInteger());//(S32)self->mSpinSections->get());
|
||||||
new_attributes.setGravity((F32)self->childGetValue("FlexGravity").asReal());
|
new_attributes.setGravity((F32)self->getChild<LLUICtrl>("FlexGravity")->getValue().asReal());
|
||||||
new_attributes.setTension((F32)self->childGetValue("FlexTension").asReal());
|
new_attributes.setTension((F32)self->getChild<LLUICtrl>("FlexTension")->getValue().asReal());
|
||||||
new_attributes.setAirFriction((F32)self->childGetValue("FlexFriction").asReal());
|
new_attributes.setAirFriction((F32)self->getChild<LLUICtrl>("FlexFriction")->getValue().asReal());
|
||||||
new_attributes.setWindSensitivity((F32)self->childGetValue("FlexWind").asReal());
|
new_attributes.setWindSensitivity((F32)self->getChild<LLUICtrl>("FlexWind")->getValue().asReal());
|
||||||
F32 fx = (F32)self->childGetValue("FlexForceX").asReal();
|
F32 fx = (F32)self->getChild<LLUICtrl>("FlexForceX")->getValue().asReal();
|
||||||
F32 fy = (F32)self->childGetValue("FlexForceY").asReal();
|
F32 fy = (F32)self->getChild<LLUICtrl>("FlexForceY")->getValue().asReal();
|
||||||
F32 fz = (F32)self->childGetValue("FlexForceZ").asReal();
|
F32 fz = (F32)self->getChild<LLUICtrl>("FlexForceZ")->getValue().asReal();
|
||||||
LLVector3 force(fx,fy,fz);
|
LLVector3 force(fx,fy,fz);
|
||||||
|
|
||||||
new_attributes.setUserForce(force);
|
new_attributes.setUserForce(force);
|
||||||
|
|||||||
@@ -70,16 +70,31 @@ public:
|
|||||||
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
|
static void onCommitLight( LLUICtrl* ctrl, void* userdata);
|
||||||
static void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
|
static void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata);
|
||||||
static void onCommitFlexible( LLUICtrl* ctrl, void* userdata);
|
static void onCommitFlexible( LLUICtrl* ctrl, void* userdata);
|
||||||
|
#if MESH_ENABLED
|
||||||
|
static void onCommitPhysicsParam( LLUICtrl* ctrl, void* userdata);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
static void onLightCancelColor(LLUICtrl* ctrl, void* userdata);
|
static void onLightCancelColor(LLUICtrl* ctrl, void* userdata);
|
||||||
static void onLightSelectColor(LLUICtrl* ctrl, void* userdata);
|
static void onLightSelectColor(LLUICtrl* ctrl, void* userdata);
|
||||||
|
|
||||||
static void onLightCancelTexture(LLUICtrl* ctrl, void* userdata);
|
static void onLightCancelTexture(LLUICtrl* ctrl, void* userdata);
|
||||||
static void onLightSelectTexture(LLUICtrl* ctrl, void* userdata);
|
static void onLightSelectTexture(LLUICtrl* ctrl, void* userdata);
|
||||||
protected:
|
|
||||||
void getState();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void getState();
|
||||||
|
#if MESH_ENABLED
|
||||||
|
void refreshCost();
|
||||||
|
#endif //MESH_ENABLED
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#if MESH_ENABLED
|
||||||
|
void sendPhysicsShapeType(LLUICtrl* ctrl, void* userdata);
|
||||||
|
void sendPhysicsGravity(LLUICtrl* ctrl, void* userdata);
|
||||||
|
void sendPhysicsFriction(LLUICtrl* ctrl, void* userdata);
|
||||||
|
void sendPhysicsRestitution(LLUICtrl* ctrl, void* userdata);
|
||||||
|
void sendPhysicsDensity(LLUICtrl* ctrl, void* userdata);
|
||||||
|
#endif //MESH_ENABLED
|
||||||
/*
|
/*
|
||||||
LLTextBox* mLabelSelectSingleMessage;
|
LLTextBox* mLabelSelectSingleMessage;
|
||||||
// Light
|
// Light
|
||||||
@@ -104,6 +119,14 @@ protected:
|
|||||||
LLUUID mLightSavedTexture;
|
LLUUID mLightSavedTexture;
|
||||||
LLPointer<LLViewerObject> mObject;
|
LLPointer<LLViewerObject> mObject;
|
||||||
LLPointer<LLViewerObject> mRootObject;
|
LLPointer<LLViewerObject> mRootObject;
|
||||||
|
#if MESH_ENABLED
|
||||||
|
LLTextBox* mComboPhysicsShapeLabel;
|
||||||
|
LLComboBox* mComboPhysicsShapeType;
|
||||||
|
LLSpinCtrl* mSpinPhysicsGravity;
|
||||||
|
LLSpinCtrl* mSpinPhysicsFriction;
|
||||||
|
LLSpinCtrl* mSpinPhysicsDensity;
|
||||||
|
LLSpinCtrl* mSpinPhysicsRestitution;
|
||||||
|
#endif //MESH_ENABLED
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user