V3 mesh, texture, and hover merge.

This commit is contained in:
Shyotl
2016-04-26 13:36:39 -05:00
parent be5d2f20bc
commit 55b5f60b68
39 changed files with 6860 additions and 4126 deletions

View File

@@ -655,7 +655,6 @@ set(viewer_HEADER_FILES
llavataractions.h
llavatarpropertiesprocessor.h
llbox.h
llcallbacklist.h
llcallingcard.h
llcapabilitylistener.h
llcaphttpsender.h

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 &params) const;
LLImportMaterial()
: mFullbright(false)
{
mDiffuseColor.set(1, 1, 1, 1);
}
LLImportMaterial(LLSD& data);
LLSD asLLSD();
};
class LLModelInstance
{
public:
LLPointer<LLModel> mModel;
LLPointer<LLModel> mLOD[5];
std::string mLabel;
LLUUID mMeshID;
S32 mLocalMeshID;
LLMatrix4 mTransform;
std::map<std::string, LLImportMaterial> mMaterial;
LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials)
: mModel(model), mLabel(label), mTransform(transform), mMaterial(materials)
{
mLocalMeshID = -1;
}
LLModelInstance(LLSD& data);
LLSD asLLSD();
};
class LLPhysicsDecomp : public LLThread
{
public:
@@ -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;

View File

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

View File

@@ -141,6 +141,8 @@ public:
virtual LLVOAvatar* asAvatar();
LLVOAvatar* getAvatarAncestor();
static void initVOClasses();
static void cleanupVOClasses();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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