V3 mesh, texture, and hover merge.
This commit is contained in:
@@ -655,7 +655,6 @@ set(viewer_HEADER_FILES
|
||||
llavataractions.h
|
||||
llavatarpropertiesprocessor.h
|
||||
llbox.h
|
||||
llcallbacklist.h
|
||||
llcallingcard.h
|
||||
llcapabilitylistener.h
|
||||
llcaphttpsender.h
|
||||
|
||||
@@ -70,7 +70,7 @@ void LLCallbackList::addFunction( callback_t func, void *data)
|
||||
}
|
||||
|
||||
|
||||
BOOL LLCallbackList::containsFunction( callback_t func, void *data)
|
||||
bool LLCallbackList::containsFunction( callback_t func, void *data)
|
||||
{
|
||||
callback_pair_t t(func, data);
|
||||
callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
|
||||
@@ -85,7 +85,7 @@ BOOL LLCallbackList::containsFunction( callback_t func, void *data)
|
||||
}
|
||||
|
||||
|
||||
BOOL LLCallbackList::deleteFunction( callback_t func, void *data)
|
||||
bool LLCallbackList::deleteFunction( callback_t func, void *data)
|
||||
{
|
||||
callback_pair_t t(func, data);
|
||||
callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* @file llcallbacklist.h
|
||||
* @brief A simple list of callback functions to call.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLCALLBACKLIST_H
|
||||
#define LL_LLCALLBACKLIST_H
|
||||
|
||||
#include "llstl.h"
|
||||
|
||||
class LLCallbackList
|
||||
{
|
||||
public:
|
||||
typedef void (*callback_t)(void*);
|
||||
|
||||
LLCallbackList();
|
||||
~LLCallbackList();
|
||||
|
||||
void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
|
||||
BOOL containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
|
||||
BOOL deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
|
||||
void callFunctions(); // calls all functions
|
||||
void deleteAllFunctions();
|
||||
|
||||
static void test();
|
||||
|
||||
protected:
|
||||
// Use a list so that the callbacks are ordered in case that matters
|
||||
typedef std::pair<callback_t,void*> callback_pair_t;
|
||||
typedef std::list<callback_pair_t > callback_list_t;
|
||||
callback_list_t mCallbackList;
|
||||
};
|
||||
|
||||
typedef boost::function<void ()> nullary_func_t;
|
||||
typedef boost::function<bool ()> bool_func_t;
|
||||
|
||||
// Call a given callable once in idle loop.
|
||||
void doOnIdleOneTime(nullary_func_t callable);
|
||||
|
||||
// Repeatedly call a callable in idle loop until it returns true.
|
||||
void doOnIdleRepeating(bool_func_t callable);
|
||||
|
||||
// Call a given callable once after specified interval.
|
||||
void doAfterInterval(nullary_func_t callable, F32 seconds);
|
||||
|
||||
// Call a given callable every specified number of seconds, until it returns true.
|
||||
void doPeriodically(bool_func_t callable, F32 seconds);
|
||||
|
||||
extern LLCallbackList gIdleCallbacks;
|
||||
|
||||
#endif
|
||||
@@ -339,6 +339,34 @@ void LLFace::dirtyTexture()
|
||||
gPipeline.markTextured(drawablep);
|
||||
}
|
||||
|
||||
void LLFace::notifyAboutCreatingTexture(LLViewerTexture *texture)
|
||||
{
|
||||
LLDrawable* drawablep = getDrawable();
|
||||
if(mVObjp.notNull() && mVObjp->getVolume())
|
||||
{
|
||||
LLVOVolume *vobj = drawablep->getVOVolume();
|
||||
if(vobj && vobj->notifyAboutCreatingTexture(texture))
|
||||
{
|
||||
gPipeline.markTextured(drawablep);
|
||||
gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFace::notifyAboutMissingAsset(LLViewerTexture *texture)
|
||||
{
|
||||
LLDrawable* drawablep = getDrawable();
|
||||
if(mVObjp.notNull() && mVObjp->getVolume())
|
||||
{
|
||||
LLVOVolume *vobj = drawablep->getVOVolume();
|
||||
if(vobj && vobj->notifyAboutMissingAsset(texture))
|
||||
{
|
||||
gPipeline.markTextured(drawablep);
|
||||
gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture)
|
||||
{
|
||||
llassert(ch < LLRender::NUM_TEXTURE_CHANNELS);
|
||||
@@ -989,6 +1017,10 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po
|
||||
const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset);
|
||||
const LLVector4a& normal = vf.mNormals[0];
|
||||
const LLVector4a& tangent = vf.mTangents[0];
|
||||
if (!&tangent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLVector4a binormal;
|
||||
binormal.setCross3(normal, tangent);
|
||||
@@ -1648,7 +1680,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
||||
do_xform = false;
|
||||
}
|
||||
|
||||
if (getVirtualSize() >= MIN_TEX_ANIM_SIZE)
|
||||
if (getVirtualSize() >= MIN_TEX_ANIM_SIZE || isState(LLFace::RIGGED))
|
||||
{ //don't override texture transform during tc bake
|
||||
tex_mode = 0;
|
||||
}
|
||||
|
||||
@@ -237,6 +237,9 @@ public:
|
||||
|
||||
static U32 getRiggedDataMask(U32 type);
|
||||
|
||||
void notifyAboutCreatingTexture(LLViewerTexture *texture);
|
||||
void notifyAboutMissingAsset(LLViewerTexture *texture);
|
||||
|
||||
public: //aligned members
|
||||
LL_ALIGN_16(LLVector4a mExtents[2]);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,31 +2,25 @@
|
||||
* @file llfloatermodelpreview.h
|
||||
* @brief LLFloaterModelPreview class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2010, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* 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.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* 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.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* 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$
|
||||
*/
|
||||
|
||||
@@ -42,105 +36,24 @@
|
||||
#include "llviewermenufile.h"
|
||||
#include "llfloatermodeluploadbase.h"
|
||||
|
||||
#include "lldaeloader.h"
|
||||
|
||||
class LLComboBox;
|
||||
class LLJoint;
|
||||
class LLViewerJointMesh;
|
||||
class LLVOAvatar;
|
||||
class LLVertexBuffer;
|
||||
class LLModelPreview;
|
||||
class LLFloaterModelPreview;
|
||||
class DAE;
|
||||
class daeElement;
|
||||
class domProfile_COMMON;
|
||||
class domInstance_geometry;
|
||||
class domNode;
|
||||
class domTranslate;
|
||||
class domController;
|
||||
|
||||
typedef std::map<std::string, LLMatrix4> JointTransformMap;
|
||||
typedef std::map<std::string, LLMatrix4>:: iterator JointTransformMapIt;
|
||||
|
||||
const S32 NUM_LOD = 4;
|
||||
|
||||
class LLModelLoader : public LLThread
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
STARTING = 0,
|
||||
READING_FILE,
|
||||
CREATING_FACES,
|
||||
GENERATING_VERTEX_BUFFERS,
|
||||
GENERATING_LOD,
|
||||
DONE,
|
||||
ERROR_PARSING, //basically loading failed
|
||||
ERROR_MATERIALS,
|
||||
} eLoadState;
|
||||
|
||||
U32 mState;
|
||||
std::string mFilename;
|
||||
S32 mLod;
|
||||
LLModelPreview* mPreview;
|
||||
LLMatrix4 mTransform;
|
||||
BOOL mFirstTransform;
|
||||
LLVector3 mExtents[2];
|
||||
bool mTrySLM;
|
||||
|
||||
std::map<daeElement*, LLPointer<LLModel> > mModel;
|
||||
|
||||
typedef std::vector<LLPointer<LLModel> > model_list;
|
||||
model_list mModelList;
|
||||
|
||||
typedef std::vector<LLModelInstance> model_instance_list;
|
||||
|
||||
typedef std::map<LLMatrix4, model_instance_list > scene;
|
||||
|
||||
scene mScene;
|
||||
|
||||
typedef std::queue<LLPointer<LLModel> > model_queue;
|
||||
|
||||
//queue of models that need a physics rep
|
||||
model_queue mPhysicsQ;
|
||||
|
||||
LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap,
|
||||
std::deque<std::string>& jointsFromNodes);
|
||||
~LLModelLoader() ;
|
||||
|
||||
virtual void run();
|
||||
bool doLoadModel();
|
||||
bool loadFromSLM(const std::string& filename);
|
||||
void loadModelCallback();
|
||||
|
||||
void loadTextures() ; //called in the main thread.
|
||||
void processElement(daeElement* element, bool& badElement);
|
||||
std::map<std::string, LLImportMaterial> getMaterials(LLModel* model, domInstance_geometry* instance_geo);
|
||||
LLImportMaterial profileToMaterial(domProfile_COMMON* material);
|
||||
std::string getElementLabel(daeElement *element);
|
||||
LLColor4 getDaeColor(daeElement* element);
|
||||
|
||||
daeElement* getChildFromElement(daeElement* pElement, std::string const & name);
|
||||
|
||||
bool isNodeAJoint(domNode* pNode);
|
||||
void processJointNode(domNode* pNode, std::map<std::string,LLMatrix4>& jointTransforms);
|
||||
void extractTranslation(domTranslate* pTranslate, LLMatrix4& transform);
|
||||
void extractTranslationViaElement(daeElement* pTranslateElement, LLMatrix4& transform);
|
||||
void extractTranslationViaSID(daeElement* pElement, LLMatrix4& transform);
|
||||
|
||||
void setLoadState(U32 state);
|
||||
|
||||
void buildJointToNodeMappingFromScene(daeElement* pRoot);
|
||||
void processJointToNodeMapping(domNode* pNode);
|
||||
void processChildJoints(domNode* pParentNode);
|
||||
|
||||
//map of avatar joints as named in COLLADA assets to internal joint names
|
||||
std::map<std::string, std::string> mJointMap;
|
||||
JointTransformMap& mJointList;
|
||||
std::deque<std::string>& mJointsFromNode;
|
||||
|
||||
S32 mNumOfFetchingTextures ; //updated in the main thread
|
||||
bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
|
||||
|
||||
private:
|
||||
static std::list<LLModelLoader*> sActiveLoaderList;
|
||||
static bool isAlive(LLModelLoader* loader) ;
|
||||
};
|
||||
class domSkin;
|
||||
class domMesh;
|
||||
|
||||
class LLFloaterModelPreview : public LLFloaterModelUploadBase
|
||||
{
|
||||
@@ -171,7 +84,8 @@ public:
|
||||
BOOL handleHover(S32 x, S32 y, MASK mask);
|
||||
BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);
|
||||
|
||||
/*virtual*/ void onOpen(/*const LLSD& key*/);
|
||||
/*virtual*/ void onOpen();
|
||||
/*virtual*/ void onClose(bool app_quitting);
|
||||
|
||||
static void onMouseCaptureLostModelPreview(LLMouseHandler*);
|
||||
static void setUploadAmount(S32 amount) { sUploadAmount = amount; }
|
||||
@@ -211,6 +125,8 @@ public:
|
||||
|
||||
/*virtual*/ void onModelUploadFailure();
|
||||
|
||||
bool isModelUploadAllowed();
|
||||
|
||||
protected:
|
||||
friend class LLModelPreview;
|
||||
friend class LLPhysicsDecomp;
|
||||
@@ -339,8 +255,12 @@ public:
|
||||
void clearModel(S32 lod);
|
||||
void loadModel(std::string filename, S32 lod, bool force_disable_slm = false);
|
||||
void loadModelCallback(S32 lod);
|
||||
bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); }
|
||||
void queryLODs() { mGenLOD = true; };
|
||||
void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false);
|
||||
void genModelBBox(); // Generate just a model BBox if we can't generate proper LOD
|
||||
void generateNormals();
|
||||
void restoreNormals();
|
||||
U32 calcResourceCost();
|
||||
void rebuildUploadData();
|
||||
void saveUploadData(bool save_skinweights, bool save_joint_poisitions);
|
||||
@@ -354,44 +274,51 @@ public:
|
||||
|
||||
const bool getModelPivot(void) const { return mHasPivot; }
|
||||
void setHasPivot(bool val) { mHasPivot = val; }
|
||||
void setModelPivot(const LLVector3& pivot) { mModelPivot = pivot; }
|
||||
void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; }
|
||||
|
||||
//Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps)
|
||||
void critiqueRigForUploadApplicability(const std::vector<std::string> &jointListFromAsset);
|
||||
void critiqueJointToNodeMappingFromScene(void);
|
||||
//Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions
|
||||
//Accessors for joint position upload friendly rigs
|
||||
const bool isRigValidForJointPositionUpload(void) const { return mRigValidJointUpload; }
|
||||
void setRigValidForJointPositionUpload(bool rigValid) { mRigValidJointUpload = rigValid; }
|
||||
bool isRigSuitableForJointPositionUpload(const std::vector<std::string> &jointListFromAsset);
|
||||
//Determines if a rig is a legacy from the joint list
|
||||
bool isRigLegacy(const std::vector<std::string> &jointListFromAsset);
|
||||
const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; }
|
||||
void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; }
|
||||
|
||||
//Accessors for the legacy rigs
|
||||
const bool isLegacyRigValid(void) const { return mLegacyRigValid; }
|
||||
void setLegacyRigValid(bool rigValid) { mLegacyRigValid = rigValid; }
|
||||
//Verify that a controller matches vertex counts
|
||||
bool verifyController(domController* pController);
|
||||
const bool isLegacyRigValid( void ) const { return mLegacyRigValid; }
|
||||
void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; }
|
||||
|
||||
static void textureLoadedCallback(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata);
|
||||
|
||||
boost::signals2::connection setDetailsCallback(const details_signal_t::slot_type& cb){ return mDetailsSignal.connect(cb); }
|
||||
boost::signals2::connection setModelLoadedCallback(const model_loaded_signal_t::slot_type& cb){ return mModelLoadedSignal.connect(cb); }
|
||||
boost::signals2::connection setModelUpdatedCallback(const model_updated_signal_t::slot_type& cb){ return mModelUpdatedSignal.connect(cb); }
|
||||
|
||||
void setLoadState(U32 state) { mLoadState = state; }
|
||||
static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
|
||||
static bool lodQueryCallback();
|
||||
|
||||
boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){ return mDetailsSignal.connect(cb); }
|
||||
boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){ return mModelLoadedSignal.connect(cb); }
|
||||
boost::signals2::connection setModelUpdatedCallback( const model_updated_signal_t::slot_type& cb ){ return mModelUpdatedSignal.connect(cb); }
|
||||
|
||||
void setLoadState( U32 state ) { mLoadState = state; }
|
||||
U32 getLoadState() { return mLoadState; }
|
||||
void setRigWithSceneParity(bool state) { mRigParityWithScene = state; }
|
||||
const bool getRigWithSceneParity(void) const { return mRigParityWithScene; }
|
||||
void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; }
|
||||
const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; }
|
||||
|
||||
LLVector3 getTranslationForJointOffset( std::string joint );
|
||||
|
||||
LLVector3 getTranslationForJointOffset(std::string joint);
|
||||
static bool sIgnoreLoadedCallback;
|
||||
std::vector<S32> mLodsQuery;
|
||||
|
||||
protected:
|
||||
|
||||
static void loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque);
|
||||
static void stateChangedCallback(U32 state, void* opaque);
|
||||
|
||||
static LLJoint* lookupJointByName(const std::string&, void* opaque);
|
||||
static U32 loadTextures(LLImportMaterial& material, void* opaque);
|
||||
|
||||
private:
|
||||
//Utility function for controller vertex compare
|
||||
bool verifyCount(int expected, int result);
|
||||
bool verifyCount( int expected, int result );
|
||||
//Creates the dummy avatar for the preview window
|
||||
void createPreviewAvatar(void);
|
||||
void createPreviewAvatar( void );
|
||||
//Accessor for the dummy avatar
|
||||
LLVOAvatar* getPreviewAvatar(void) { return mPreviewAvatar; }
|
||||
LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; }
|
||||
// Count amount of original models, excluding sub-models
|
||||
static U32 countRootModels(LLModelLoader::model_list models);
|
||||
|
||||
protected:
|
||||
friend class LLModelLoader;
|
||||
@@ -413,12 +340,14 @@ private:
|
||||
LLVector3 mPreviewTarget;
|
||||
LLVector3 mPreviewScale;
|
||||
S32 mPreviewLOD;
|
||||
S32 mPhysicsSearchLOD;
|
||||
U32 mResourceCost;
|
||||
std::string mLODFile[LLModel::NUM_LODS];
|
||||
bool mLoading;
|
||||
U32 mLoadState;
|
||||
bool mResetJoints;
|
||||
bool mRigParityWithScene;
|
||||
bool mModelNoErrors;
|
||||
|
||||
std::map<std::string, bool> mViewOption;
|
||||
|
||||
@@ -445,6 +374,12 @@ private:
|
||||
LLModelLoader::model_list mModel[LLModel::NUM_LODS];
|
||||
LLModelLoader::model_list mBaseModel;
|
||||
|
||||
typedef std::vector<LLVolumeFace> v_LLVolumeFace_t;
|
||||
typedef std::vector<v_LLVolumeFace_t> vv_LLVolumeFace_t;
|
||||
|
||||
vv_LLVolumeFace_t mModelFacesCopy[LLModel::NUM_LODS];
|
||||
vv_LLVolumeFace_t mBaseModelFacesCopy;
|
||||
|
||||
U32 mGroup;
|
||||
std::map<LLPointer<LLModel>, U32> mObject;
|
||||
U32 mMaxTriangleLimit;
|
||||
@@ -463,16 +398,15 @@ private:
|
||||
bool mHasPivot;
|
||||
|
||||
float mPelvisZOffset;
|
||||
|
||||
|
||||
bool mRigValidJointUpload;
|
||||
bool mLegacyRigValid;
|
||||
|
||||
bool mLastJointUpdate;
|
||||
|
||||
std::deque<std::string> mMasterJointList;
|
||||
std::deque<std::string> mMasterLegacyJointList;
|
||||
std::deque<std::string> mJointsFromNode;
|
||||
JointTransformMap mJointTransformMap;
|
||||
JointSet mJointsFromNode;
|
||||
JointTransformMap mJointTransformMap;
|
||||
|
||||
LLPointer<LLVOAvatar> mPreviewAvatar;
|
||||
};
|
||||
|
||||
|
||||
@@ -124,6 +124,7 @@ std::string header_lod[] =
|
||||
"medium_lod",
|
||||
"high_lod"
|
||||
};
|
||||
const char * const LOG_MESH = "Mesh";
|
||||
|
||||
|
||||
//get the number of bytes resident in memory for given volume
|
||||
@@ -206,6 +207,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res,
|
||||
}
|
||||
}
|
||||
|
||||
LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material)
|
||||
{
|
||||
LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData);
|
||||
return ppTex ? (*ppTex).get() : NULL;
|
||||
}
|
||||
|
||||
S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
|
||||
S32 LLMeshRepoThread::sActiveLODRequests = 0;
|
||||
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
|
||||
@@ -1429,6 +1436,13 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
|
||||
{
|
||||
LLMeshUploadData data;
|
||||
data.mBaseModel = iter->first;
|
||||
|
||||
if (data.mBaseModel->mSubmodelID)
|
||||
{
|
||||
// These are handled below to insure correct parenting order on creation
|
||||
// due to map walking being based on model address (aka random)
|
||||
continue;
|
||||
}
|
||||
LLModelInstance& first_instance = *(iter->second.begin());
|
||||
for (S32 i = 0; i < 5; i++)
|
||||
{
|
||||
@@ -1466,7 +1480,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
|
||||
data.mModel[LLModel::LOD_IMPOSTOR],
|
||||
decomp,
|
||||
mUploadSkin,
|
||||
mUploadJoints);
|
||||
mUploadJoints,
|
||||
FALSE,
|
||||
FALSE,
|
||||
data.mBaseModel->mSubmodelID);
|
||||
|
||||
data.mAssetData = ostr.str();
|
||||
std::string str = ostr.str();
|
||||
@@ -1500,17 +1517,26 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
|
||||
instance_entry["scale"] = ll_sd_from_vector3(scale);
|
||||
|
||||
instance_entry["material"] = LL_MCODE_WOOD;
|
||||
instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
|
||||
instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL);
|
||||
instance_entry["mesh"] = mesh_index[data.mBaseModel];
|
||||
|
||||
instance_entry["face_list"] = LLSD::emptyArray();
|
||||
|
||||
S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ;
|
||||
// We want to be able to allow more than 8 materials...
|
||||
//
|
||||
S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
|
||||
|
||||
for (S32 face_num = 0; face_num < end; face_num++)
|
||||
{
|
||||
LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
|
||||
LLSD face_entry = LLSD::emptyMap();
|
||||
LLViewerFetchedTexture *texture = material.mDiffuseMap.get();
|
||||
|
||||
LLViewerFetchedTexture *texture = NULL;
|
||||
|
||||
if (material.mDiffuseMapFilename.size())
|
||||
{
|
||||
texture = FindViewerTexture(material);
|
||||
}
|
||||
|
||||
if ((texture != NULL) &&
|
||||
(textures.find(texture) == textures.end()))
|
||||
@@ -1525,9 +1551,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures)
|
||||
{
|
||||
LLPointer<LLImageJ2C> upload_file =
|
||||
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
|
||||
|
||||
if (!upload_file.isNull() && upload_file->getDataSize())
|
||||
{
|
||||
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (texture != NULL &&
|
||||
mUploadTextures &&
|
||||
texture_index.find(texture) == texture_index.end())
|
||||
{
|
||||
texture_index[texture] = texture_num;
|
||||
std::string str = texture_str.str();
|
||||
res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end());
|
||||
texture_num++;
|
||||
}
|
||||
|
||||
// Subset of TextureEntry fields.
|
||||
if (texture != NULL && mUploadTextures)
|
||||
{
|
||||
face_entry["image"] = texture_index[texture];
|
||||
face_entry["scales"] = 1.0;
|
||||
face_entry["scalet"] = 1.0;
|
||||
face_entry["offsets"] = 0.0;
|
||||
face_entry["offsett"] = 0.0;
|
||||
face_entry["imagerot"] = 0.0;
|
||||
}
|
||||
face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor);
|
||||
face_entry["fullbright"] = material.mFullbright;
|
||||
instance_entry["face_list"][face_num] = face_entry;
|
||||
}
|
||||
|
||||
res["instance_list"][instance_num] = instance_entry;
|
||||
instance_num++;
|
||||
}
|
||||
}
|
||||
|
||||
for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter)
|
||||
{
|
||||
LLMeshUploadData data;
|
||||
data.mBaseModel = iter->first;
|
||||
|
||||
if (!data.mBaseModel->mSubmodelID)
|
||||
{
|
||||
// These were handled above already...
|
||||
//
|
||||
continue;
|
||||
}
|
||||
|
||||
LLModelInstance& first_instance = *(iter->second.begin());
|
||||
for (S32 i = 0; i < 5; i++)
|
||||
{
|
||||
data.mModel[i] = first_instance.mLOD[i];
|
||||
}
|
||||
|
||||
if (mesh_index.find(data.mBaseModel) == mesh_index.end())
|
||||
{
|
||||
// Have not seen this model before - create a new mesh_list entry for it.
|
||||
if (model_name.empty())
|
||||
{
|
||||
model_name = data.mBaseModel->getName();
|
||||
}
|
||||
|
||||
if (model_metric.empty())
|
||||
{
|
||||
model_metric = data.mBaseModel->getMetric();
|
||||
}
|
||||
|
||||
std::stringstream ostr;
|
||||
|
||||
LLModel::Decomposition& decomp =
|
||||
data.mModel[LLModel::LOD_PHYSICS].notNull() ?
|
||||
data.mModel[LLModel::LOD_PHYSICS]->mPhysics :
|
||||
data.mBaseModel->mPhysics;
|
||||
|
||||
decomp.mBaseHull = mHullMap[data.mBaseModel];
|
||||
|
||||
LLSD mesh_header = LLModel::writeModel(
|
||||
ostr,
|
||||
data.mModel[LLModel::LOD_PHYSICS],
|
||||
data.mModel[LLModel::LOD_HIGH],
|
||||
data.mModel[LLModel::LOD_MEDIUM],
|
||||
data.mModel[LLModel::LOD_LOW],
|
||||
data.mModel[LLModel::LOD_IMPOSTOR],
|
||||
decomp,
|
||||
mUploadSkin,
|
||||
mUploadJoints,
|
||||
FALSE,
|
||||
FALSE,
|
||||
data.mBaseModel->mSubmodelID);
|
||||
|
||||
data.mAssetData = ostr.str();
|
||||
std::string str = ostr.str();
|
||||
|
||||
res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end());
|
||||
mesh_index[data.mBaseModel] = mesh_num;
|
||||
mesh_num++;
|
||||
}
|
||||
|
||||
// For all instances that use this model
|
||||
for (instance_list::iterator instance_iter = iter->second.begin();
|
||||
instance_iter != iter->second.end();
|
||||
++instance_iter)
|
||||
{
|
||||
|
||||
LLModelInstance& instance = *instance_iter;
|
||||
|
||||
LLSD instance_entry;
|
||||
|
||||
for (S32 i = 0; i < 5; i++)
|
||||
{
|
||||
data.mModel[i] = instance.mLOD[i];
|
||||
}
|
||||
|
||||
LLVector3 pos, scale;
|
||||
LLQuaternion rot;
|
||||
LLMatrix4 transformation = instance.mTransform;
|
||||
decomposeMeshMatrix(transformation,pos,rot,scale);
|
||||
instance_entry["position"] = ll_sd_from_vector3(pos);
|
||||
instance_entry["rotation"] = ll_sd_from_quaternion(rot);
|
||||
instance_entry["scale"] = ll_sd_from_vector3(scale);
|
||||
|
||||
instance_entry["material"] = LL_MCODE_WOOD;
|
||||
instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE);
|
||||
instance_entry["mesh"] = mesh_index[data.mBaseModel];
|
||||
|
||||
instance_entry["face_list"] = LLSD::emptyArray();
|
||||
|
||||
// We want to be able to allow more than 8 materials...
|
||||
//
|
||||
S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ;
|
||||
|
||||
for (S32 face_num = 0; face_num < end; face_num++)
|
||||
{
|
||||
LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]];
|
||||
LLSD face_entry = LLSD::emptyMap();
|
||||
|
||||
LLViewerFetchedTexture *texture = NULL;
|
||||
|
||||
if (material.mDiffuseMapFilename.size())
|
||||
{
|
||||
texture = FindViewerTexture(material);
|
||||
}
|
||||
|
||||
if ((texture != NULL) &&
|
||||
(textures.find(texture) == textures.end()))
|
||||
{
|
||||
textures.insert(texture);
|
||||
}
|
||||
|
||||
std::stringstream texture_str;
|
||||
if (texture != NULL && include_textures && mUploadTextures)
|
||||
{
|
||||
if(texture->hasSavedRawImage())
|
||||
{
|
||||
LLPointer<LLImageJ2C> upload_file =
|
||||
LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage());
|
||||
|
||||
if (!upload_file.isNull() && upload_file->getDataSize())
|
||||
{
|
||||
texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (texture != NULL &&
|
||||
mUploadTextures &&
|
||||
@@ -2165,7 +2353,7 @@ void LLMeshRepository::init()
|
||||
|
||||
void LLMeshRepository::shutdown()
|
||||
{
|
||||
LL_INFOS() << "Shutting down mesh repository." << LL_ENDL;
|
||||
LL_INFOS(LOG_MESH) << "Shutting down mesh repository." << LL_ENDL;
|
||||
|
||||
mThread->mSignal->signal();
|
||||
|
||||
@@ -2179,7 +2367,7 @@ void LLMeshRepository::shutdown()
|
||||
delete mMeshMutex;
|
||||
mMeshMutex = NULL;
|
||||
|
||||
LL_INFOS() << "Shutting down decomposition system." << LL_ENDL;
|
||||
LL_INFOS(LOG_MESH) << "Shutting down decomposition system." << LL_ENDL;
|
||||
|
||||
if (mDecompThread)
|
||||
{
|
||||
@@ -2407,7 +2595,8 @@ void LLMeshRepository::notifyLoadedMeshes()
|
||||
}
|
||||
|
||||
//sort by "score"
|
||||
std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
|
||||
std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count,
|
||||
mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater());
|
||||
|
||||
while (!mPendingRequests.empty() && push_count > 0)
|
||||
{
|
||||
@@ -2461,9 +2650,8 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info)
|
||||
vobj->notifyMeshLoaded();
|
||||
}
|
||||
}
|
||||
mLoadingSkins.erase(info.mMeshID);
|
||||
}
|
||||
|
||||
mLoadingSkins.erase(info.mMeshID);
|
||||
}
|
||||
|
||||
void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp)
|
||||
@@ -2472,18 +2660,18 @@ void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decom
|
||||
if (iter == mDecompositionMap.end())
|
||||
{ //just insert decomp into map
|
||||
mDecompositionMap[decomp->mMeshID] = decomp;
|
||||
mLoadingDecompositions.erase(decomp->mMeshID);
|
||||
}
|
||||
else
|
||||
{ //merge decomp with existing entry
|
||||
{ //merge decomp with existing entry
|
||||
iter->second->merge(decomp);
|
||||
mLoadingDecompositions.erase(decomp->mMeshID);
|
||||
delete decomp;
|
||||
}
|
||||
|
||||
mLoadingDecompositions.erase(decomp->mMeshID);
|
||||
}
|
||||
|
||||
void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume)
|
||||
{ //called from main thread
|
||||
{ //called from main thread
|
||||
S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail());
|
||||
|
||||
//get list of objects waiting to be notified this mesh is loaded
|
||||
@@ -2494,7 +2682,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
|
||||
//make sure target volume is still valid
|
||||
if (volume->getNumVolumeFaces() <= 0)
|
||||
{
|
||||
LL_WARNS() << "Mesh loading returned empty volume." << LL_ENDL;
|
||||
LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_params.getSculptID()
|
||||
<< LL_ENDL;
|
||||
}
|
||||
|
||||
{ //update system volume
|
||||
@@ -2507,7 +2696,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Couldn't find system volume for given mesh." << LL_ENDL;
|
||||
LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID()
|
||||
<< LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2774,37 +2964,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation,
|
||||
result_rot = quat_rotation;
|
||||
}
|
||||
|
||||
bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const
|
||||
{
|
||||
if (mDiffuseMap != rhs.mDiffuseMap)
|
||||
{
|
||||
return mDiffuseMap < rhs.mDiffuseMap;
|
||||
}
|
||||
|
||||
if (mDiffuseMapFilename != rhs.mDiffuseMapFilename)
|
||||
{
|
||||
return mDiffuseMapFilename < rhs.mDiffuseMapFilename;
|
||||
}
|
||||
|
||||
if (mDiffuseMapLabel != rhs.mDiffuseMapLabel)
|
||||
{
|
||||
return mDiffuseMapLabel < rhs.mDiffuseMapLabel;
|
||||
}
|
||||
|
||||
if (mDiffuseColor != rhs.mDiffuseColor)
|
||||
{
|
||||
return mDiffuseColor < rhs.mDiffuseColor;
|
||||
}
|
||||
|
||||
if (mBinding != rhs.mBinding)
|
||||
{
|
||||
return mBinding < rhs.mBinding;
|
||||
}
|
||||
|
||||
return mFullbright < rhs.mFullbright;
|
||||
}
|
||||
|
||||
|
||||
void LLMeshRepository::updateInventory(inventory_data data)
|
||||
{
|
||||
LLMutexLock lock(mMeshMutex);
|
||||
@@ -3036,7 +3195,7 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh, bool vertex_based)
|
||||
|
||||
if (ret)
|
||||
{
|
||||
LL_ERRS() << "Convex Decomposition thread valid but could not set mesh data" << LL_ENDL;
|
||||
LL_ERRS(LOG_MESH) << "Convex Decomposition thread valid but could not set mesh data." << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3112,7 +3271,8 @@ void LLPhysicsDecomp::doDecomposition()
|
||||
|
||||
if (ret)
|
||||
{
|
||||
LL_WARNS() << "Convex Decomposition thread valid but could not execute stage " << stage << LL_ENDL;
|
||||
LL_WARNS(LOG_MESH) << "Convex Decomposition thread valid but could not execute stage " << stage << "."
|
||||
<< LL_ENDL;
|
||||
LLMutexLock lock(mMutex);
|
||||
|
||||
mCurRequest->mHull.clear();
|
||||
@@ -3243,7 +3403,7 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
|
||||
LLCDResult ret = decomp->buildSingleHull() ;
|
||||
if(ret)
|
||||
{
|
||||
LL_WARNS() << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL;
|
||||
LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL;
|
||||
make_box(mCurRequest);
|
||||
}
|
||||
else
|
||||
@@ -3491,60 +3651,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg)
|
||||
mStatusMessage = msg;
|
||||
}
|
||||
|
||||
LLModelInstance::LLModelInstance(LLSD& data)
|
||||
{
|
||||
mLocalMeshID = data["mesh_id"].asInteger();
|
||||
mLabel = data["label"].asString();
|
||||
mTransform.setValue(data["transform"]);
|
||||
|
||||
for (U32 i = 0; i < (U32)data["material"].size(); ++i)
|
||||
{
|
||||
LLImportMaterial mat(data["material"][i]);
|
||||
mMaterial[mat.mBinding] = mat;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LLSD LLModelInstance::asLLSD()
|
||||
{
|
||||
LLSD ret;
|
||||
|
||||
ret["mesh_id"] = mModel->mLocalID;
|
||||
ret["label"] = mLabel;
|
||||
ret["transform"] = mTransform.getValue();
|
||||
|
||||
U32 i = 0;
|
||||
for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter)
|
||||
{
|
||||
ret["material"][i++] = iter->second.asLLSD();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
LLImportMaterial::LLImportMaterial(LLSD& data)
|
||||
{
|
||||
mDiffuseMapFilename = data["diffuse"]["filename"].asString();
|
||||
mDiffuseMapLabel = data["diffuse"]["label"].asString();
|
||||
mDiffuseColor.setValue(data["diffuse"]["color"]);
|
||||
mFullbright = data["fullbright"].asBoolean();
|
||||
mBinding = data["binding"].asString();
|
||||
}
|
||||
|
||||
|
||||
LLSD LLImportMaterial::asLLSD()
|
||||
{
|
||||
LLSD ret;
|
||||
|
||||
ret["diffuse"]["filename"] = mDiffuseMapFilename;
|
||||
ret["diffuse"]["label"] = mDiffuseMapLabel;
|
||||
ret["diffuse"]["color"] = mDiffuseColor.getValue();
|
||||
ret["fullbright"] = mFullbright;
|
||||
ret["binding"] = mBinding;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp)
|
||||
{
|
||||
decomp.mMesh.resize(decomp.mHull.size());
|
||||
|
||||
@@ -92,54 +92,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class LLImportMaterial
|
||||
{
|
||||
public:
|
||||
LLPointer<LLViewerFetchedTexture> mDiffuseMap;
|
||||
std::string mDiffuseMapFilename;
|
||||
std::string mDiffuseMapLabel;
|
||||
std::string mBinding;
|
||||
LLColor4 mDiffuseColor;
|
||||
bool mFullbright;
|
||||
|
||||
bool operator<(const LLImportMaterial ¶ms) const;
|
||||
|
||||
LLImportMaterial()
|
||||
: mFullbright(false)
|
||||
{
|
||||
mDiffuseColor.set(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
LLImportMaterial(LLSD& data);
|
||||
|
||||
LLSD asLLSD();
|
||||
};
|
||||
|
||||
class LLModelInstance
|
||||
{
|
||||
public:
|
||||
LLPointer<LLModel> mModel;
|
||||
LLPointer<LLModel> mLOD[5];
|
||||
|
||||
std::string mLabel;
|
||||
|
||||
LLUUID mMeshID;
|
||||
S32 mLocalMeshID;
|
||||
|
||||
LLMatrix4 mTransform;
|
||||
std::map<std::string, LLImportMaterial> mMaterial;
|
||||
|
||||
LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials)
|
||||
: mModel(model), mLabel(label), mTransform(transform), mMaterial(materials)
|
||||
{
|
||||
mLocalMeshID = -1;
|
||||
}
|
||||
|
||||
LLModelInstance(LLSD& data);
|
||||
|
||||
LLSD asLLSD();
|
||||
};
|
||||
|
||||
class LLPhysicsDecomp : public LLThread
|
||||
{
|
||||
public:
|
||||
@@ -441,6 +393,7 @@ public:
|
||||
void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
|
||||
void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
|
||||
|
||||
LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material);
|
||||
private:
|
||||
LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
|
||||
LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
|
||||
|
||||
@@ -372,10 +372,17 @@ void LLViewerObject::markDead()
|
||||
//</singu>
|
||||
|
||||
// Root object of this hierarchy unlinks itself.
|
||||
LLVOAvatar *av = getAvatarAncestor();
|
||||
if (getParent())
|
||||
{
|
||||
((LLViewerObject *)getParent())->removeChild(this);
|
||||
}
|
||||
LLUUID mesh_id;
|
||||
if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id))
|
||||
{
|
||||
// This case is needed for indirectly attached mesh objects.
|
||||
av->resetJointPositionsOnDetach(mesh_id);
|
||||
}
|
||||
|
||||
// Mark itself as dead
|
||||
mDead = TRUE;
|
||||
@@ -4798,6 +4805,22 @@ LLVOAvatar* LLViewerObject::asAvatar()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If this object is directly or indirectly parented by an avatar, return it.
|
||||
LLVOAvatar* LLViewerObject::getAvatarAncestor()
|
||||
{
|
||||
LLViewerObject *pobj = (LLViewerObject*) getParent();
|
||||
while (pobj)
|
||||
{
|
||||
LLVOAvatar *av = pobj->asAvatar();
|
||||
if (av)
|
||||
{
|
||||
return av;
|
||||
}
|
||||
pobj = (LLViewerObject*) pobj->getParent();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL LLViewerObject::isParticleSource() const
|
||||
{
|
||||
return !mPartSourcep.isNull() && !mPartSourcep->isDead();
|
||||
|
||||
@@ -141,6 +141,8 @@ public:
|
||||
|
||||
virtual LLVOAvatar* asAvatar();
|
||||
|
||||
LLVOAvatar* getAvatarAncestor();
|
||||
|
||||
static void initVOClasses();
|
||||
static void cleanupVOClasses();
|
||||
|
||||
|
||||
@@ -536,7 +536,6 @@ void output_statistics(void*)
|
||||
LL_INFOS() << "--------------------------------" << LL_ENDL;
|
||||
LL_INFOS() << "Avatar Memory (partly overlaps with above stats):" << LL_ENDL;
|
||||
LLTexLayerStaticImageList::getInstance()->dumpByteCount();
|
||||
LLVOAvatarSelf::dumpScratchTextureByteCount();
|
||||
LLViewerTexLayerSetBuffer::dumpTotalByteCount();
|
||||
LLVOAvatarSelf::dumpTotalLocalTextureByteCount();
|
||||
LLTexLayerParamAlpha::dumpCacheByteCount();
|
||||
|
||||
@@ -614,6 +614,7 @@ LLViewerTexture::~LLViewerTexture()
|
||||
// virtual
|
||||
void LLViewerTexture::init(bool firstinit)
|
||||
{
|
||||
mSelectedTime = 0.f;
|
||||
mMaxVirtualSize = 0.f;
|
||||
mNeedsGLTexture = FALSE ;
|
||||
mMaxVirtualSizeResetInterval = 1;
|
||||
@@ -639,12 +640,37 @@ S8 LLViewerTexture::getType() const
|
||||
|
||||
void LLViewerTexture::cleanup()
|
||||
{
|
||||
mFaceList[LLRender::DIFFUSE_MAP].clear() ;
|
||||
mFaceList[LLRender::NORMAL_MAP].clear() ;
|
||||
notifyAboutMissingAsset();
|
||||
|
||||
mFaceList[LLRender::DIFFUSE_MAP].clear();
|
||||
mFaceList[LLRender::NORMAL_MAP].clear();
|
||||
mFaceList[LLRender::SPECULAR_MAP].clear() ;
|
||||
mVolumeList.clear();
|
||||
}
|
||||
|
||||
void LLViewerTexture::notifyAboutCreatingTexture()
|
||||
{
|
||||
for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
|
||||
{
|
||||
for(U32 f = 0; f < mNumFaces[ch]; f++)
|
||||
{
|
||||
mFaceList[ch][f]->notifyAboutCreatingTexture(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerTexture::notifyAboutMissingAsset()
|
||||
{
|
||||
for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch)
|
||||
{
|
||||
for(U32 f = 0; f < mNumFaces[ch]; f++)
|
||||
{
|
||||
mFaceList[ch][f]->notifyAboutMissingAsset(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLViewerTexture::dump()
|
||||
{
|
||||
LLGLTexture::dump();
|
||||
@@ -654,6 +680,30 @@ void LLViewerTexture::dump()
|
||||
<< LL_ENDL;
|
||||
}
|
||||
|
||||
void LLViewerTexture::setBoostLevel(S32 level)
|
||||
{
|
||||
if(mBoostLevel != level)
|
||||
{
|
||||
mBoostLevel = level;
|
||||
if(mBoostLevel != LLViewerTexture::BOOST_NONE &&
|
||||
mBoostLevel != LLViewerTexture::BOOST_SELECTED)
|
||||
{
|
||||
setNoDelete();
|
||||
}
|
||||
}
|
||||
|
||||
if (mBoostLevel == LLViewerTexture::BOOST_SELECTED)
|
||||
{
|
||||
mSelectedTime = gFrameTimeSeconds;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool LLViewerTexture::isActiveFetching()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLViewerTexture::bindDefaultImage(S32 stage)
|
||||
{
|
||||
if (stage < 0) return false;
|
||||
@@ -945,6 +995,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
|
||||
{
|
||||
mOrigWidth = 0;
|
||||
mOrigHeight = 0;
|
||||
mHasAux = FALSE;
|
||||
mNeedsAux = FALSE;
|
||||
mRequestedDiscardLevel = -1;
|
||||
mRequestedDownloadPriority = 0.f;
|
||||
@@ -1002,6 +1053,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
|
||||
mLastReferencedSavedRawImageTime = 0.0f ;
|
||||
mKeptSavedRawImageTime = 0.f ;
|
||||
mLastCallBackActiveTime = 0.f;
|
||||
mForceCallbackFetch = FALSE;
|
||||
}
|
||||
|
||||
LLViewerFetchedTexture::~LLViewerFetchedTexture()
|
||||
@@ -1348,6 +1400,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
|
||||
//{
|
||||
res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel);
|
||||
//resetFaceAtlas() ;
|
||||
notifyAboutCreatingTexture();
|
||||
//}
|
||||
setActive() ;
|
||||
}
|
||||
@@ -1666,6 +1719,14 @@ void LLViewerFetchedTexture::updateVirtualSize()
|
||||
}
|
||||
}
|
||||
}
|
||||
//reset whether or not a face was selected after 10 seconds
|
||||
const F32 SELECTION_RESET_TIME = 10.f;
|
||||
|
||||
if (getBoostLevel() == LLViewerTexture::BOOST_SELECTED &&
|
||||
gFrameTimeSeconds - mSelectedTime > SELECTION_RESET_TIME)
|
||||
{
|
||||
setBoostLevel(LLViewerTexture::BOOST_NONE);
|
||||
}
|
||||
|
||||
if(mMaxVirtualSizeResetCounter > 0)
|
||||
{
|
||||
@@ -1693,6 +1754,27 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching()
|
||||
return current_discard ;
|
||||
}
|
||||
|
||||
bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level)
|
||||
{
|
||||
if(debug_level < 0)
|
||||
{
|
||||
mInDebug = FALSE;
|
||||
return false;
|
||||
}
|
||||
mInDebug = TRUE;
|
||||
|
||||
mDesiredDiscardLevel = debug_level;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLViewerFetchedTexture::isActiveFetching()
|
||||
{
|
||||
static LLCachedControl<bool> monitor_enabled(gSavedSettings,"DebugShowTextureInfo");
|
||||
|
||||
return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE.
|
||||
}
|
||||
|
||||
bool LLViewerFetchedTexture::updateFetch()
|
||||
{
|
||||
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled");
|
||||
@@ -1745,7 +1827,11 @@ bool LLViewerFetchedTexture::updateFetch()
|
||||
if (mAuxRawImage.notNull()) sAuxCount--;
|
||||
bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage);
|
||||
if (mRawImage.notNull()) sRawCount++;
|
||||
if (mAuxRawImage.notNull()) sAuxCount++;
|
||||
if (mAuxRawImage.notNull())
|
||||
{
|
||||
mHasAux = TRUE;
|
||||
sAuxCount++;
|
||||
}
|
||||
if (finished)
|
||||
{
|
||||
mIsFetching = FALSE;
|
||||
@@ -1808,7 +1894,7 @@ bool LLViewerFetchedTexture::updateFetch()
|
||||
if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL))
|
||||
{
|
||||
// We finished but received no data
|
||||
if (current_discard < 0)
|
||||
if (getDiscardLevel() < 0)
|
||||
{
|
||||
LL_WARNS() << "!mIsFetching, setting as missing, decode_priority " << decode_priority
|
||||
<< " mRawDiscardLevel " << mRawDiscardLevel
|
||||
@@ -1820,8 +1906,17 @@ bool LLViewerFetchedTexture::updateFetch()
|
||||
else
|
||||
{
|
||||
//LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL;
|
||||
mMinDiscardLevel = current_discard;
|
||||
desired_discard = current_discard;
|
||||
if(current_discard >= 0)
|
||||
{
|
||||
mMinDiscardLevel = current_discard;
|
||||
desired_discard = current_discard;
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 dis_level = getDiscardLevel();
|
||||
mMinDiscardLevel = dis_level;
|
||||
desired_discard = dis_level;
|
||||
}
|
||||
}
|
||||
destroyRawImage();
|
||||
}
|
||||
@@ -1959,6 +2054,22 @@ bool LLViewerFetchedTexture::updateFetch()
|
||||
return mIsFetching ? true : false;
|
||||
}
|
||||
|
||||
void LLViewerFetchedTexture::clearFetchedResults()
|
||||
{
|
||||
if(mNeedsCreateTexture || mIsFetching)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
destroyGLTexture();
|
||||
|
||||
if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate
|
||||
{
|
||||
mGLTexturep->forceToInvalidateGLTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void LLViewerFetchedTexture::forceToDeleteRequest()
|
||||
{
|
||||
if (mHasFetcher)
|
||||
@@ -1973,26 +2084,42 @@ void LLViewerFetchedTexture::forceToDeleteRequest()
|
||||
mDesiredDiscardLevel = getMaxDiscardLevel() + 1; //defer LLAppViewer::getTextureFetch()->deleteRequest to updateFetch?
|
||||
}
|
||||
|
||||
void LLViewerFetchedTexture::setIsMissingAsset()
|
||||
void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing)
|
||||
{
|
||||
if (mUrl.empty())
|
||||
if (is_missing == mIsMissingAsset)
|
||||
{
|
||||
LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
if (is_missing)
|
||||
{
|
||||
notifyAboutMissingAsset();
|
||||
|
||||
if (mUrl.empty())
|
||||
{
|
||||
LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This may or may not be an error - it is normal to have no
|
||||
// map tile on an empty region, but bad if we're failing on a
|
||||
// server bake texture.
|
||||
LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL;
|
||||
}
|
||||
if (mHasFetcher)
|
||||
{
|
||||
LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
|
||||
mHasFetcher = FALSE;
|
||||
mIsFetching = FALSE;
|
||||
mLastPacketTimer.reset();
|
||||
mFetchState = 0;
|
||||
mFetchPriority = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL;
|
||||
LL_INFOS() << mID << ": un-flagging missing asset" << LL_ENDL;
|
||||
}
|
||||
if (mHasFetcher)
|
||||
{
|
||||
LLAppViewer::getTextureFetch()->deleteRequest(getID(), true);
|
||||
mHasFetcher = FALSE;
|
||||
mIsFetching = FALSE;
|
||||
mLastPacketTimer.reset();
|
||||
mFetchState = 0;
|
||||
mFetchPriority = 0;
|
||||
}
|
||||
mIsMissingAsset = TRUE;
|
||||
mIsMissingAsset = is_missing;
|
||||
}
|
||||
|
||||
void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback,
|
||||
@@ -2035,10 +2162,19 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call
|
||||
}
|
||||
if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0)
|
||||
{
|
||||
// We need aux data, but we've already loaded the image, and it didn't have any
|
||||
LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL;
|
||||
if(mHasAux)
|
||||
{
|
||||
//trigger a refetch
|
||||
forceToRefetchTexture();
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need aux data, but we've already loaded the image, and it didn't have any
|
||||
LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
mLastCallBackActiveTime = sCurrentTime ;
|
||||
mLastReferencedSavedRawImageTime = sCurrentTime;
|
||||
}
|
||||
|
||||
void LLViewerFetchedTexture::clearCallbackEntryList()
|
||||
@@ -2151,6 +2287,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry:
|
||||
}
|
||||
mPauseLoadedCallBacks = FALSE ;
|
||||
mLastCallBackActiveTime = sCurrentTime ;
|
||||
mForceCallbackFetch = TRUE;
|
||||
if(need_raw)
|
||||
{
|
||||
mSaveRawImage = TRUE ;
|
||||
@@ -2191,6 +2328,7 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s
|
||||
bool LLViewerFetchedTexture::doLoadedCallbacks()
|
||||
{
|
||||
static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds
|
||||
static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds
|
||||
|
||||
if (mNeedsCreateTexture)
|
||||
{
|
||||
@@ -2395,6 +2533,9 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
|
||||
}
|
||||
}
|
||||
|
||||
// Done with any raw image data at this point (will be re-created if we still have callbacks)
|
||||
destroyRawImage();
|
||||
|
||||
//
|
||||
// If we have no callbacks, take us off of the image callback list.
|
||||
//
|
||||
@@ -2402,10 +2543,12 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
|
||||
{
|
||||
gTextureList.mCallbackList.erase(this);
|
||||
}
|
||||
|
||||
// Done with any raw image data at this point (will be re-created if we still have callbacks)
|
||||
destroyRawImage();
|
||||
|
||||
else if(!res && mForceCallbackFetch && sCurrentTime - mLastCallBackActiveTime > MAX_IDLE_WAIT_TIME && !mIsFetching)
|
||||
{
|
||||
//wait for long enough but no fetching request issued, force one.
|
||||
forceToRefetchTexture(mLoadedCallbackDesiredDiscardLevel, 5.f);
|
||||
mForceCallbackFetch = FALSE; //fire once.
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -2487,7 +2630,7 @@ bool LLViewerFetchedTexture::needsToSaveRawImage()
|
||||
|
||||
void LLViewerFetchedTexture::destroyRawImage()
|
||||
{
|
||||
if (mAuxRawImage.notNull())
|
||||
if (mAuxRawImage.notNull() && !needsToSaveRawImage())
|
||||
{
|
||||
sAuxCount--;
|
||||
mAuxRawImage = NULL;
|
||||
@@ -2660,7 +2803,25 @@ void LLViewerFetchedTexture::saveRawImage()
|
||||
mForceToSaveRawImage = FALSE ;
|
||||
}
|
||||
|
||||
mLastReferencedSavedRawImageTime = sCurrentTime;
|
||||
}
|
||||
|
||||
//force to refetch the texture to the discard level
|
||||
void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard, F32 kept_time)
|
||||
{
|
||||
if(mForceToSaveRawImage)
|
||||
{
|
||||
desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel);
|
||||
kept_time = llmax(kept_time, mKeptSavedRawImageTime);
|
||||
}
|
||||
|
||||
//trigger a new fetch.
|
||||
mForceToSaveRawImage = TRUE ;
|
||||
mDesiredSavedRawDiscardLevel = desired_discard ;
|
||||
mKeptSavedRawImageTime = kept_time ;
|
||||
mLastReferencedSavedRawImageTime = sCurrentTime ;
|
||||
mSavedRawImage = NULL ;
|
||||
mSavedRawDiscardLevel = -1 ;
|
||||
}
|
||||
|
||||
void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time)
|
||||
@@ -2710,6 +2871,12 @@ void LLViewerFetchedTexture::destroySavedRawImage()
|
||||
mDesiredSavedRawDiscardLevel = -1 ;
|
||||
mLastReferencedSavedRawImageTime = 0.0f ;
|
||||
mKeptSavedRawImageTime = 0.f ;
|
||||
|
||||
if(mAuxRawImage.notNull())
|
||||
{
|
||||
sAuxCount--;
|
||||
mAuxRawImage = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
LLImageRaw* LLViewerFetchedTexture::getSavedRawImage()
|
||||
|
||||
@@ -132,9 +132,10 @@ public:
|
||||
|
||||
/*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
|
||||
/*virtual*/ void forceImmediateUpdate() ;
|
||||
/*virtual*/ bool isActiveFetching();
|
||||
|
||||
/*virtual*/ const LLUUID& getID() const { return mID; }
|
||||
//void setBoostLevel(S32 level);
|
||||
void setBoostLevel(S32 level);
|
||||
S32 getBoostLevel() { return mBoostLevel; }
|
||||
|
||||
void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const;
|
||||
@@ -147,6 +148,8 @@ public:
|
||||
|
||||
LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;}
|
||||
|
||||
S32 getFullWidth() const { return mFullWidth; }
|
||||
S32 getFullHeight() const { return mFullHeight; }
|
||||
/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
|
||||
|
||||
virtual void addFace(U32 channel, LLFace* facep) ;
|
||||
@@ -174,6 +177,10 @@ protected:
|
||||
void init(bool firstinit) ;
|
||||
void reorganizeFaceList() ;
|
||||
void reorganizeVolumeList() ;
|
||||
|
||||
void notifyAboutMissingAsset();
|
||||
void notifyAboutCreatingTexture();
|
||||
|
||||
private:
|
||||
friend class LLBumpImageList;
|
||||
friend class LLUIImageList;
|
||||
@@ -184,7 +191,7 @@ private:
|
||||
static bool isMemoryForTextureLow() ;
|
||||
protected:
|
||||
LLUUID mID;
|
||||
|
||||
F32 mSelectedTime; // time texture was last selected
|
||||
mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need?
|
||||
mutable S32 mMaxVirtualSizeResetCounter ;
|
||||
mutable S32 mMaxVirtualSizeResetInterval;
|
||||
@@ -325,13 +332,17 @@ public:
|
||||
void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); }
|
||||
|
||||
bool updateFetch();
|
||||
bool setDebugFetching(S32 debug_level);
|
||||
bool isInDebug() {return mInDebug;}
|
||||
|
||||
void clearFetchedResults(); //clear all fetched results, for debug use.
|
||||
|
||||
// Override the computation of discard levels if we know the exact output
|
||||
// size of the image. Used for UI textures to not decode, even if we have
|
||||
// more data.
|
||||
/*virtual*/ void setKnownDrawSize(S32 width, S32 height);
|
||||
|
||||
void setIsMissingAsset();
|
||||
void setIsMissingAsset(BOOL is_missing = true);
|
||||
/*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
|
||||
|
||||
// returns dimensions of original image for local files (before power of two scaling)
|
||||
@@ -374,6 +385,7 @@ public:
|
||||
BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
|
||||
BOOL isRawImageValid()const { return mIsRawImageValid ; }
|
||||
void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
|
||||
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
|
||||
/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
|
||||
void destroySavedRawImage() ;
|
||||
LLImageRaw* getSavedRawImage() ;
|
||||
@@ -386,6 +398,7 @@ public:
|
||||
|
||||
void forceToDeleteRequest();
|
||||
void forceRefetch();
|
||||
/*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline.
|
||||
|
||||
protected:
|
||||
/*virtual*/ void switchToCachedImage();
|
||||
@@ -406,6 +419,8 @@ private:
|
||||
|
||||
private:
|
||||
BOOL mFullyLoaded;
|
||||
BOOL mInDebug;
|
||||
BOOL mForceCallbackFetch;
|
||||
|
||||
protected:
|
||||
std::string mLocalFileName;
|
||||
@@ -433,6 +448,7 @@ protected:
|
||||
S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have
|
||||
|
||||
S8 mNeedsAux; // We need to decode the auxiliary channels
|
||||
S8 mHasAux; // We have aux channels
|
||||
S8 mDecodingAux; // Are we decoding high components
|
||||
S8 mIsRawImageValid;
|
||||
S8 mHasFetcher; // We've made a fecth request
|
||||
|
||||
@@ -139,6 +139,8 @@ size_t strnlen(const char *s, size_t n)
|
||||
}
|
||||
#endif
|
||||
|
||||
extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG;
|
||||
|
||||
const F32 MAX_HOVER_Z = 2.0;
|
||||
const F32 MIN_HOVER_Z = -2.0;
|
||||
|
||||
@@ -290,6 +292,9 @@ const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f;
|
||||
|
||||
const S32 MORPH_MASK_REQUESTED_DISCARD = 0;
|
||||
|
||||
const F32 MAX_STANDOFF_FROM_ORIGIN = 3;
|
||||
const F32 MAX_STANDOFF_DISTANCE_CHANGE = 32;
|
||||
|
||||
// Discard level at which to switch to baked textures
|
||||
// Should probably be 4 or 3, but didn't want to change it while change other logic - SJB
|
||||
const S32 SWITCH_TO_BAKED_DISCARD = 5;
|
||||
@@ -1092,7 +1097,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
||||
mFullyLoadedInitialized(FALSE),
|
||||
mSupportsAlphaLayers(FALSE),
|
||||
mLoadedCallbacksPaused(FALSE),
|
||||
mHasPelvisOffset( FALSE ),
|
||||
mLastRezzedStatus(-1),
|
||||
mIsEditingAppearance(FALSE),
|
||||
mUseLocalAppearance(FALSE),
|
||||
@@ -1166,10 +1170,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
|
||||
mRuthDebugTimer.reset();
|
||||
mDebugExistenceTimer.reset();
|
||||
mLastAppearanceMessageTimer.reset();
|
||||
mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
|
||||
mLastPelvisToFoot = 0.0f;
|
||||
mPelvisFixup = 0.0f;
|
||||
mLastPelvisFixup = 0.0f;
|
||||
}
|
||||
|
||||
std::string LLVOAvatar::avString() const
|
||||
@@ -1524,7 +1524,6 @@ void LLVOAvatar::deleteCachedImages(bool clearAll)
|
||||
}
|
||||
LLViewerTexLayerSet::sHasCaches = FALSE;
|
||||
}
|
||||
LLVOAvatarSelf::deleteScratchTextures();
|
||||
LLTexLayerStaticImageList::getInstance()->deleteCachedImages();
|
||||
}
|
||||
|
||||
@@ -1659,23 +1658,25 @@ LLTexLayerSet* LLVOAvatar::createTexLayerSet()
|
||||
|
||||
const LLVector3 LLVOAvatar::getRenderPosition() const
|
||||
{
|
||||
|
||||
if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
|
||||
{
|
||||
return getPositionAgent();
|
||||
}
|
||||
else if (isRoot() || !mDrawable->getParent())
|
||||
{
|
||||
if ( !mHasPelvisOffset )
|
||||
{
|
||||
return mDrawable->getPositionAgent();
|
||||
}
|
||||
else
|
||||
F32 fixup;
|
||||
if ( hasPelvisFixup( fixup) )
|
||||
{
|
||||
//Apply a pelvis fixup (as defined by the avs skin)
|
||||
LLVector3 pos = mDrawable->getPositionAgent();
|
||||
pos[VZ] += mPelvisFixup;
|
||||
pos[VZ] += fixup;
|
||||
return pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mDrawable->getPositionAgent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2420,11 +2421,16 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU
|
||||
if (!result)
|
||||
{
|
||||
const std::string url = getImageURL(te,uuid);
|
||||
|
||||
if (!url.empty())
|
||||
{
|
||||
LL_DEBUGS("Avatar") << avString() << "from URL " << url << LL_ENDL;
|
||||
result = LLViewerTextureManager::getFetchedTextureFromUrl(
|
||||
url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid);
|
||||
if (result->isMissingAsset())
|
||||
{
|
||||
result->setIsMissingAsset(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2569,7 +2575,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
||||
|
||||
// animate the character
|
||||
// store off last frame's root position to be consistent with camera position
|
||||
LLVector3 root_pos_last = mRoot->getWorldPosition();
|
||||
mLastRootPos = mRoot->getWorldPosition();
|
||||
bool detailed_update;
|
||||
{
|
||||
LLFastTimer t(FTM_CHARACTER_UPDATE);
|
||||
@@ -2598,7 +2604,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
||||
idleUpdateWindEffect();
|
||||
}
|
||||
|
||||
idleUpdateNameTag(root_pos_last);
|
||||
idleUpdateNameTag( mLastRootPos );
|
||||
idleUpdateRenderCost();
|
||||
}
|
||||
}
|
||||
@@ -3845,18 +3851,8 @@ void LLVOAvatar::resetFreezeTime()
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// updateCharacter()
|
||||
// called on both your avatar and other avatars
|
||||
//------------------------------------------------------------------------
|
||||
BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
void LLVOAvatar::updateDebugText()
|
||||
{
|
||||
// Frozen!
|
||||
if (areAnimationsPaused())
|
||||
{
|
||||
updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))
|
||||
{
|
||||
@@ -3947,6 +3943,34 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
}
|
||||
}
|
||||
|
||||
if (!mDebugText.size() && mText.notNull())
|
||||
{
|
||||
mText->markDead();
|
||||
mText = NULL;
|
||||
}
|
||||
else if (mDebugText.size())
|
||||
{
|
||||
setDebugText(mDebugText);
|
||||
}
|
||||
mDebugText.clear();
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// updateCharacter()
|
||||
// called on both your avatar and other avatars
|
||||
//------------------------------------------------------------------------
|
||||
BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
{
|
||||
// Frozen!
|
||||
if (areAnimationsPaused())
|
||||
{
|
||||
updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
updateDebugText();
|
||||
|
||||
if (gNoRender)
|
||||
{
|
||||
// Hack if we're running drones...
|
||||
@@ -3957,9 +3981,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
LLVector3d root_pos_global;
|
||||
|
||||
if (!mIsBuilt)
|
||||
{
|
||||
return FALSE;
|
||||
@@ -4444,17 +4465,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
|
||||
|
||||
mRoot->updateWorldMatrixChildren();
|
||||
|
||||
if (!mDebugText.size() && mText.notNull())
|
||||
{
|
||||
mText->markDead();
|
||||
mText = NULL;
|
||||
}
|
||||
else if (mDebugText.size())
|
||||
{
|
||||
setDebugText(mDebugText);
|
||||
}
|
||||
mDebugText.clear();
|
||||
|
||||
//mesh vertices need to be reskinned
|
||||
mNeedsSkin = TRUE;
|
||||
|
||||
@@ -4485,39 +4495,13 @@ void LLVOAvatar::updateHeadOffset()
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
// setPelvisOffset
|
||||
//------------------------------------------------------------------------
|
||||
void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup )
|
||||
{
|
||||
mHasPelvisOffset = hasOffset;
|
||||
if ( mHasPelvisOffset )
|
||||
{
|
||||
//Store off last pelvis to foot value
|
||||
mLastPelvisToFoot = mPelvisToFoot;
|
||||
mPelvisOffset = offsetAmount;
|
||||
mLastPelvisFixup = mPelvisFixup;
|
||||
mPelvisFixup = pelvisFixup;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
// postPelvisSetRecalc
|
||||
//------------------------------------------------------------------------
|
||||
void LLVOAvatar::postPelvisSetRecalc( void )
|
||||
{
|
||||
computeBodySize();
|
||||
mRoot->touch();
|
||||
mRoot->updateWorldMatrixChildren();
|
||||
dirtyMesh();
|
||||
updateHeadOffset();
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
// pelisPoke
|
||||
//------------------------------------------------------------------------
|
||||
void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount )
|
||||
{
|
||||
mHasPelvisOffset = true;
|
||||
mLastPelvisFixup = mPelvisFixup;
|
||||
mPelvisFixup = pelvisFixupAmount;
|
||||
{
|
||||
mRoot->updateWorldMatrixChildren();
|
||||
computeBodySize();
|
||||
dirtyMesh(2);
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
// updateVisibility()
|
||||
@@ -5773,6 +5757,12 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL
|
||||
{
|
||||
sitDown(FALSE);
|
||||
}
|
||||
if ((anim_id == ANIM_AGENT_BUSY) && gAgent.isDoNotDisturb())
|
||||
{
|
||||
// re-assert DND tag animation
|
||||
gAgent.sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START);
|
||||
return result;
|
||||
}
|
||||
stopMotion(anim_id);
|
||||
result = TRUE;
|
||||
}
|
||||
@@ -5985,11 +5975,163 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
|
||||
|
||||
return jointp;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// resetJointPositionsToDefault
|
||||
// getRiggedMeshID
|
||||
//
|
||||
// If viewer object is a rigged mesh, set the mesh id and return true.
|
||||
// Otherwise, null out the id and return false.
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLVOAvatar::resetJointPositionsToDefault( void )
|
||||
// static
|
||||
bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id)
|
||||
{
|
||||
mesh_id.setNull();
|
||||
|
||||
//If a VO has a skin that we'll reset the joint positions to their default
|
||||
if ( pVO && pVO->mDrawable )
|
||||
{
|
||||
LLVOVolume* pVObj = pVO->mDrawable->getVOVolume();
|
||||
if ( pVObj )
|
||||
{
|
||||
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
|
||||
if (pSkinData
|
||||
&& pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG // full rig
|
||||
&& pSkinData->mAlternateBindMatrix.size() > 0 )
|
||||
{
|
||||
mesh_id = pSkinData->mMeshID;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLVOAvatar::clearAttachmentPosOverrides()
|
||||
{
|
||||
//Subsequent joints are relative to pelvis
|
||||
avatar_joint_list_t::iterator iter = mSkeleton.begin();
|
||||
avatar_joint_list_t::iterator end = mSkeleton.end();
|
||||
|
||||
for (; iter != end; ++iter)
|
||||
{
|
||||
LLJoint* pJoint = (*iter);
|
||||
pJoint->clearAttachmentPosOverrides();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// addAttachmentPosOverridesForObject
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLVOAvatar::addAttachmentPosOverridesForObject(LLViewerObject *vo)
|
||||
{
|
||||
LLVOAvatar *av = vo->getAvatarAncestor();
|
||||
if (!av || (av != this))
|
||||
{
|
||||
LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL;
|
||||
}
|
||||
|
||||
// Process all children
|
||||
LLViewerObject::const_child_list_t& children = vo->getChildren();
|
||||
for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
|
||||
it != children.end(); ++it)
|
||||
{
|
||||
LLViewerObject *childp = *it;
|
||||
addAttachmentPosOverridesForObject(childp);
|
||||
}
|
||||
|
||||
LLVOVolume *vobj = dynamic_cast<LLVOVolume*>(vo);
|
||||
bool pelvisGotSet = false;
|
||||
|
||||
if (!vobj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (vobj->isMesh() &&
|
||||
((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
|
||||
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
|
||||
|
||||
if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData )
|
||||
{
|
||||
const int bindCnt = pSkinData->mAlternateBindMatrix.size();
|
||||
if ( bindCnt > 0 )
|
||||
{
|
||||
const U32 jointCnt = pSkinData->mJointNames.size();
|
||||
const F32 pelvisZOffset = pSkinData->mPelvisOffset;
|
||||
const LLUUID& mesh_id = pSkinData->mMeshID;
|
||||
bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false;
|
||||
if ( fullRig )
|
||||
{
|
||||
for ( U32 i=0; i<jointCnt; ++i )
|
||||
{
|
||||
std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
|
||||
LLJoint* pJoint = getJoint( lookingForJoint );
|
||||
if ( pJoint && pJoint->getId() != currentId )
|
||||
{
|
||||
pJoint->setId( currentId );
|
||||
const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();
|
||||
//Set the joint position
|
||||
pJoint->addAttachmentPosOverride( jointPos, mesh_id, avString() );
|
||||
|
||||
//If joint is a pelvis then handle old/new pelvis to foot values
|
||||
if ( lookingForJoint == "mPelvis" )
|
||||
{
|
||||
pelvisGotSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pelvisZOffset != 0.0F)
|
||||
{
|
||||
addPelvisFixup( pelvisZOffset, mesh_id );
|
||||
pelvisGotSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Rebuild body data if we altered joints/pelvis
|
||||
if ( pelvisGotSet )
|
||||
{
|
||||
postPelvisSetRecalc();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// resetJointPositionsOnDetach
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLVOAvatar::resetJointPositionsOnDetach(LLViewerObject *vo)
|
||||
{
|
||||
LLVOAvatar *av = vo->getAvatarAncestor();
|
||||
if (!av || (av != this))
|
||||
{
|
||||
LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL;
|
||||
}
|
||||
|
||||
// Process all children
|
||||
LLViewerObject::const_child_list_t& children = vo->getChildren();
|
||||
for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
|
||||
it != children.end(); ++it)
|
||||
{
|
||||
LLViewerObject *childp = *it;
|
||||
resetJointPositionsOnDetach(childp);
|
||||
}
|
||||
|
||||
// Process self.
|
||||
LLUUID mesh_id;
|
||||
if (getRiggedMeshID(vo,mesh_id))
|
||||
{
|
||||
resetJointPositionsOnDetach(mesh_id);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// resetJointPositionsOnDetach
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLVOAvatar::resetJointPositionsOnDetach(const LLUUID& mesh_id)
|
||||
{
|
||||
//Subsequent joints are relative to pelvis
|
||||
avatar_joint_list_t::iterator iter = mSkeleton.begin();
|
||||
avatar_joint_list_t::iterator end = mSkeleton.end();
|
||||
@@ -6000,24 +6142,19 @@ void LLVOAvatar::resetJointPositionsToDefault( void )
|
||||
{
|
||||
LLJoint* pJoint = (*iter);
|
||||
//Reset joints except for pelvis
|
||||
if ( pJoint && pJoint != pJointPelvis && pJoint->doesJointNeedToBeReset() )
|
||||
{
|
||||
if ( pJoint )
|
||||
{
|
||||
pJoint->setId( LLUUID::null );
|
||||
pJoint->restoreOldXform();
|
||||
}
|
||||
else
|
||||
if ( pJoint && pJoint == pJointPelvis && pJoint->doesJointNeedToBeReset() )
|
||||
pJoint->removeAttachmentPosOverride(mesh_id, avString());
|
||||
}
|
||||
if ( pJoint && pJoint == pJointPelvis)
|
||||
{
|
||||
pJoint->setId( LLUUID::null );
|
||||
removePelvisFixup( mesh_id );
|
||||
pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) );
|
||||
//pJoint->setJointResetFlag( false ); // Singu TODO
|
||||
}
|
||||
}
|
||||
|
||||
//make sure we don't apply the joint offset
|
||||
mHasPelvisOffset = false;
|
||||
mPelvisFixup = mLastPelvisFixup;
|
||||
postPelvisSetRecalc();
|
||||
}
|
||||
}
|
||||
|
||||
postPelvisSetRecalc();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// getCharacterPosition()
|
||||
@@ -6461,12 +6598,20 @@ BOOL LLVOAvatar::setParent(LLViewerObject* parent)
|
||||
void LLVOAvatar::addChild(LLViewerObject *childp)
|
||||
{
|
||||
childp->extractAttachmentItemID(); // find the inventory item this object is associated with.
|
||||
if (isSelf())
|
||||
{
|
||||
const LLUUID& item_id = childp->getAttachmentItemID();
|
||||
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||
LL_DEBUGS("Avatar") << "ATT attachment child added " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
|
||||
|
||||
}
|
||||
|
||||
LLViewerObject::addChild(childp);
|
||||
if (childp->mDrawable)
|
||||
{
|
||||
if (!attachObject(childp))
|
||||
{
|
||||
LL_WARNS() << "addChild() failed for "
|
||||
LL_WARNS() << "ATT addChild() failed for "
|
||||
<< childp->getID()
|
||||
<< " item " << childp->getAttachmentItemID()
|
||||
<< LL_ENDL;
|
||||
@@ -6552,10 +6697,21 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi
|
||||
//-----------------------------------------------------------------------------
|
||||
const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
|
||||
{
|
||||
if (isSelf())
|
||||
{
|
||||
const LLUUID& item_id = viewer_object->getAttachmentItemID();
|
||||
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||
LL_DEBUGS("Avatar") << "ATT attaching object "
|
||||
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
|
||||
}
|
||||
LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
|
||||
|
||||
if (!attachment || !attachment->addObject(viewer_object))
|
||||
{
|
||||
const LLUUID& item_id = viewer_object->getAttachmentItemID();
|
||||
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||
LL_WARNS("Avatar") << "ATT attach failed "
|
||||
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6620,7 +6776,14 @@ void LLVOAvatar::lazyAttach()
|
||||
LLPointer<LLViewerObject> cur_attachment = mPendingAttachment[i];
|
||||
if (cur_attachment->mDrawable)
|
||||
{
|
||||
if(!attachObject(cur_attachment))
|
||||
if (isSelf())
|
||||
{
|
||||
const LLUUID& item_id = cur_attachment->getAttachmentItemID();
|
||||
LLViewerInventoryItem *item = gInventory.getItem(item_id);
|
||||
LL_DEBUGS("Avatar") << "ATT attaching object "
|
||||
<< (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL;
|
||||
}
|
||||
if (!attachObject(cur_attachment))
|
||||
{ // Drop it
|
||||
LL_WARNS() << "attachObject() failed for "
|
||||
<< cur_attachment->getID()
|
||||
@@ -6686,27 +6849,15 @@ void LLVOAvatar::rebuildRiggedAttachments( void )
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
|
||||
{
|
||||
//If a VO has a skin that we'll reset the joint positions to their default
|
||||
if ( pVO && pVO->mDrawable )
|
||||
LLUUID mesh_id;
|
||||
if (getRiggedMeshID(pVO, mesh_id))
|
||||
{
|
||||
LLVOVolume* pVObj = pVO->mDrawable->getVOVolume();
|
||||
if ( pVObj )
|
||||
resetJointPositionsOnDetach(mesh_id);
|
||||
if ( gAgentCamera.cameraCustomizeAvatar() )
|
||||
{
|
||||
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
|
||||
if ( pSkinData
|
||||
&& pSkinData->mJointNames.size() > 20 // full rig
|
||||
&& pSkinData->mAlternateBindMatrix.size() > 0 )
|
||||
{
|
||||
LLVOAvatar::resetJointPositionsToDefault();
|
||||
//Need to handle the repositioning of the cam, updating rig data etc during outfit editing
|
||||
//This handles the case where we detach a replacement rig.
|
||||
if ( gAgentCamera.cameraCustomizeAvatar() )
|
||||
{
|
||||
gAgent.unpauseAnimation();
|
||||
//Still want to refocus on head bone
|
||||
gAgentCamera.changeCameraToCustomizeAvatar();
|
||||
}
|
||||
}
|
||||
gAgent.unpauseAnimation();
|
||||
//Still want to refocus on head bone
|
||||
gAgentCamera.changeCameraToCustomizeAvatar();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6845,9 +6996,18 @@ void LLVOAvatar::getOffObject()
|
||||
LLVector3 cur_position_world = mDrawable->getWorldPosition();
|
||||
LLQuaternion cur_rotation_world = mDrawable->getWorldRotation();
|
||||
|
||||
if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN
|
||||
&& (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN
|
||||
|| dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE))
|
||||
{
|
||||
// Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent
|
||||
// restore coordinates from cache
|
||||
cur_position_world = mLastRootPos;
|
||||
}
|
||||
|
||||
// set *local* position based on last *world* position, since we're unparenting the avatar
|
||||
mDrawable->mXform.setPosition(cur_position_world);
|
||||
mDrawable->mXform.setRotation(cur_rotation_world);
|
||||
mDrawable->mXform.setRotation(cur_rotation_world);
|
||||
|
||||
gPipeline.markMoved(mDrawable, TRUE);
|
||||
|
||||
@@ -7065,6 +7225,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, bool
|
||||
BOOL LLVOAvatar::isVisible() const
|
||||
{
|
||||
return mDrawable.notNull()
|
||||
&& (!mOrphaned || isSelf())
|
||||
&& (mDrawable->isVisible() || mIsDummy);
|
||||
}
|
||||
|
||||
@@ -7109,6 +7270,7 @@ void LLVOAvatar::updateRezzedStatusTimers()
|
||||
for (S32 i = 1; i < 4; i++)
|
||||
{
|
||||
startPhase("load_" + LLVOAvatar::rezStatusToString(i));
|
||||
startPhase("first_load_" + LLVOAvatar::rezStatusToString(i));
|
||||
}
|
||||
}
|
||||
if (rez_status < mLastRezzedStatus)
|
||||
@@ -7125,6 +7287,7 @@ void LLVOAvatar::updateRezzedStatusTimers()
|
||||
for (S32 i = llmax(mLastRezzedStatus+1,1); i <= rez_status; i++)
|
||||
{
|
||||
stopPhase("load_" + LLVOAvatar::rezStatusToString(i));
|
||||
stopPhase("first_load_" + LLVOAvatar::rezStatusToString(i), false);
|
||||
}
|
||||
if (rez_status == 3)
|
||||
{
|
||||
@@ -7254,14 +7417,7 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse
|
||||
record["grid_y"] = LLSD::Integer(grid_y);
|
||||
record["is_using_server_bakes"] = ((bool) isUsingServerBakes());
|
||||
record["is_self"] = isSelf();
|
||||
|
||||
|
||||
#if 0 // verbose logging
|
||||
std::ostringstream ostr;
|
||||
ostr << LLSDNotationStreamer(record);
|
||||
LL_DEBUGS("Avatar") << "record\n" << ostr.str() << LL_ENDL;
|
||||
#endif
|
||||
|
||||
|
||||
if (isAgentAvatarValid())
|
||||
{
|
||||
gAgentAvatarp->addMetricsTimerRecord(record);
|
||||
@@ -7535,6 +7691,8 @@ void LLVOAvatar::updateMeshTextures()
|
||||
// we'll consider it loaded and use it (rather than
|
||||
// doing compositing).
|
||||
useBakedTexture( baked_img->getID() );
|
||||
mLoadedCallbacksPaused |= !isVisible();
|
||||
checkTextureLoading();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7547,6 +7705,10 @@ void LLVOAvatar::updateMeshTextures()
|
||||
}
|
||||
baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ),
|
||||
src_callback_list, paused );
|
||||
|
||||
// this could add paused texture callbacks
|
||||
mLoadedCallbacksPaused |= paused;
|
||||
checkTextureLoading();
|
||||
}
|
||||
}
|
||||
else if (layerset && isUsingLocalAppearance())
|
||||
@@ -7615,7 +7777,15 @@ void LLVOAvatar::updateMeshTextures()
|
||||
}
|
||||
}
|
||||
}
|
||||
removeMissingBakedTextures();
|
||||
|
||||
// removeMissingBakedTextures() will call back into this rountine if something is removed, and can blow up the stack
|
||||
static bool call_remove_missing = true;
|
||||
if (call_remove_missing)
|
||||
{
|
||||
call_remove_missing = false;
|
||||
removeMissingBakedTextures(); // May call back into this function if anything is removed
|
||||
call_remove_missing = true;
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
@@ -7916,6 +8086,9 @@ void LLVOAvatar::onFirstTEMessageReceived()
|
||||
LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL;
|
||||
image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ),
|
||||
src_callback_list, paused );
|
||||
|
||||
// this could add paused texture callbacks
|
||||
mLoadedCallbacksPaused |= paused;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8494,7 +8667,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
|
||||
}
|
||||
if (!found_texture_id)
|
||||
{
|
||||
LL_INFOS() << "onBakedTextureMasksLoaded(): unexpected image id: " << id << LL_ENDL;
|
||||
LL_INFOS() << "unexpected image id: " << id << LL_ENDL;
|
||||
}
|
||||
self->dirtyMesh();
|
||||
}
|
||||
|
||||
@@ -249,7 +249,10 @@ public:
|
||||
|
||||
virtual LLJoint* getJoint(const std::string &name);
|
||||
|
||||
void resetJointPositionsToDefault( void );
|
||||
void addAttachmentPosOverridesForObject(LLViewerObject *vo);
|
||||
void resetJointPositionsOnDetach(const LLUUID& mesh_id);
|
||||
void resetJointPositionsOnDetach(LLViewerObject *vo);
|
||||
void clearAttachmentPosOverrides();
|
||||
|
||||
/*virtual*/ const LLUUID& getID() const;
|
||||
/*virtual*/ void addDebugText(const std::string& text);
|
||||
@@ -283,6 +286,7 @@ private:
|
||||
// Updates
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
void updateDebugText();
|
||||
virtual BOOL updateCharacter(LLAgent &agent);
|
||||
void idleUpdateVoiceVisualizer(bool voice_enabled);
|
||||
void idleUpdateMisc(bool detailed_update);
|
||||
@@ -393,19 +397,13 @@ protected:
|
||||
/*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh
|
||||
public:
|
||||
void updateHeadOffset();
|
||||
void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ;
|
||||
bool hasPelvisOffset( void ) { return mHasPelvisOffset; }
|
||||
void postPelvisSetRecalc( void );
|
||||
void setPelvisOffset( F32 pelvixFixupAmount );
|
||||
|
||||
/*virtual*/ BOOL loadSkeletonNode();
|
||||
/*virtual*/ void buildCharacter();
|
||||
|
||||
bool mHasPelvisOffset;
|
||||
LLVector3 mPelvisOffset;
|
||||
F32 mLastPelvisToFoot;
|
||||
F32 mPelvisFixup;
|
||||
F32 mLastPelvisFixup;
|
||||
LLVector3 mCurRootToHeadOffset;
|
||||
LLVector3 mTargetRootToHeadOffset;
|
||||
|
||||
S32 mLastSkeletonSerialNum;
|
||||
|
||||
@@ -744,6 +742,7 @@ public:
|
||||
void clampAttachmentPositions();
|
||||
virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
|
||||
virtual BOOL detachObject(LLViewerObject *viewer_object);
|
||||
static bool getRiggedMeshID( LLViewerObject* pVO, LLUUID& mesh_id );
|
||||
void cleanupAttachedMesh( LLViewerObject* pVO );
|
||||
static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj);
|
||||
/*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const;
|
||||
@@ -905,6 +904,8 @@ public:
|
||||
private:
|
||||
// set this property only with LLVOAvatar::sitDown method
|
||||
BOOL mIsSitting;
|
||||
// position backup in case of missing data
|
||||
LLVector3 mLastRootPos;
|
||||
|
||||
/** Hierarchy
|
||||
** **
|
||||
|
||||
@@ -153,15 +153,6 @@ typedef LLHTTPClient::ResponderIgnore LLHoverHeightResponder;
|
||||
** **
|
||||
*********************************************************************************/
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Static Data
|
||||
//-----------------------------------------------------------------------------
|
||||
S32Bytes LLVOAvatarSelf::sScratchTexBytes(0);
|
||||
LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames;
|
||||
LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime;
|
||||
|
||||
|
||||
/*********************************************************************************
|
||||
** **
|
||||
** Begin LLVOAvatarSelf Constructor routines
|
||||
@@ -2685,13 +2676,9 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe
|
||||
{
|
||||
F32 desired_pixels;
|
||||
desired_pixels = llmin(mPixelArea, (F32)getTexImageArea());
|
||||
|
||||
// DRANO what priority should wearable-based textures have?
|
||||
if (isUsingLocalAppearance())
|
||||
{
|
||||
imagep->setBoostLevel(getAvatarBoostLevel());
|
||||
imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
|
||||
}
|
||||
|
||||
imagep->setBoostLevel(getAvatarBoostLevel());
|
||||
imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ;
|
||||
imagep->resetTextureStats();
|
||||
imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL);
|
||||
imagep->addTextureStats( desired_pixels / texel_area_ratio );
|
||||
@@ -3210,77 +3197,6 @@ BOOL LLVOAvatarSelf::needsRenderBeam()
|
||||
return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection());
|
||||
}
|
||||
|
||||
// static
|
||||
void LLVOAvatarSelf::deleteScratchTextures()
|
||||
{
|
||||
if(gAuditTexture)
|
||||
{
|
||||
S32Bytes total_tex_size = sScratchTexBytes ;
|
||||
S32Bytes tex_size(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT) ;
|
||||
|
||||
if( sScratchTexNames.checkData( GL_LUMINANCE ) )
|
||||
{
|
||||
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||
total_tex_size -= tex_size ;
|
||||
}
|
||||
if( sScratchTexNames.checkData( GL_ALPHA ) )
|
||||
{
|
||||
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||
total_tex_size -= tex_size ;
|
||||
}
|
||||
if( sScratchTexNames.checkData( GL_COLOR_INDEX ) )
|
||||
{
|
||||
LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||
total_tex_size -= tex_size ;
|
||||
}
|
||||
if( sScratchTexNames.checkData( LLRender::sGLCoreProfile ? GL_RG : GL_LUMINANCE_ALPHA ) )
|
||||
{
|
||||
LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||
total_tex_size -= 2 * tex_size ;
|
||||
}
|
||||
if( sScratchTexNames.checkData( GL_RGB ) )
|
||||
{
|
||||
LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||
total_tex_size -= 3 * tex_size ;
|
||||
}
|
||||
if( sScratchTexNames.checkData( GL_RGBA ) )
|
||||
{
|
||||
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||
total_tex_size -= 4 * tex_size ;
|
||||
}
|
||||
//others
|
||||
while(total_tex_size > S32Bytes(0))
|
||||
{
|
||||
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||
total_tex_size -= 4 * tex_size ;
|
||||
}
|
||||
}
|
||||
|
||||
for( LLGLuint* namep = sScratchTexNames.getFirstData();
|
||||
namep;
|
||||
namep = sScratchTexNames.getNextData() )
|
||||
{
|
||||
LLImageGL::deleteTextures(1, (U32 *)namep );
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
if( sScratchTexBytes.value() )
|
||||
{
|
||||
LL_DEBUGS() << "Clearing Scratch Textures " << (S32Kilobytes)sScratchTexBytes << "KB" << LL_ENDL;
|
||||
|
||||
sScratchTexNames.deleteAllData();
|
||||
sScratchTexLastBindTime.deleteAllData();
|
||||
LLImageGL::sGlobalTextureMemory -= sScratchTexBytes;
|
||||
sScratchTexBytes = S32Bytes(0);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLVOAvatarSelf::dumpScratchTextureByteCount()
|
||||
{
|
||||
LL_INFOS() << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << LL_ENDL;
|
||||
}
|
||||
|
||||
void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value);
|
||||
|
||||
void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include "llviewertexture.h"
|
||||
#include "llvoavatar.h"
|
||||
#include <map>
|
||||
|
||||
struct LocalTextureData;
|
||||
class LLInventoryCallback;
|
||||
@@ -266,17 +267,6 @@ public:
|
||||
const LLUUID& grabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
|
||||
BOOL canGrabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Scratch textures (used for compositing)
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
static void deleteScratchTextures();
|
||||
private:
|
||||
static S32Bytes sScratchTexBytes;
|
||||
static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;
|
||||
static LLMap< LLGLenum, F32*> sScratchTexLastBindTime;
|
||||
|
||||
/** Textures
|
||||
** **
|
||||
*******************************************************************************/
|
||||
@@ -383,7 +373,6 @@ public:
|
||||
public:
|
||||
static void dumpTotalLocalTextureByteCount();
|
||||
void dumpLocalTextures() const;
|
||||
static void dumpScratchTextureByteCount();
|
||||
void dumpWearableInfo(LLAPRFile& outfile);
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
const S32 MIN_QUIET_FRAMES_COALESCE = 30;
|
||||
const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
|
||||
const F32 FORCE_CULL_AREA = 8.f;
|
||||
U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 20;
|
||||
|
||||
BOOL gAnimateTextures = TRUE;
|
||||
//extern BOOL gHideSelectedObjects;
|
||||
@@ -1564,6 +1565,65 @@ static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies");
|
||||
static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives");
|
||||
static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged");
|
||||
|
||||
bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable)
|
||||
{
|
||||
bool regen_faces = false;
|
||||
|
||||
LLVolume *old_volumep, *new_volumep;
|
||||
F32 old_lod, new_lod;
|
||||
S32 old_num_faces, new_num_faces ;
|
||||
|
||||
old_volumep = getVolume();
|
||||
old_lod = old_volumep->getDetail();
|
||||
old_num_faces = old_volumep->getNumFaces() ;
|
||||
old_volumep = NULL ;
|
||||
|
||||
{
|
||||
LLFastTimer ftm(FTM_GEN_VOLUME);
|
||||
const LLVolumeParams &volume_params = getVolume()->getParams();
|
||||
setVolume(volume_params, 0);
|
||||
}
|
||||
|
||||
new_volumep = getVolume();
|
||||
new_lod = new_volumep->getDetail();
|
||||
new_num_faces = new_volumep->getNumFaces() ;
|
||||
new_volumep = NULL ;
|
||||
|
||||
if ((new_lod != old_lod) || mSculptChanged)
|
||||
{
|
||||
sNumLODChanges += new_num_faces ;
|
||||
|
||||
if((S32)getNumTEs() != getVolume()->getNumFaces())
|
||||
{
|
||||
setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
|
||||
}
|
||||
|
||||
drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_GEN_TRIANGLES);
|
||||
regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs();
|
||||
if (regen_faces)
|
||||
{
|
||||
regenFaces();
|
||||
}
|
||||
|
||||
if (mSculptChanged)
|
||||
{ //changes in sculpt maps can thrash an object bounding box without
|
||||
//triggering a spatial group bounding box update -- force spatial group
|
||||
//to update bounding boxes
|
||||
LLSpatialGroup* group = mDrawable->getSpatialGroup();
|
||||
if (group)
|
||||
{
|
||||
group->unbound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return regen_faces;
|
||||
}
|
||||
|
||||
BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
||||
{
|
||||
LLFastTimer t(FTM_UPDATE_PRIMITIVES);
|
||||
@@ -1595,8 +1655,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
||||
group->dirtyMesh();
|
||||
}
|
||||
|
||||
BOOL compiled = FALSE;
|
||||
|
||||
updateRelativeXform();
|
||||
|
||||
if (mDrawable.isNull()) // Not sure why this is happening, but it is...
|
||||
@@ -1608,83 +1666,35 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
||||
{
|
||||
dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
|
||||
|
||||
compiled = TRUE;
|
||||
bool was_regen_faces = false;
|
||||
|
||||
if (mVolumeChanged)
|
||||
{
|
||||
LLFastTimer ftm(FTM_GEN_VOLUME);
|
||||
LLVolumeParams volume_params = getVolume()->getParams();
|
||||
setVolume(volume_params, 0);
|
||||
was_regen_faces = lodOrSculptChanged(drawable);
|
||||
drawable->setState(LLDrawable::REBUILD_VOLUME);
|
||||
}
|
||||
|
||||
else if (mSculptChanged || mLODChanged)
|
||||
{
|
||||
was_regen_faces = lodOrSculptChanged(drawable);
|
||||
}
|
||||
|
||||
if (!was_regen_faces) {
|
||||
LLFastTimer t(FTM_GEN_TRIANGLES);
|
||||
regenFaces();
|
||||
genBBoxes(FALSE);
|
||||
}
|
||||
|
||||
genBBoxes(FALSE);
|
||||
}
|
||||
else if ((mLODChanged) || (mSculptChanged))
|
||||
else if (mLODChanged || mSculptChanged)
|
||||
{
|
||||
dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));
|
||||
lodOrSculptChanged(drawable);
|
||||
genBBoxes(FALSE);
|
||||
|
||||
LLVolume *old_volumep, *new_volumep;
|
||||
F32 old_lod, new_lod;
|
||||
S32 old_num_faces, new_num_faces ;
|
||||
|
||||
old_volumep = getVolume();
|
||||
old_lod = old_volumep->getDetail();
|
||||
old_num_faces = old_volumep->getNumFaces() ;
|
||||
old_volumep = NULL ;
|
||||
|
||||
{
|
||||
LLFastTimer ftm(FTM_GEN_VOLUME);
|
||||
LLVolumeParams volume_params = getVolume()->getParams();
|
||||
setVolume(volume_params, 0);
|
||||
}
|
||||
|
||||
new_volumep = getVolume();
|
||||
new_lod = new_volumep->getDetail();
|
||||
new_num_faces = new_volumep->getNumFaces() ;
|
||||
new_volumep = NULL ;
|
||||
|
||||
if ((new_lod != old_lod) || mSculptChanged)
|
||||
{
|
||||
compiled = TRUE;
|
||||
sNumLODChanges += new_num_faces ;
|
||||
|
||||
if((S32)getNumTEs() != getVolume()->getNumFaces())
|
||||
{
|
||||
setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces.
|
||||
}
|
||||
|
||||
drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles()
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_GEN_TRIANGLES);
|
||||
if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs())
|
||||
{
|
||||
regenFaces();
|
||||
}
|
||||
genBBoxes(FALSE);
|
||||
|
||||
if (mSculptChanged)
|
||||
{ //changes in sculpt maps can thrash an object bounding box without
|
||||
//triggering a spatial group bounding box update -- force spatial group
|
||||
//to update bounding boxes
|
||||
LLSpatialGroup* group = mDrawable->getSpatialGroup();
|
||||
if (group)
|
||||
{
|
||||
group->unbound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local
|
||||
else
|
||||
{
|
||||
compiled = TRUE;
|
||||
// All it did was move or we changed the texture coordinate offset
|
||||
LLFastTimer t(FTM_GEN_TRIANGLES);
|
||||
genBBoxes(FALSE);
|
||||
@@ -1692,7 +1702,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
|
||||
|
||||
// Update face flags
|
||||
updateFaceFlags();
|
||||
|
||||
|
||||
mVolumeChanged = FALSE;
|
||||
mLODChanged = FALSE;
|
||||
mSculptChanged = FALSE;
|
||||
@@ -1819,7 +1829,7 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color)
|
||||
const LLTextureEntry *tep = getTE(te);
|
||||
if (!tep)
|
||||
{
|
||||
LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL;
|
||||
LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL;
|
||||
}
|
||||
else if (color != tep->getColor())
|
||||
{
|
||||
@@ -1971,10 +1981,237 @@ S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
|
||||
return res;
|
||||
}
|
||||
|
||||
bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture)
|
||||
{ //Ok, here we have confirmation about texture creation, check our wait-list
|
||||
//and make changes, or return false
|
||||
|
||||
std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
|
||||
|
||||
typedef std::map<U8, LLMaterialPtr> map_te_material;
|
||||
map_te_material new_material;
|
||||
|
||||
for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
|
||||
{
|
||||
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
|
||||
|
||||
//here we just interesting in DIFFUSE_MAP only!
|
||||
if(cur_material.notNull() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat())
|
||||
{ //ok let's check the diffuse mode
|
||||
switch(cur_material->getDiffuseAlphaMode())
|
||||
{
|
||||
case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
|
||||
case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
|
||||
case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
|
||||
{ //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
|
||||
|
||||
LLMaterialPtr mat = NULL;
|
||||
map_te_material::iterator it = new_material.find(range_it->second.te);
|
||||
if(new_material.end() == it) {
|
||||
mat = new LLMaterial(cur_material->asLLSD());
|
||||
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
|
||||
} else {
|
||||
mat = it->second;
|
||||
}
|
||||
|
||||
mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
|
||||
|
||||
} break;
|
||||
} //switch
|
||||
} //if
|
||||
} //for
|
||||
|
||||
//setup new materials
|
||||
for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
|
||||
{
|
||||
LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
|
||||
LLViewerObject::setTEMaterialParams(it->first, it->second);
|
||||
}
|
||||
|
||||
//clear wait-list
|
||||
mWaitingTextureInfo.erase(range.first, range.second);
|
||||
|
||||
return 0 != new_material.size();
|
||||
}
|
||||
|
||||
bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)
|
||||
{ //Ok, here if we wait information about texture and it's missing
|
||||
//then depending from the texture map (diffuse, normal, or specular)
|
||||
//make changes in material and confirm it. If not return false.
|
||||
std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
|
||||
if(range.first == range.second) return false;
|
||||
|
||||
typedef std::map<U8, LLMaterialPtr> map_te_material;
|
||||
map_te_material new_material;
|
||||
|
||||
for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
|
||||
{
|
||||
LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
|
||||
if (cur_material.isNull())
|
||||
continue;
|
||||
|
||||
switch(range_it->second.map)
|
||||
{
|
||||
case LLRender::DIFFUSE_MAP:
|
||||
{
|
||||
if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode())
|
||||
{ //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
|
||||
LLMaterialPtr mat = NULL;
|
||||
map_te_material::iterator it = new_material.find(range_it->second.te);
|
||||
if(new_material.end() == it) {
|
||||
mat = new LLMaterial(cur_material->asLLSD());
|
||||
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
|
||||
} else {
|
||||
mat = it->second;
|
||||
}
|
||||
|
||||
mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
|
||||
}
|
||||
} break;
|
||||
case LLRender::NORMAL_MAP:
|
||||
{ //missing texture => reset material texture id
|
||||
LLMaterialPtr mat = NULL;
|
||||
map_te_material::iterator it = new_material.find(range_it->second.te);
|
||||
if(new_material.end() == it) {
|
||||
mat = new LLMaterial(cur_material->asLLSD());
|
||||
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
|
||||
} else {
|
||||
mat = it->second;
|
||||
}
|
||||
|
||||
mat->setNormalID(LLUUID::null);
|
||||
} break;
|
||||
case LLRender::SPECULAR_MAP:
|
||||
{ //missing texture => reset material texture id
|
||||
LLMaterialPtr mat = NULL;
|
||||
map_te_material::iterator it = new_material.find(range_it->second.te);
|
||||
if(new_material.end() == it) {
|
||||
mat = new LLMaterial(cur_material->asLLSD());
|
||||
new_material.insert(map_te_material::value_type(range_it->second.te, mat));
|
||||
} else {
|
||||
mat = it->second;
|
||||
}
|
||||
|
||||
mat->setSpecularID(LLUUID::null);
|
||||
} break;
|
||||
case LLRender::NUM_TEXTURE_CHANNELS:
|
||||
//nothing to do, make compiler happy
|
||||
break;
|
||||
} //switch
|
||||
} //for
|
||||
|
||||
//setup new materials
|
||||
for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
|
||||
{
|
||||
LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
|
||||
LLViewerObject::setTEMaterialParams(it->first, it->second);
|
||||
}
|
||||
|
||||
//clear wait-list
|
||||
mWaitingTextureInfo.erase(range.first, range.second);
|
||||
|
||||
return 0 != new_material.size();
|
||||
}
|
||||
|
||||
S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
|
||||
{
|
||||
S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams);
|
||||
LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res
|
||||
LLMaterialPtr pMaterial = const_cast<LLMaterialPtr&>(pMaterialParams);
|
||||
|
||||
if(pMaterialParams)
|
||||
{ //check all of them according to material settings
|
||||
|
||||
LLViewerTexture *img_diffuse = getTEImage(te);
|
||||
LLViewerTexture *img_normal = getTENormalMap(te);
|
||||
LLViewerTexture *img_specular = getTESpecularMap(te);
|
||||
|
||||
llassert(NULL != img_diffuse);
|
||||
|
||||
LLMaterialPtr new_material = NULL;
|
||||
|
||||
//diffuse
|
||||
if(NULL != img_diffuse)
|
||||
{ //guard
|
||||
if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset())
|
||||
{ //ok here we don't have information about texture, let's belief and leave material settings
|
||||
//but we remember this case
|
||||
mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
|
||||
}
|
||||
else
|
||||
{
|
||||
bool bSetDiffuseNone = false;
|
||||
if(img_diffuse->isMissingAsset())
|
||||
{
|
||||
bSetDiffuseNone = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(pMaterialParams->getDiffuseAlphaMode())
|
||||
{
|
||||
case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
|
||||
case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
|
||||
case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
|
||||
{ //all of them modes available only for 32 bit textures
|
||||
if(GL_RGBA != img_diffuse->getPrimaryFormat())
|
||||
{
|
||||
bSetDiffuseNone = true;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} //else
|
||||
|
||||
|
||||
if(bSetDiffuseNone)
|
||||
{ //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE
|
||||
new_material = new LLMaterial(pMaterialParams->asLLSD());
|
||||
new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//normal
|
||||
if(LLUUID::null != pMaterialParams->getNormalID())
|
||||
{
|
||||
if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID())
|
||||
{
|
||||
if(!new_material) {
|
||||
new_material = new LLMaterial(pMaterialParams->asLLSD());
|
||||
}
|
||||
new_material->setNormalID(LLUUID::null);
|
||||
}
|
||||
else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat())
|
||||
{ //ok here we don't have information about texture, let's belief and leave material settings
|
||||
//but we remember this case
|
||||
mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//specular
|
||||
if(LLUUID::null != pMaterialParams->getSpecularID())
|
||||
{
|
||||
if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID())
|
||||
{
|
||||
if(!new_material) {
|
||||
new_material = new LLMaterial(pMaterialParams->asLLSD());
|
||||
}
|
||||
new_material->setSpecularID(LLUUID::null);
|
||||
}
|
||||
else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat())
|
||||
{ //ok here we don't have information about texture, let's belief and leave material settings
|
||||
//but we remember this case
|
||||
mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te)));
|
||||
}
|
||||
}
|
||||
|
||||
if(new_material) {
|
||||
pMaterial = new_material;
|
||||
LLMaterialMgr::getInstance()->put(getID(),te,*pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial);
|
||||
|
||||
LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res
|
||||
<< ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
|
||||
<< LL_ENDL;
|
||||
setChanged(ALL_CHANGED);
|
||||
@@ -4597,60 +4834,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
|
||||
//get drawpool of avatar with rigged face
|
||||
LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);
|
||||
|
||||
//Determine if we've received skininfo that contains an
|
||||
//alternate bind matrix - if it does then apply the translational component
|
||||
//to the joints of the avatar.
|
||||
bool pelvisGotSet = false;
|
||||
|
||||
|
||||
// FIXME should this be inside the face loop?
|
||||
// doesn't seem to depend on any per-face state.
|
||||
if ( pAvatarVO )
|
||||
{
|
||||
LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
|
||||
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
|
||||
|
||||
if ( pSkinData )
|
||||
{
|
||||
const int bindCnt = pSkinData->mAlternateBindMatrix.size();
|
||||
if ( bindCnt > 0 )
|
||||
{
|
||||
const int jointCnt = pSkinData->mJointNames.size();
|
||||
const F32 pelvisZOffset = pSkinData->mPelvisOffset;
|
||||
bool fullRig = (jointCnt>=20) ? true : false;
|
||||
if ( fullRig )
|
||||
{
|
||||
for ( int i=0; i<jointCnt; ++i )
|
||||
{
|
||||
std::string lookingForJoint = pSkinData->mJointNames[i].c_str();
|
||||
//LL_INFOS() <<"joint name "<<lookingForJoint.c_str()<<LL_ENDL;
|
||||
LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint );
|
||||
if ( pJoint && pJoint->getId() != currentId )
|
||||
{
|
||||
pJoint->setId( currentId );
|
||||
const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation();
|
||||
//Set the joint position
|
||||
pJoint->storeCurrentXform( jointPos );
|
||||
//If joint is a pelvis then handle old/new pelvis to foot values
|
||||
if ( lookingForJoint == "mPelvis" )
|
||||
{
|
||||
pJoint->storeCurrentXform( jointPos );
|
||||
if ( !pAvatarVO->hasPelvisOffset() )
|
||||
{
|
||||
pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset );
|
||||
//Trigger to rebuild viewer AV
|
||||
pelvisGotSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//If we've set the pelvis to a new position we need to also rebuild some information that the
|
||||
//viewer does at launch (e.g. body size etc.)
|
||||
if ( pelvisGotSet )
|
||||
{
|
||||
pAvatarVO->postPelvisSetRecalc();
|
||||
pAvatarVO->addAttachmentPosOverridesForObject(vobj);
|
||||
}
|
||||
|
||||
if (pool)
|
||||
@@ -5407,6 +5596,10 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
|
||||
for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)
|
||||
{
|
||||
LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable();
|
||||
if(!drawablep)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (S32 i = 0; i < drawablep->getNumFaces(); ++i)
|
||||
{
|
||||
LLFace* face = drawablep->getFace(i);
|
||||
|
||||
@@ -358,6 +358,10 @@ protected:
|
||||
void cleanUpMediaImpls();
|
||||
void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ;
|
||||
void removeMediaImpl(S32 texture_index) ;
|
||||
|
||||
private:
|
||||
bool lodOrSculptChanged(LLDrawable *drawable);
|
||||
|
||||
public:
|
||||
|
||||
static S32 getRenderComplexityMax() {return mRenderComplexity_last;}
|
||||
@@ -402,6 +406,26 @@ protected:
|
||||
static S32 sNumLODChanges;
|
||||
|
||||
friend class LLVolumeImplFlexible;
|
||||
|
||||
public:
|
||||
bool notifyAboutCreatingTexture(LLViewerTexture *texture);
|
||||
bool notifyAboutMissingAsset(LLViewerTexture *texture);
|
||||
|
||||
private:
|
||||
struct material_info
|
||||
{
|
||||
LLRender::eTexIndex map;
|
||||
U8 te;
|
||||
|
||||
material_info(LLRender::eTexIndex map_, U8 te_)
|
||||
: map(map_)
|
||||
, te(te_)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef std::multimap<LLUUID, material_info> mmap_UUID_MAP_t;
|
||||
mmap_UUID_MAP_t mWaitingTextureInfo;
|
||||
|
||||
};
|
||||
|
||||
#endif // LL_LLVOVOLUME_H
|
||||
|
||||
Reference in New Issue
Block a user