This commit is contained in:
Siana Gearz
2011-08-01 19:56:33 +02:00
131 changed files with 18142 additions and 1761 deletions

View File

@@ -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)

View File

@@ -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() ;
} }

View File

@@ -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;

View File

@@ -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()

View File

@@ -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>

View File

@@ -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;

View File

@@ -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

View 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

View File

@@ -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)

View File

@@ -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));
}; };

View File

@@ -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
}; };

View File

@@ -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,

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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)
{ {

View File

@@ -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;

View 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

View 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

View 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

View File

@@ -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

View File

@@ -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

View 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;

View 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

View File

@@ -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);
} }

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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();

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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();

View File

@@ -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

File diff suppressed because it is too large Load Diff

288
indra/llprimitive/llmodel.h Normal file
View 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

View File

@@ -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:

View File

@@ -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
{ {
} }

View File

@@ -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;

View File

@@ -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 );
} }
} }

View File

@@ -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
/////////////////////////////////////// ///////////////////////////////////////

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;
}; };

View File

@@ -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 )

View File

@@ -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;
} }

View File

@@ -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 )
{ {

View File

@@ -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++)
{ {

View File

@@ -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)

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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 );

View File

@@ -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

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);

View 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

View 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

View File

@@ -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()
{ {

View File

@@ -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

View File

@@ -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
View 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
View 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

View File

@@ -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");

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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 },

View File

@@ -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;
} }

View File

@@ -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,

View File

@@ -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;

View File

@@ -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();

View File

@@ -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)

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View 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 &params) 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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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