Merge branch 'master' into DRTVWR-500
# Conflicts: # indra/newview/pipeline.cppmaster
commit
c757c29c95
|
|
@ -486,6 +486,16 @@ Geenz Spad
|
|||
STORM-1900
|
||||
STORM-1905
|
||||
NORSPEC-229
|
||||
BUG-226611
|
||||
BUG-226617
|
||||
BUG-226618
|
||||
BUG-226646
|
||||
BUG-226647
|
||||
BUG-226648
|
||||
OPEN-339
|
||||
BUG-226620
|
||||
OPEN-340
|
||||
OPEN-343
|
||||
Gene Frostbite
|
||||
GeneJ Composer
|
||||
Geneko Nemeth
|
||||
|
|
@ -1075,6 +1085,7 @@ Nicky Dasmijn
|
|||
SL-10291
|
||||
SL-10293
|
||||
SL-11061
|
||||
SL-11072
|
||||
Nicky Perian
|
||||
OPEN-1
|
||||
STORM-1087
|
||||
|
|
@ -1326,6 +1337,7 @@ Sovereign Engineer
|
|||
STORM-2148
|
||||
MAINT-7343
|
||||
SL-11079
|
||||
OPEN-343
|
||||
SpacedOut Frye
|
||||
VWR-34
|
||||
VWR-45
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
use_prebuilt_binary(libatmosphere)
|
||||
set(LIBATMOSPHERE_LIBRARIES atmosphere)
|
||||
set(LIBATMOSPHERE_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/atmosphere)
|
||||
|
|
@ -81,8 +81,8 @@ public:
|
|||
LLAvatarBoneInfo() : mIsJoint(FALSE) {}
|
||||
~LLAvatarBoneInfo()
|
||||
{
|
||||
std::for_each(mChildList.begin(), mChildList.end(), DeletePointer());
|
||||
mChildList.clear();
|
||||
std::for_each(mChildren.begin(), mChildren.end(), DeletePointer());
|
||||
mChildren.clear();
|
||||
}
|
||||
BOOL parseXml(LLXmlTreeNode* node);
|
||||
|
||||
|
|
@ -96,8 +96,8 @@ private:
|
|||
LLVector3 mRot;
|
||||
LLVector3 mScale;
|
||||
LLVector3 mPivot;
|
||||
typedef std::vector<LLAvatarBoneInfo*> child_list_t;
|
||||
child_list_t mChildList;
|
||||
typedef std::vector<LLAvatarBoneInfo*> bones_t;
|
||||
bones_t mChildren;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
|
@ -679,8 +679,8 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
|
|||
|
||||
|
||||
// setup children
|
||||
LLAvatarBoneInfo::child_list_t::const_iterator iter;
|
||||
for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter)
|
||||
LLAvatarBoneInfo::bones_t::const_iterator iter;
|
||||
for (iter = info->mChildren.begin(); iter != info->mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarBoneInfo *child_info = *iter;
|
||||
if (!setupBone(child_info, joint, volume_num, joint_num))
|
||||
|
|
@ -1684,7 +1684,7 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
|
|||
delete child_info;
|
||||
return FALSE;
|
||||
}
|
||||
mChildList.push_back(child_info);
|
||||
mChildren.push_back(child_info);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1743,10 +1743,9 @@ void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info)
|
|||
mJointAliasMap[*i] = bone_name;
|
||||
}
|
||||
|
||||
LLAvatarBoneInfo::child_list_t::const_iterator iter;
|
||||
for (iter = bone_info->mChildList.begin(); iter != bone_info->mChildList.end(); ++iter)
|
||||
for (LLAvatarBoneInfo* bone : bone_info->mChildren)
|
||||
{
|
||||
makeJointAliases( *iter );
|
||||
makeJointAliases(bone);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ void LLAvatarJoint::setValid( BOOL valid, BOOL recursive )
|
|||
//----------------------------------------------------------------
|
||||
if (recursive)
|
||||
{
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
|
||||
|
|
@ -118,10 +118,10 @@ void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive )
|
|||
mComponents = comp;
|
||||
if (recursive)
|
||||
{
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
|
||||
joint->setSkeletonComponents(comp, recursive);
|
||||
}
|
||||
}
|
||||
|
|
@ -133,7 +133,7 @@ void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive)
|
|||
|
||||
if (recursive)
|
||||
{
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
|
||||
|
|
@ -144,27 +144,27 @@ void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive)
|
|||
|
||||
void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
|
||||
{
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
|
||||
joint->updateFaceSizes(num_vertices, num_indices, pixel_area);
|
||||
}
|
||||
}
|
||||
|
||||
void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update)
|
||||
{
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
|
||||
joint->updateFaceData(face, pixel_area, damp_wind, terse_update);
|
||||
}
|
||||
}
|
||||
|
||||
void LLAvatarJoint::updateJointGeometry()
|
||||
{
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
|
|
@ -178,10 +178,10 @@ BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate)
|
|||
BOOL lod_changed = FALSE;
|
||||
BOOL found_lod = FALSE;
|
||||
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
|
||||
F32 jointLOD = joint->getLOD();
|
||||
|
||||
if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD)
|
||||
|
|
@ -207,10 +207,10 @@ BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate)
|
|||
|
||||
void LLAvatarJoint::dump()
|
||||
{
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
|
||||
LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
|
||||
joint->dump();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
|
|||
}
|
||||
|
||||
// depth-first traversal
|
||||
for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
|
||||
for (LLJoint::joints_t::iterator iter = current_joint->mChildren.begin();
|
||||
iter != current_joint->mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
|
||||
|
|
|
|||
|
|
@ -614,7 +614,7 @@ void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight)
|
|||
mAvatarAppearance->isValid() &&
|
||||
driven->mParam->getCrossWearable())
|
||||
{
|
||||
LLWearable* wearable = dynamic_cast<LLWearable*> (mWearablep);
|
||||
LLWearable* wearable = mWearablep;
|
||||
if (mAvatarAppearance->getWearableData()->isOnTop(wearable))
|
||||
{
|
||||
use_self = true;
|
||||
|
|
|
|||
|
|
@ -816,8 +816,8 @@ void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height,
|
|||
U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1);
|
||||
U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1);
|
||||
|
||||
mWeights[index] = ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f;
|
||||
|
||||
mWeights[index] = maskTextureData ? ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f : 0.0f;
|
||||
|
||||
if (invert)
|
||||
{
|
||||
mWeights[index] = 1.f - mWeights[index];
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
|
|||
mJointScales[joint] = bone_info->mScaleDeformation;
|
||||
|
||||
// apply to children that need to inherit it
|
||||
for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
|
||||
for (LLJoint::joints_t::iterator iter = joint->mChildren.begin();
|
||||
iter != joint->mChildren.end(); ++iter)
|
||||
{
|
||||
LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success)
|
|||
popProjection();
|
||||
}
|
||||
|
||||
BOOL LLTexLayerSetBuffer::renderTexLayerSet()
|
||||
BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target)
|
||||
{
|
||||
// Default color mask for tex layer render
|
||||
gGL.setColorMask(true, true);
|
||||
|
|
@ -161,7 +161,7 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet()
|
|||
// Composite the color data
|
||||
LLGLSUIDefault gls_ui;
|
||||
success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(),
|
||||
getCompositeWidth(), getCompositeHeight() );
|
||||
getCompositeWidth(), getCompositeHeight(), bound_target );
|
||||
gGL.flush();
|
||||
|
||||
midRenderTexLayerSet(success);
|
||||
|
|
@ -375,7 +375,7 @@ void LLTexLayerSet::deleteCaches()
|
|||
}
|
||||
|
||||
|
||||
BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
|
||||
BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target )
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
mIsVisible = TRUE;
|
||||
|
|
@ -427,12 +427,12 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
|
|||
if (layer->getRenderPass() == LLTexLayer::RP_COLOR)
|
||||
{
|
||||
gGL.flush();
|
||||
success &= layer->render(x, y, width, height);
|
||||
success &= layer->render(x, y, width, height, bound_target);
|
||||
gGL.flush();
|
||||
}
|
||||
}
|
||||
|
||||
renderAlphaMaskTextures(x, y, width, height, false);
|
||||
renderAlphaMaskTextures(x, y, width, height, bound_target, false);
|
||||
|
||||
stop_glerror();
|
||||
}
|
||||
|
|
@ -523,7 +523,7 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const
|
|||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha");
|
||||
void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height)
|
||||
void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_GATHER_MORPH_MASK_ALPHA);
|
||||
memset(data, 255, width * height);
|
||||
|
|
@ -531,15 +531,15 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S
|
|||
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
|
||||
{
|
||||
LLTexLayerInterface* layer = *iter;
|
||||
layer->gatherAlphaMasks(data, origin_x, origin_y, width, height);
|
||||
layer->gatherAlphaMasks(data, origin_x, origin_y, width, height, bound_target);
|
||||
}
|
||||
|
||||
// Set alpha back to that of our alpha masks.
|
||||
renderAlphaMaskTextures(origin_x, origin_y, width, height, true);
|
||||
renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true);
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures");
|
||||
void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear)
|
||||
void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_TEXTURES);
|
||||
const LLTexLayerSetInfo *info = getInfo();
|
||||
|
|
@ -1065,7 +1065,7 @@ LLTexLayer::~LLTexLayer()
|
|||
iter != mAlphaCache.end(); iter++ )
|
||||
{
|
||||
U8* alpha_data = iter->second;
|
||||
delete [] alpha_data;
|
||||
ll_aligned_free_32(alpha_data);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1124,7 +1124,7 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t ¶m_list, LL
|
|||
}
|
||||
}
|
||||
|
||||
BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
|
||||
BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target)
|
||||
{
|
||||
LLGLEnable color_mat(GL_COLOR_MATERIAL);
|
||||
// *TODO: Is this correct?
|
||||
|
|
@ -1185,7 +1185,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
|
|||
}//*/
|
||||
|
||||
const bool force_render = true;
|
||||
renderMorphMasks(x, y, width, height, net_color, force_render);
|
||||
renderMorphMasks(x, y, width, height, net_color, bound_target, force_render);
|
||||
alpha_mask_specified = TRUE;
|
||||
gGL.flush();
|
||||
gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA);
|
||||
|
|
@ -1428,13 +1428,13 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
|
|||
return success;
|
||||
}
|
||||
|
||||
/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
|
||||
/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
|
||||
{
|
||||
addAlphaMask(data, originX, originY, width, height);
|
||||
addAlphaMask(data, originX, originY, width, height, bound_target);
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_RENDER_MORPH_MASKS("renderMorphMasks");
|
||||
void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render)
|
||||
void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render)
|
||||
{
|
||||
if (!force_render && !hasMorph())
|
||||
{
|
||||
|
|
@ -1572,17 +1572,64 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
|
|||
{
|
||||
alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry
|
||||
alpha_data = iter2->second;
|
||||
delete [] alpha_data;
|
||||
ll_aligned_free_32(alpha_data);
|
||||
mAlphaCache.erase(iter2);
|
||||
}
|
||||
alpha_data = new U8[width * height];
|
||||
mAlphaCache[cache_index] = alpha_data;
|
||||
|
||||
// nSight doesn't support use of glReadPixels
|
||||
if (!LLRender::sNsightDebugSupport)
|
||||
|
||||
// GPUs tend to be very uptight about memory alignment as the DMA used to convey
|
||||
// said data to the card works better when well-aligned so plain old default-aligned heap mem is a no-no
|
||||
//new U8[width * height];
|
||||
size_t bytes_per_pixel = 1; // unsigned byte alpha channel only...
|
||||
size_t row_size = (width + 3) & ~0x3; // OpenGL 4-byte row align (even for things < 4 bpp...)
|
||||
size_t pixels = (row_size * height);
|
||||
size_t mem_size = pixels * bytes_per_pixel;
|
||||
|
||||
alpha_data = (U8*)ll_aligned_malloc_32(mem_size);
|
||||
|
||||
bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels
|
||||
|
||||
if (!skip_readback)
|
||||
{
|
||||
glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
|
||||
}
|
||||
if (gGLManager.mIsIntel)
|
||||
{ // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO
|
||||
// returning only the alpha portion without locking up downstream
|
||||
U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA
|
||||
|
||||
if (bound_target)
|
||||
{
|
||||
gGL.getTexUnit(0)->bind(bound_target);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0);
|
||||
}
|
||||
|
||||
glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
|
||||
|
||||
U8* alpha_cursor = alpha_data;
|
||||
U8* pixel = temp;
|
||||
for (int i = 0; i < pixels; i++)
|
||||
{
|
||||
*alpha_cursor++ = pixel[3];
|
||||
pixel += 4;
|
||||
}
|
||||
|
||||
gGL.getTexUnit(0)->disable();
|
||||
|
||||
ll_aligned_free_32(temp);
|
||||
}
|
||||
else
|
||||
{ // platforms with working drivers...
|
||||
glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ll_aligned_free_32(alpha_data);
|
||||
alpha_data = nullptr;
|
||||
}
|
||||
|
||||
mAlphaCache[cache_index] = alpha_data;
|
||||
}
|
||||
|
||||
getTexLayerSet()->getAvatarAppearance()->dirtyMesh();
|
||||
|
|
@ -1593,7 +1640,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
|
|||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_ADD_ALPHA_MASK("addAlphaMask");
|
||||
void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
|
||||
void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_ADD_ALPHA_MASK);
|
||||
S32 size = width * height;
|
||||
|
|
@ -1605,7 +1652,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32
|
|||
// TODO: eliminate need for layer morph mask valid flag
|
||||
invalidateMorphMasks();
|
||||
const bool force_render = false;
|
||||
renderMorphMasks(originX, originY, width, height, net_color, force_render);
|
||||
renderMorphMasks(originX, originY, width, height, net_color, bound_target, force_render);
|
||||
alphaData = getAlphaData();
|
||||
}
|
||||
if (alphaData)
|
||||
|
|
@ -1739,7 +1786,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
|
|||
return layer;
|
||||
}
|
||||
|
||||
/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height)
|
||||
/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target)
|
||||
{
|
||||
if(!mInfo)
|
||||
{
|
||||
|
|
@ -1766,7 +1813,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
|
|||
{
|
||||
wearable->writeToAvatar(mAvatarAppearance);
|
||||
layer->setLTO(lto);
|
||||
success &= layer->render(x,y,width,height);
|
||||
success &= layer->render(x, y, width, height, bound_target);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1788,14 +1835,14 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
|
|||
return success;
|
||||
}
|
||||
|
||||
/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
|
||||
/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
|
||||
{
|
||||
U32 num_wearables = updateWearableCache();
|
||||
U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable
|
||||
LLTexLayer *layer = getLayer(i);
|
||||
if (layer)
|
||||
{
|
||||
layer->addAlphaMask(data, originX, originY, width, height);
|
||||
layer->addAlphaMask(data, originX, originY, width, height, bound_target);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public:
|
|||
LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable);
|
||||
virtual ~LLTexLayerInterface() {}
|
||||
|
||||
virtual BOOL render(S32 x, S32 y, S32 width, S32 height) = 0;
|
||||
virtual BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0;
|
||||
virtual void deleteCaches() = 0;
|
||||
virtual BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0;
|
||||
virtual BOOL isInvisibleAlphaMask() const = 0;
|
||||
|
|
@ -85,7 +85,7 @@ public:
|
|||
BOOL isMorphValid() const { return mMorphMasksValid; }
|
||||
|
||||
void requestUpdate();
|
||||
virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0;
|
||||
virtual void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0;
|
||||
BOOL hasAlphaParams() const { return !mParamAlphaList.empty(); }
|
||||
|
||||
ERenderPass getRenderPass() const;
|
||||
|
|
@ -121,10 +121,10 @@ public:
|
|||
LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance);
|
||||
LLTexLayerTemplate(const LLTexLayerTemplate &layer);
|
||||
/*virtual*/ ~LLTexLayerTemplate();
|
||||
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
|
||||
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target);
|
||||
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions
|
||||
/*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
|
||||
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
|
||||
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
|
||||
/*virtual*/ void setHasMorph(BOOL newval);
|
||||
/*virtual*/ void deleteCaches();
|
||||
/*virtual*/ BOOL isInvisibleAlphaMask() const;
|
||||
|
|
@ -152,16 +152,16 @@ public:
|
|||
/*virtual*/ ~LLTexLayer();
|
||||
|
||||
/*virtual*/ BOOL setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions
|
||||
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height);
|
||||
/*virtual*/ BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target);
|
||||
|
||||
/*virtual*/ void deleteCaches();
|
||||
const U8* getAlphaData() const;
|
||||
|
||||
BOOL findNetColor(LLColor4* color) const;
|
||||
/*virtual*/ BOOL blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
|
||||
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
|
||||
void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render);
|
||||
void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
|
||||
/*virtual*/ void gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
|
||||
void renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render);
|
||||
void addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
|
||||
/*virtual*/ BOOL isInvisibleAlphaMask() const;
|
||||
|
||||
void setLTO(LLLocalTextureObject *lto) { mLocalTextureObject = lto; }
|
||||
|
|
@ -194,13 +194,13 @@ public:
|
|||
const LLTexLayerSetBuffer* getComposite() const; // Do not create one if it doesn't exist.
|
||||
virtual void createComposite() = 0;
|
||||
void destroyComposite();
|
||||
void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height);
|
||||
void gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target);
|
||||
|
||||
const LLTexLayerSetInfo* getInfo() const { return mInfo; }
|
||||
BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
|
||||
|
||||
BOOL render(S32 x, S32 y, S32 width, S32 height);
|
||||
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false);
|
||||
BOOL render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr);
|
||||
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false);
|
||||
|
||||
BOOL isBodyRegion(const std::string& region) const;
|
||||
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
|
||||
|
|
@ -282,7 +282,7 @@ protected:
|
|||
virtual S32 getCompositeOriginY() const = 0;
|
||||
virtual S32 getCompositeWidth() const = 0;
|
||||
virtual S32 getCompositeHeight() const = 0;
|
||||
BOOL renderTexLayerSet();
|
||||
BOOL renderTexLayerSet(LLRenderTarget* bound_target);
|
||||
|
||||
LLTexLayerSet* const mTexLayerSet;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -181,6 +181,6 @@ BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
|
|||
// static
|
||||
LLWearableType::EType LLWearableType::inventoryFlagsToWearableType(U32 flags)
|
||||
{
|
||||
return (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);
|
||||
return (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,16 +31,7 @@
|
|||
#include "lldictionary.h"
|
||||
#include "llinventorytype.h"
|
||||
#include "llsingleton.h"
|
||||
|
||||
class LLTranslationBridge
|
||||
{
|
||||
public:
|
||||
// clang needs this to be happy
|
||||
virtual ~LLTranslationBridge() {}
|
||||
|
||||
virtual std::string getString(const std::string &xml_desc) = 0;
|
||||
};
|
||||
|
||||
#include "llinvtranslationbrdg.h"
|
||||
|
||||
class LLWearableType : public LLParamSingleton<LLWearableType>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ void LLCharacter::dumpCharacter( LLJoint* joint )
|
|||
LL_INFOS() << "DEBUG: " << joint->getName() << " (" << (joint->getParent()?joint->getParent()->getName():std::string("ROOT")) << ")" << LL_ENDL;
|
||||
|
||||
// recurse
|
||||
for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
|
||||
for (LLJoint::joints_t::iterator iter = joint->mChildren.begin();
|
||||
iter != joint->mChildren.end(); ++iter)
|
||||
{
|
||||
LLJoint* child_joint = *iter;
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ void LLJoint::touch(U32 flags)
|
|||
child_flags |= POSITION_DIRTY;
|
||||
}
|
||||
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLJoint* joint = *iter;
|
||||
|
|
@ -251,7 +251,7 @@ LLJoint *LLJoint::findJoint( const std::string &name )
|
|||
if (name == getName())
|
||||
return this;
|
||||
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLJoint* joint = *iter;
|
||||
|
|
@ -286,7 +286,7 @@ void LLJoint::addChild(LLJoint* joint)
|
|||
//--------------------------------------------------------------------
|
||||
void LLJoint::removeChild(LLJoint* joint)
|
||||
{
|
||||
child_list_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
|
||||
joints_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
|
||||
if (iter != mChildren.end())
|
||||
{
|
||||
mChildren.erase(iter);
|
||||
|
|
@ -303,16 +303,17 @@ void LLJoint::removeChild(LLJoint* joint)
|
|||
//--------------------------------------------------------------------
|
||||
void LLJoint::removeAllChildren()
|
||||
{
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end();)
|
||||
for (LLJoint* joint : mChildren)
|
||||
{
|
||||
child_list_t::iterator curiter = iter++;
|
||||
LLJoint* joint = *curiter;
|
||||
mChildren.erase(curiter);
|
||||
joint->mXform.setParent(NULL);
|
||||
joint->mParent = NULL;
|
||||
joint->touch();
|
||||
if (joint)
|
||||
{
|
||||
joint->mXform.setParent(NULL);
|
||||
joint->mParent = NULL;
|
||||
joint->touch();
|
||||
//delete joint;
|
||||
}
|
||||
}
|
||||
mChildren.clear();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -985,7 +986,7 @@ void LLJoint::updateWorldMatrixChildren()
|
|||
{
|
||||
updateWorldMatrix();
|
||||
}
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLJoint* joint = *iter;
|
||||
|
|
@ -1031,7 +1032,7 @@ void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
|
|||
{
|
||||
LLVector3 main_axis(1.f, 0.f, 0.f);
|
||||
|
||||
for (child_list_t::iterator iter = mChildren.begin();
|
||||
for (joints_t::iterator iter = mChildren.begin();
|
||||
iter != mChildren.end(); ++iter)
|
||||
{
|
||||
LLJoint* joint = *iter;
|
||||
|
|
|
|||
|
|
@ -139,8 +139,8 @@ public:
|
|||
S32 mJointNum;
|
||||
|
||||
// child joints
|
||||
typedef std::list<LLJoint*> child_list_t;
|
||||
child_list_t mChildren;
|
||||
typedef std::vector<LLJoint*> joints_t;
|
||||
joints_t mChildren;
|
||||
|
||||
// debug statics
|
||||
static S32 sNumTouches;
|
||||
|
|
|
|||
|
|
@ -2321,7 +2321,7 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
|
|||
LLCharacter* character = *char_iter;
|
||||
|
||||
// look for an existing instance of this motion
|
||||
LLKeyframeMotion* motionp = dynamic_cast<LLKeyframeMotion*> (character->findMotion(asset_uuid));
|
||||
LLKeyframeMotion* motionp = static_cast<LLKeyframeMotion*> (character->findMotion(asset_uuid));
|
||||
if (motionp)
|
||||
{
|
||||
if (0 == status)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ const LLUUID IMG_ALPHA_GRAD ("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEW
|
|||
const LLUUID IMG_ALPHA_GRAD_2D ("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER
|
||||
const LLUUID IMG_TRANSPARENT ("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER
|
||||
|
||||
const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
|
||||
const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
|
||||
const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
|
||||
const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
|
||||
|
|
|
|||
|
|
@ -200,7 +200,6 @@ LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD;
|
|||
LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD_2D;
|
||||
LL_COMMON_API extern const LLUUID IMG_TRANSPARENT;
|
||||
|
||||
LL_COMMON_API extern const LLUUID IMG_BLOOM1;
|
||||
LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
|
||||
LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
|
||||
LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL;
|
||||
|
|
|
|||
|
|
@ -95,11 +95,14 @@ LLAssetDictionary::LLAssetDictionary()
|
|||
addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
|
||||
addEntry(LLAssetType::AT_WIDGET, new AssetEntry("WIDGET", "widget", "widget", false, false, false));
|
||||
addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false));
|
||||
addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true));
|
||||
addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false));
|
||||
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
|
||||
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE));
|
||||
|
||||
};
|
||||
|
||||
const std::string LLAssetType::BADLOOKUP("llassettype_bad_lookup");
|
||||
|
||||
// static
|
||||
LLAssetType::EType LLAssetType::getType(const std::string& desc_name)
|
||||
{
|
||||
|
|
@ -118,7 +121,7 @@ const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
|
|||
}
|
||||
else
|
||||
{
|
||||
return badLookup();
|
||||
return BADLOOKUP;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +136,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type)
|
|||
}
|
||||
else
|
||||
{
|
||||
return badLookup().c_str();
|
||||
return BADLOOKUP.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +174,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
|
|||
}
|
||||
else
|
||||
{
|
||||
return badLookup().c_str();
|
||||
return BADLOOKUP.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -221,14 +224,6 @@ bool LLAssetType::lookupIsLinkType(EType asset_type)
|
|||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
const std::string &LLAssetType::badLookup()
|
||||
{
|
||||
static const std::string sBadLookup = "llassettype_bad_lookup";
|
||||
return sBadLookup;
|
||||
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -116,10 +116,19 @@ public:
|
|||
AT_PERSON = 45,
|
||||
// A user uuid which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop.
|
||||
|
||||
AT_MESH = 49,
|
||||
// Mesh data in our proprietary SLM format
|
||||
|
||||
AT_COUNT = 50,
|
||||
AT_MESH = 49,
|
||||
// Mesh data in our proprietary SLM format
|
||||
|
||||
AT_RESERVED_1 = 50,
|
||||
AT_RESERVED_2 = 51,
|
||||
AT_RESERVED_3 = 52,
|
||||
AT_RESERVED_4 = 53,
|
||||
AT_RESERVED_5 = 54,
|
||||
AT_RESERVED_6 = 55,
|
||||
|
||||
AT_SETTINGS = 56, // Collection of settings
|
||||
|
||||
AT_COUNT = 57,
|
||||
|
||||
// +*********************************************************+
|
||||
// | TO ADD AN ELEMENT TO THIS ENUM: |
|
||||
|
|
@ -153,7 +162,7 @@ public:
|
|||
static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
|
||||
static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
|
||||
|
||||
static const std::string& badLookup(); // error string when a lookup fails
|
||||
static const std::string BADLOOKUP;
|
||||
|
||||
protected:
|
||||
LLAssetType() {}
|
||||
|
|
|
|||
|
|
@ -181,32 +181,35 @@ namespace {
|
|||
return LLError::getEnabledLogTypesMask() & 0x04;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE std::string createANSI(const std::string& color)
|
||||
{
|
||||
std::string ansi_code;
|
||||
ansi_code += '\033';
|
||||
ansi_code += "[";
|
||||
ansi_code += color;
|
||||
ansi_code += "m";
|
||||
return ansi_code;
|
||||
}
|
||||
|
||||
virtual void recordMessage(LLError::ELevel level,
|
||||
const std::string& message) override
|
||||
{
|
||||
if (ANSI_PROBE == mUseANSI)
|
||||
mUseANSI = (checkANSI() ? ANSI_YES : ANSI_NO);
|
||||
{
|
||||
static std::string s_ansi_error = createANSI("31"); // red
|
||||
static std::string s_ansi_warn = createANSI("34"); // blue
|
||||
static std::string s_ansi_debug = createANSI("35"); // magenta
|
||||
|
||||
mUseANSI = (ANSI_PROBE == mUseANSI) ? (checkANSI() ? ANSI_YES : ANSI_NO) : mUseANSI;
|
||||
|
||||
if (ANSI_YES == mUseANSI)
|
||||
{
|
||||
// Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries.
|
||||
colorANSI("1"); // bold
|
||||
switch (level) {
|
||||
case LLError::LEVEL_ERROR:
|
||||
colorANSI("31"); // red
|
||||
break;
|
||||
case LLError::LEVEL_WARN:
|
||||
colorANSI("34"); // blue
|
||||
break;
|
||||
case LLError::LEVEL_DEBUG:
|
||||
colorANSI("35"); // magenta
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
writeANSI((level == LLError::LEVEL_ERROR) ? s_ansi_error :
|
||||
(level == LLError::LEVEL_WARN) ? s_ansi_warn :
|
||||
s_ansi_debug, message);
|
||||
}
|
||||
fprintf(stderr, "%s\n", message.c_str());
|
||||
if (ANSI_YES == mUseANSI) colorANSI("0"); // reset
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s\n", message.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -217,11 +220,14 @@ namespace {
|
|||
ANSI_NO
|
||||
} mUseANSI;
|
||||
|
||||
void colorANSI(const std::string color)
|
||||
LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message)
|
||||
{
|
||||
// ANSI color code escape sequence
|
||||
fprintf(stderr, "\033[%sm", color.c_str() );
|
||||
};
|
||||
static std::string s_ansi_bold = createANSI("1"); // bold
|
||||
static std::string s_ansi_reset = createANSI("0"); // reset
|
||||
// ANSI color code escape sequence, message, and reset in one fprintf call
|
||||
// Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries.
|
||||
fprintf(stderr, "%s%s%s\n%s", s_ansi_bold.c_str(), ansi_code.c_str(), message.c_str(), s_ansi_reset.c_str() );
|
||||
}
|
||||
|
||||
bool checkANSI(void)
|
||||
{
|
||||
|
|
@ -232,8 +238,8 @@ namespace {
|
|||
return (0 != isatty(2)) &&
|
||||
(NULL == getenv("LL_NO_ANSI_COLOR"));
|
||||
#endif // LL_LINUX
|
||||
return false;
|
||||
};
|
||||
return FALSE; // works in a cygwin shell... ;)
|
||||
}
|
||||
};
|
||||
|
||||
class RecordToFixedBuffer : public LLError::Recorder
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
|
|||
//static
|
||||
void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
|
||||
{
|
||||
sMaxHeapSizeInKB = max_heap_size;
|
||||
sMaxHeapSizeInKB = U32Kilobytes::convert(max_heap_size);
|
||||
sEnableMemoryFailurePrevention = prevent_heap_failure ;
|
||||
}
|
||||
|
||||
|
|
@ -93,9 +93,9 @@ void LLMemory::updateMemoryInfo()
|
|||
return ;
|
||||
}
|
||||
|
||||
sAllocatedMemInKB = U64Bytes(counters.WorkingSetSize) ;
|
||||
sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
|
||||
sample(sAllocatedMem, sAllocatedMemInKB);
|
||||
sAllocatedPageSizeInKB = U64Bytes(counters.PagefileUsage) ;
|
||||
sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
|
||||
sample(sVirtualMem, sAllocatedPageSizeInKB);
|
||||
|
||||
U32Kilobytes avail_phys, avail_virtual;
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ public:
|
|||
|
||||
virtual bool has(const String&) const { return false; }
|
||||
virtual LLSD get(const String&) const { return LLSD(); }
|
||||
virtual LLSD getKeys() const { return LLSD::emptyArray(); }
|
||||
virtual void erase(const String&) { }
|
||||
virtual const LLSD& ref(const String&) const{ return undef(); }
|
||||
|
||||
|
|
@ -380,7 +381,8 @@ namespace
|
|||
using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
|
||||
using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
|
||||
virtual LLSD get(const LLSD::String&) const;
|
||||
void insert(const LLSD::String& k, const LLSD& v);
|
||||
virtual LLSD getKeys() const;
|
||||
void insert(const LLSD::String& k, const LLSD& v);
|
||||
virtual void erase(const LLSD::String&);
|
||||
LLSD& ref(const LLSD::String&);
|
||||
virtual const LLSD& ref(const LLSD::String&) const;
|
||||
|
|
@ -421,7 +423,19 @@ namespace
|
|||
DataMap::const_iterator i = mData.find(k);
|
||||
return (i != mData.end()) ? i->second : LLSD();
|
||||
}
|
||||
|
||||
|
||||
LLSD ImplMap::getKeys() const
|
||||
{
|
||||
LLSD keys = LLSD::emptyArray();
|
||||
DataMap::const_iterator iter = mData.begin();
|
||||
while (iter != mData.end())
|
||||
{
|
||||
keys.append((*iter).first);
|
||||
iter++;
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
void ImplMap::insert(const LLSD::String& k, const LLSD& v)
|
||||
{
|
||||
mData.insert(DataMap::value_type(k, v));
|
||||
|
|
@ -502,7 +516,7 @@ namespace
|
|||
virtual LLSD get(LLSD::Integer) const;
|
||||
void set(LLSD::Integer, const LLSD&);
|
||||
void insert(LLSD::Integer, const LLSD&);
|
||||
void append(const LLSD&);
|
||||
LLSD& append(const LLSD&);
|
||||
virtual void erase(LLSD::Integer);
|
||||
LLSD& ref(LLSD::Integer);
|
||||
virtual const LLSD& ref(LLSD::Integer) const;
|
||||
|
|
@ -570,9 +584,10 @@ namespace
|
|||
mData.insert(mData.begin() + index, v);
|
||||
}
|
||||
|
||||
void ImplArray::append(const LLSD& v)
|
||||
LLSD& ImplArray::append(const LLSD& v)
|
||||
{
|
||||
mData.push_back(v);
|
||||
return mData.back();
|
||||
}
|
||||
|
||||
void ImplArray::erase(LLSD::Integer i)
|
||||
|
|
@ -862,6 +877,7 @@ LLSD LLSD::emptyMap()
|
|||
|
||||
bool LLSD::has(const String& k) const { return safe(impl).has(k); }
|
||||
LLSD LLSD::get(const String& k) const { return safe(impl).get(k); }
|
||||
LLSD LLSD::getKeys() const { return safe(impl).getKeys(); }
|
||||
void LLSD::insert(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); }
|
||||
|
||||
LLSD& LLSD::with(const String& k, const LLSD& v)
|
||||
|
|
@ -895,7 +911,7 @@ LLSD& LLSD::with(Integer i, const LLSD& v)
|
|||
makeArray(impl).insert(i, v);
|
||||
return *this;
|
||||
}
|
||||
void LLSD::append(const LLSD& v) { makeArray(impl).append(v); }
|
||||
LLSD& LLSD::append(const LLSD& v) { return makeArray(impl).append(v); }
|
||||
void LLSD::erase(Integer i) { makeArray(impl).erase(i); }
|
||||
|
||||
LLSD& LLSD::operator[](Integer i)
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
an LLSD array).
|
||||
|
||||
An array is a sequence of zero or more LLSD values.
|
||||
|
||||
|
||||
Thread Safety
|
||||
|
||||
In general, these LLSD classes offer *less* safety than STL container
|
||||
|
|
@ -284,6 +284,7 @@ public:
|
|||
|
||||
bool has(const String&) const;
|
||||
LLSD get(const String&) const;
|
||||
LLSD getKeys() const; // Return an LLSD array with keys as strings
|
||||
void insert(const String&, const LLSD&);
|
||||
void erase(const String&);
|
||||
LLSD& with(const String&, const LLSD&);
|
||||
|
|
@ -301,7 +302,7 @@ public:
|
|||
LLSD get(Integer) const;
|
||||
void set(Integer, const LLSD&);
|
||||
void insert(Integer, const LLSD&);
|
||||
void append(const LLSD&);
|
||||
LLSD& append(const LLSD&);
|
||||
void erase(Integer);
|
||||
LLSD& with(Integer, const LLSD&);
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ static const S32 UNZIP_LLSD_MAX_DEPTH = 96;
|
|||
static const char LEGACY_NON_HEADER[] = "<llsd>";
|
||||
const std::string LLSD_BINARY_HEADER("LLSD/Binary");
|
||||
const std::string LLSD_XML_HEADER("LLSD/XML");
|
||||
const std::string LLSD_NOTATION_HEADER("llsd/notation");
|
||||
|
||||
//used to deflate a gzipped asset (currently used for navmeshes)
|
||||
#define windowBits 15
|
||||
|
|
@ -81,6 +82,11 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
|
|||
f = new LLSDXMLFormatter;
|
||||
break;
|
||||
|
||||
case LLSD_NOTATION:
|
||||
str << "<? " << LLSD_NOTATION_HEADER << " ?>\n";
|
||||
f = new LLSDNotationFormatter;
|
||||
break;
|
||||
|
||||
default:
|
||||
LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
|
||||
}
|
||||
|
|
@ -168,6 +174,10 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
|
|||
{
|
||||
p = new LLSDXMLParser;
|
||||
}
|
||||
else if (header == LLSD_NOTATION_HEADER)
|
||||
{
|
||||
p = new LLSDNotationParser;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -706,7 +706,7 @@ class LL_COMMON_API LLSDSerialize
|
|||
public:
|
||||
enum ELLSD_Serialize
|
||||
{
|
||||
LLSD_BINARY, LLSD_XML
|
||||
LLSD_BINARY, LLSD_XML, LLSD_NOTATION
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -322,6 +322,180 @@ BOOL compare_llsd_with_template(
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
// filter_llsd_with_template() is a direct clone (copy-n-paste) of
|
||||
// compare_llsd_with_template with the following differences:
|
||||
// (1) bool vs BOOL return types
|
||||
// (2) A map with the key value "*" is a special value and maps any key in the
|
||||
// test llsd that doesn't have an explicitly matching key in the template.
|
||||
// (3) The element of an array with exactly one element is taken as a template
|
||||
// for *all* the elements of the test array. If the template array is of
|
||||
// different size, compare_llsd_with_template() semantics apply.
|
||||
bool filter_llsd_with_template(
|
||||
const LLSD & llsd_to_test,
|
||||
const LLSD & template_llsd,
|
||||
LLSD & resultant_llsd)
|
||||
{
|
||||
if (llsd_to_test.isUndefined() && template_llsd.isDefined())
|
||||
{
|
||||
resultant_llsd = template_llsd;
|
||||
return true;
|
||||
}
|
||||
else if (llsd_to_test.type() != template_llsd.type())
|
||||
{
|
||||
resultant_llsd = LLSD();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (llsd_to_test.isArray())
|
||||
{
|
||||
//they are both arrays
|
||||
//we loop over all the items in the template
|
||||
//verifying that the to_test has a subset (in the same order)
|
||||
//any shortcoming in the testing_llsd are just taken
|
||||
//to be the rest of the template
|
||||
LLSD data;
|
||||
LLSD::array_const_iterator test_iter;
|
||||
LLSD::array_const_iterator template_iter;
|
||||
|
||||
resultant_llsd = LLSD::emptyArray();
|
||||
test_iter = llsd_to_test.beginArray();
|
||||
|
||||
if (1 == template_llsd.size())
|
||||
{
|
||||
// If the template has a single item, treat it as
|
||||
// the template for *all* items in the test LLSD.
|
||||
template_iter = template_llsd.beginArray();
|
||||
|
||||
for (; test_iter != llsd_to_test.endArray(); ++test_iter)
|
||||
{
|
||||
if (! filter_llsd_with_template(*test_iter, *template_iter, data))
|
||||
{
|
||||
resultant_llsd = LLSD();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultant_llsd.append(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Traditional compare_llsd_with_template matching
|
||||
|
||||
for (template_iter = template_llsd.beginArray();
|
||||
template_iter != template_llsd.endArray() &&
|
||||
test_iter != llsd_to_test.endArray();
|
||||
++template_iter, ++test_iter)
|
||||
{
|
||||
if (! filter_llsd_with_template(*test_iter, *template_iter, data))
|
||||
{
|
||||
resultant_llsd = LLSD();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultant_llsd.append(data);
|
||||
}
|
||||
}
|
||||
|
||||
//so either the test or the template ended
|
||||
//we do another loop now to the end of the template
|
||||
//grabbing the default values
|
||||
for (;
|
||||
template_iter != template_llsd.endArray();
|
||||
++template_iter)
|
||||
{
|
||||
resultant_llsd.append(*template_iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (llsd_to_test.isMap())
|
||||
{
|
||||
resultant_llsd = LLSD::emptyMap();
|
||||
|
||||
//now we loop over the keys of the two maps
|
||||
//any excess is taken from the template
|
||||
//excess is ignored in the test
|
||||
|
||||
// Special tag for wildcarded LLSD map key templates
|
||||
const LLSD::String wildcard_tag("*");
|
||||
|
||||
const bool template_has_wildcard = template_llsd.has(wildcard_tag);
|
||||
LLSD wildcard_value;
|
||||
LLSD value;
|
||||
|
||||
const LLSD::map_const_iterator template_iter_end(template_llsd.endMap());
|
||||
for (LLSD::map_const_iterator template_iter(template_llsd.beginMap());
|
||||
template_iter_end != template_iter;
|
||||
++template_iter)
|
||||
{
|
||||
if (wildcard_tag == template_iter->first)
|
||||
{
|
||||
wildcard_value = template_iter->second;
|
||||
}
|
||||
else if (llsd_to_test.has(template_iter->first))
|
||||
{
|
||||
//the test LLSD has the same key
|
||||
if (! filter_llsd_with_template(llsd_to_test[template_iter->first],
|
||||
template_iter->second,
|
||||
value))
|
||||
{
|
||||
resultant_llsd = LLSD();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultant_llsd[template_iter->first] = value;
|
||||
}
|
||||
}
|
||||
else if (! template_has_wildcard)
|
||||
{
|
||||
// test llsd doesn't have it...take the
|
||||
// template as default value
|
||||
resultant_llsd[template_iter->first] = template_iter->second;
|
||||
}
|
||||
}
|
||||
if (template_has_wildcard)
|
||||
{
|
||||
LLSD sub_value;
|
||||
LLSD::map_const_iterator test_iter;
|
||||
|
||||
for (test_iter = llsd_to_test.beginMap();
|
||||
test_iter != llsd_to_test.endMap();
|
||||
++test_iter)
|
||||
{
|
||||
if (resultant_llsd.has(test_iter->first))
|
||||
{
|
||||
// Final value has test key, assume more specific
|
||||
// template matched and we shouldn't modify it again.
|
||||
continue;
|
||||
}
|
||||
else if (! filter_llsd_with_template(test_iter->second,
|
||||
wildcard_value,
|
||||
sub_value))
|
||||
{
|
||||
// Test value doesn't match wildcarded template
|
||||
resultant_llsd = LLSD();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Test value matches template, add the actuals.
|
||||
resultant_llsd[test_iter->first] = sub_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//of same type...take the test llsd's value
|
||||
resultant_llsd = llsd_to_test;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Helpers for llsd_matches()
|
||||
*****************************************************************************/
|
||||
|
|
@ -681,3 +855,104 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits)
|
|||
return false; // pacify the compiler
|
||||
}
|
||||
}
|
||||
|
||||
// Construct a deep partial clone of of an LLSD object. primitive types share
|
||||
// references, however maps, arrays and binary objects are duplicated. An optional
|
||||
// filter may be include to exclude/include keys in a map.
|
||||
LLSD llsd_clone(LLSD value, LLSD filter)
|
||||
{
|
||||
LLSD clone;
|
||||
bool has_filter(filter.isMap());
|
||||
|
||||
switch (value.type())
|
||||
{
|
||||
case LLSD::TypeMap:
|
||||
clone = LLSD::emptyMap();
|
||||
for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm)
|
||||
{
|
||||
if (has_filter)
|
||||
{
|
||||
if (filter.has((*itm).first))
|
||||
{
|
||||
if (!filter[(*itm).first].asBoolean())
|
||||
continue;
|
||||
}
|
||||
else if (filter.has("*"))
|
||||
{
|
||||
if (!filter["*"].asBoolean())
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
clone[(*itm).first] = llsd_clone((*itm).second, filter);
|
||||
}
|
||||
break;
|
||||
case LLSD::TypeArray:
|
||||
clone = LLSD::emptyArray();
|
||||
for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
|
||||
{
|
||||
clone.append(llsd_clone(*ita, filter));
|
||||
}
|
||||
break;
|
||||
|
||||
case LLSD::TypeBinary:
|
||||
{
|
||||
LLSD::Binary bin(value.asBinary().begin(), value.asBinary().end());
|
||||
clone = LLSD::Binary(bin);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
clone = value;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
LLSD llsd_shallow(LLSD value, LLSD filter)
|
||||
{
|
||||
LLSD shallow;
|
||||
bool has_filter(filter.isMap());
|
||||
|
||||
if (value.isMap())
|
||||
{
|
||||
shallow = LLSD::emptyMap();
|
||||
for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm)
|
||||
{
|
||||
if (has_filter)
|
||||
{
|
||||
if (filter.has((*itm).first))
|
||||
{
|
||||
if (!filter[(*itm).first].asBoolean())
|
||||
continue;
|
||||
}
|
||||
else if (filter.has("*"))
|
||||
{
|
||||
if (!filter["*"].asBoolean())
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
shallow[(*itm).first] = (*itm).second;
|
||||
}
|
||||
}
|
||||
else if (value.isArray())
|
||||
{
|
||||
shallow = LLSD::emptyArray();
|
||||
for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
|
||||
{
|
||||
shallow.append(*ita);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return shallow;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#define LL_LLSDUTIL_H
|
||||
|
||||
#include "llsd.h"
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
// U32
|
||||
LL_COMMON_API LLSD ll_sd_from_U32(const U32);
|
||||
|
|
@ -70,6 +71,19 @@ LL_COMMON_API BOOL compare_llsd_with_template(
|
|||
const LLSD& template_llsd,
|
||||
LLSD& resultant_llsd);
|
||||
|
||||
// filter_llsd_with_template() is a direct clone (copy-n-paste) of
|
||||
// compare_llsd_with_template with the following differences:
|
||||
// (1) bool vs BOOL return types
|
||||
// (2) A map with the key value "*" is a special value and maps any key in the
|
||||
// test llsd that doesn't have an explicitly matching key in the template.
|
||||
// (3) The element of an array with exactly one element is taken as a template
|
||||
// for *all* the elements of the test array. If the template array is of
|
||||
// different size, compare_llsd_with_template() semantics apply.
|
||||
bool filter_llsd_with_template(
|
||||
const LLSD & llsd_to_test,
|
||||
const LLSD & template_llsd,
|
||||
LLSD & resultant_llsd);
|
||||
|
||||
/**
|
||||
* Recursively determine whether a given LLSD data block "matches" another
|
||||
* LLSD prototype. The returned string is empty() on success, non-empty() on
|
||||
|
|
@ -421,4 +435,86 @@ private:
|
|||
|
||||
} // namespace llsd
|
||||
|
||||
|
||||
// Creates a deep clone of an LLSD object. Maps, Arrays and binary objects
|
||||
// are duplicated, atomic primitives (Boolean, Integer, Real, etc) simply
|
||||
// use a shared reference.
|
||||
// Optionally a filter may be specified to control what is duplicated. The
|
||||
// map takes the form "keyname/boolean".
|
||||
// If the value is true the value will be duplicated otherwise it will be skipped
|
||||
// when encountered in a map. A key name of "*" can be specified as a wild card
|
||||
// and will specify the default behavior. If no wild card is given and the clone
|
||||
// encounters a name not in the filter, that value will be skipped.
|
||||
LLSD llsd_clone(LLSD value, LLSD filter = LLSD());
|
||||
|
||||
// Creates a shallow copy of a map or array. If passed any other type of LLSD
|
||||
// object it simply returns that value. See llsd_clone for a description of
|
||||
// the filter parameter.
|
||||
LLSD llsd_shallow(LLSD value, LLSD filter = LLSD());
|
||||
|
||||
|
||||
// Specialization for generating a hash value from an LLSD block.
|
||||
template <>
|
||||
struct boost::hash<LLSD>
|
||||
{
|
||||
typedef LLSD argument_type;
|
||||
typedef std::size_t result_type;
|
||||
result_type operator()(argument_type const& s) const
|
||||
{
|
||||
result_type seed(0);
|
||||
|
||||
LLSD::Type stype = s.type();
|
||||
boost::hash_combine(seed, (S32)stype);
|
||||
|
||||
switch (stype)
|
||||
{
|
||||
case LLSD::TypeBoolean:
|
||||
boost::hash_combine(seed, s.asBoolean());
|
||||
break;
|
||||
case LLSD::TypeInteger:
|
||||
boost::hash_combine(seed, s.asInteger());
|
||||
break;
|
||||
case LLSD::TypeReal:
|
||||
boost::hash_combine(seed, s.asReal());
|
||||
break;
|
||||
case LLSD::TypeURI:
|
||||
case LLSD::TypeString:
|
||||
boost::hash_combine(seed, s.asString());
|
||||
break;
|
||||
case LLSD::TypeUUID:
|
||||
boost::hash_combine(seed, s.asUUID());
|
||||
break;
|
||||
case LLSD::TypeDate:
|
||||
boost::hash_combine(seed, s.asDate().secondsSinceEpoch());
|
||||
break;
|
||||
case LLSD::TypeBinary:
|
||||
{
|
||||
const LLSD::Binary &b(s.asBinary());
|
||||
boost::hash_range(seed, b.begin(), b.end());
|
||||
break;
|
||||
}
|
||||
case LLSD::TypeMap:
|
||||
{
|
||||
for (LLSD::map_const_iterator itm = s.beginMap(); itm != s.endMap(); ++itm)
|
||||
{
|
||||
boost::hash_combine(seed, (*itm).first);
|
||||
boost::hash_combine(seed, (*itm).second);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LLSD::TypeArray:
|
||||
for (LLSD::array_const_iterator ita = s.beginArray(); ita != s.endArray(); ++ita)
|
||||
{
|
||||
boost::hash_combine(seed, (*ita));
|
||||
}
|
||||
break;
|
||||
case LLSD::TypeUndefined:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LL_LLSDUTIL_H
|
||||
|
|
|
|||
|
|
@ -763,6 +763,17 @@ private: \
|
|||
friend class LLSingleton<DERIVED_CLASS>; \
|
||||
DERIVED_CLASS(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* A slight variance from the above, but includes the "override" keyword
|
||||
*/
|
||||
#define LLSINGLETON_C11(DERIVED_CLASS) \
|
||||
private: \
|
||||
/* implement LLSingleton pure virtual method whose sole purpose */ \
|
||||
/* is to remind people to use this macro */ \
|
||||
virtual void you_must_use_LLSINGLETON_macro() override {} \
|
||||
friend class LLSingleton<DERIVED_CLASS>; \
|
||||
DERIVED_CLASS()
|
||||
|
||||
/**
|
||||
* Use LLSINGLETON_EMPTY_CTOR(Foo); at the start of an LLSingleton<Foo>
|
||||
* subclass body when the constructor is trivial:
|
||||
|
|
@ -781,4 +792,8 @@ private: \
|
|||
/* LLSINGLETON() is carefully implemented to permit exactly this */ \
|
||||
LLSINGLETON(DERIVED_CLASS) {}
|
||||
|
||||
#define LLSINGLETON_EMPTY_CTOR_C11(DERIVED_CLASS) \
|
||||
/* LLSINGLETON() is carefully implemented to permit exactly this */ \
|
||||
LLSINGLETON_C11(DERIVED_CLASS) {}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -132,23 +132,34 @@ struct LLUnit
|
|||
return mValue;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void value(storage_t value)
|
||||
LL_FORCE_INLINE void value(const storage_t& value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
template<typename NEW_UNITS>
|
||||
storage_t valueInUnits()
|
||||
storage_t valueInUnits() const
|
||||
{
|
||||
return LLUnit<storage_t, NEW_UNITS>(*this).value();
|
||||
}
|
||||
|
||||
template<typename NEW_UNITS>
|
||||
void valueInUnits(storage_t value)
|
||||
void valueInUnits(const storage_t& value) const
|
||||
{
|
||||
*this = LLUnit<storage_t, NEW_UNITS>(value);
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE operator storage_t() const
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
/*LL_FORCE_INLINE self_t& operator= (storage_t v)
|
||||
{
|
||||
value(v);
|
||||
return *this;
|
||||
}*/
|
||||
|
||||
LL_FORCE_INLINE void operator += (self_t other)
|
||||
{
|
||||
mValue += convert(other).mValue;
|
||||
|
|
@ -159,60 +170,60 @@ struct LLUnit
|
|||
mValue -= convert(other).mValue;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator *= (storage_t multiplicand)
|
||||
LL_FORCE_INLINE void operator *= (const storage_t& multiplicand)
|
||||
{
|
||||
mValue *= multiplicand;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator *= (self_t multiplicand)
|
||||
LL_FORCE_INLINE void operator *= (const self_t& multiplicand)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator /= (storage_t divisor)
|
||||
LL_FORCE_INLINE void operator /= (const storage_t& divisor)
|
||||
{
|
||||
mValue /= divisor;
|
||||
}
|
||||
|
||||
void operator /= (self_t divisor)
|
||||
void operator /= (const self_t& divisor)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
LL_FORCE_INLINE bool operator == (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
|
||||
{
|
||||
return mValue == convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
LL_FORCE_INLINE bool operator != (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
|
||||
{
|
||||
return mValue != convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
LL_FORCE_INLINE bool operator < (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
|
||||
{
|
||||
return mValue < convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
LL_FORCE_INLINE bool operator <= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
|
||||
{
|
||||
return mValue <= convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
LL_FORCE_INLINE bool operator > (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
|
||||
{
|
||||
return mValue > convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
LL_FORCE_INLINE bool operator >= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
|
||||
{
|
||||
return mValue >= convert(other).value();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <vector>
|
||||
#include "stdtypes.h"
|
||||
#include "llpreprocessor.h"
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
class LLMutex;
|
||||
|
||||
|
|
@ -164,6 +165,25 @@ public:
|
|||
LLAssetID makeAssetID(const LLUUID& session) const;
|
||||
};
|
||||
|
||||
// Generate a hash of an LLUUID object using the boost hash templates.
|
||||
template <>
|
||||
struct boost::hash<LLUUID>
|
||||
{
|
||||
typedef LLUUID argument_type;
|
||||
typedef std::size_t result_type;
|
||||
result_type operator()(argument_type const& s) const
|
||||
{
|
||||
result_type seed(0);
|
||||
|
||||
for (S32 i = 0; i < UUID_BYTES; ++i)
|
||||
{
|
||||
boost::hash_combine(seed, s.mData[i]);
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -22,12 +22,17 @@ set(llinventory_SOURCE_FILES
|
|||
llfoldertype.cpp
|
||||
llinventory.cpp
|
||||
llinventorydefines.cpp
|
||||
llinventorysettings.cpp
|
||||
llinventorytype.cpp
|
||||
lllandmark.cpp
|
||||
llnotecard.cpp
|
||||
llparcel.cpp
|
||||
llpermissions.cpp
|
||||
llsaleinfo.cpp
|
||||
llsettingsbase.cpp
|
||||
llsettingsdaycycle.cpp
|
||||
llsettingssky.cpp
|
||||
llsettingswater.cpp
|
||||
lltransactionflags.cpp
|
||||
lluserrelations.cpp
|
||||
)
|
||||
|
|
@ -39,7 +44,9 @@ set(llinventory_HEADER_FILES
|
|||
llfoldertype.h
|
||||
llinventory.h
|
||||
llinventorydefines.h
|
||||
llinventorysettings.h
|
||||
llinventorytype.h
|
||||
llinvtranslationbrdg.h
|
||||
lllandmark.h
|
||||
llnotecard.h
|
||||
llparcel.h
|
||||
|
|
@ -47,6 +54,10 @@ set(llinventory_HEADER_FILES
|
|||
llpermissions.h
|
||||
llpermissionsflags.h
|
||||
llsaleinfo.h
|
||||
llsettingsbase.h
|
||||
llsettingsdaycycle.h
|
||||
llsettingssky.h
|
||||
llsettingswater.h
|
||||
lltransactionflags.h
|
||||
lltransactiontypes.h
|
||||
lluserrelations.h
|
||||
|
|
|
|||
|
|
@ -100,6 +100,8 @@ LLFolderDictionary::LLFolderDictionary()
|
|||
addEntry(LLFolderType::FT_MARKETPLACE_STOCK, new FolderEntry("stock", FALSE));
|
||||
addEntry(LLFolderType::FT_MARKETPLACE_VERSION, new FolderEntry("version", FALSE));
|
||||
|
||||
addEntry(LLFolderType::FT_SETTINGS, new FolderEntry("settings", TRUE));
|
||||
|
||||
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
|
||||
};
|
||||
|
||||
|
|
@ -147,7 +149,7 @@ bool LLFolderType::lookupIsEnsembleType(EType folder_type)
|
|||
// static
|
||||
LLAssetType::EType LLFolderType::folderTypeToAssetType(LLFolderType::EType folder_type)
|
||||
{
|
||||
if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::badLookup())
|
||||
if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::BADLOOKUP)
|
||||
{
|
||||
LL_WARNS() << "Converting to unknown asset type " << folder_type << LL_ENDL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ public:
|
|||
FT_MARKETPLACE_STOCK = 54,
|
||||
FT_MARKETPLACE_VERSION = 55, // Note: We actually *never* create folders with that type. This is used for icon override only.
|
||||
|
||||
FT_SETTINGS = 56,
|
||||
|
||||
FT_COUNT,
|
||||
|
||||
FT_NONE = -1
|
||||
|
|
|
|||
|
|
@ -81,9 +81,10 @@ public:
|
|||
II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS = 0x200000,
|
||||
// Whether a returned object is composed of multiple items.
|
||||
|
||||
II_FLAGS_WEARABLES_MASK = 0xff,
|
||||
// Wearables use the low order byte of flags to store the
|
||||
// LLWearableType::EType enumeration found in newview/llwearable.h
|
||||
II_FLAGS_SUBTYPE_MASK = 0x0000ff,
|
||||
// Some items like Wearables and settings use the low order byte
|
||||
// of flags to store the sub type of the inventory item.
|
||||
// see LLWearableType::EType enumeration found in newview/llwearable.h
|
||||
|
||||
II_FLAGS_PERM_OVERWRITE_MASK = (II_FLAGS_OBJECT_SLAM_PERM |
|
||||
II_FLAGS_OBJECT_SLAM_SALE |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,116 @@
|
|||
/**
|
||||
* @file llinventorysettings.cpp
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llinventorysettings.h"
|
||||
#include "llinventorytype.h"
|
||||
#include "llinventorydefines.h"
|
||||
#include "lldictionary.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llinvtranslationbrdg.h"
|
||||
|
||||
//=========================================================================
|
||||
namespace {
|
||||
LLTranslationBridge::ptr_t sTranslator;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
struct SettingsEntry : public LLDictionaryEntry
|
||||
{
|
||||
SettingsEntry(const std::string &name,
|
||||
const std::string& default_new_name,
|
||||
LLInventoryType::EIconName iconName) :
|
||||
LLDictionaryEntry(name),
|
||||
mDefaultNewName(default_new_name),
|
||||
mLabel(name),
|
||||
mIconName(iconName)
|
||||
{
|
||||
std::string transdname = sTranslator->getString(mLabel);
|
||||
if (!transdname.empty())
|
||||
{
|
||||
mLabel = transdname;
|
||||
}
|
||||
}
|
||||
|
||||
std::string mLabel;
|
||||
std::string mDefaultNewName; //keep mLabel for backward compatibility
|
||||
LLInventoryType::EIconName mIconName;
|
||||
};
|
||||
|
||||
class LLSettingsDictionary : public LLSingleton<LLSettingsDictionary>,
|
||||
public LLDictionary<LLSettingsType::type_e, SettingsEntry>
|
||||
{
|
||||
LLSINGLETON(LLSettingsDictionary);
|
||||
|
||||
void initSingleton();
|
||||
};
|
||||
|
||||
LLSettingsDictionary::LLSettingsDictionary()
|
||||
{
|
||||
}
|
||||
|
||||
void LLSettingsDictionary::initSingleton()
|
||||
{
|
||||
addEntry(LLSettingsType::ST_SKY, new SettingsEntry("sky", "New Sky", LLInventoryType::ICONNAME_SETTINGS_SKY));
|
||||
addEntry(LLSettingsType::ST_WATER, new SettingsEntry("water", "New Water", LLInventoryType::ICONNAME_SETTINGS_WATER));
|
||||
addEntry(LLSettingsType::ST_DAYCYCLE, new SettingsEntry("day", "New Day", LLInventoryType::ICONNAME_SETTINGS_DAY));
|
||||
addEntry(LLSettingsType::ST_NONE, new SettingsEntry("none", "New Settings", LLInventoryType::ICONNAME_SETTINGS));
|
||||
addEntry(LLSettingsType::ST_INVALID, new SettingsEntry("invalid", "New Settings", LLInventoryType::ICONNAME_SETTINGS));
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
||||
LLSettingsType::type_e LLSettingsType::fromInventoryFlags(U32 flags)
|
||||
{
|
||||
return (LLSettingsType::type_e)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK);
|
||||
}
|
||||
|
||||
LLInventoryType::EIconName LLSettingsType::getIconName(LLSettingsType::type_e type)
|
||||
{
|
||||
const SettingsEntry *entry = LLSettingsDictionary::instance().lookup(type);
|
||||
if (!entry)
|
||||
return getIconName(ST_INVALID);
|
||||
return entry->mIconName;
|
||||
}
|
||||
|
||||
std::string LLSettingsType::getDefaultName(LLSettingsType::type_e type)
|
||||
{
|
||||
const SettingsEntry *entry = LLSettingsDictionary::instance().lookup(type);
|
||||
if (!entry)
|
||||
return getDefaultName(ST_INVALID);
|
||||
return entry->mDefaultNewName;
|
||||
}
|
||||
|
||||
void LLSettingsType::initClass(LLTranslationBridge::ptr_t &trans)
|
||||
{
|
||||
sTranslator = trans;
|
||||
}
|
||||
|
||||
void LLSettingsType::cleanupClass()
|
||||
{
|
||||
sTranslator.reset();
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* @file llinventorysettings.h
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, 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_INVENTORY_SETTINGS_H
|
||||
#define LL_INVENTORY_SETTINGS_H
|
||||
|
||||
#include "llinventorytype.h"
|
||||
#include "llinvtranslationbrdg.h"
|
||||
|
||||
class LLSettingsType
|
||||
{
|
||||
public:
|
||||
enum type_e
|
||||
{
|
||||
ST_SKY = 0,
|
||||
ST_WATER = 1,
|
||||
ST_DAYCYCLE = 2,
|
||||
|
||||
ST_INVALID = 255,
|
||||
ST_NONE = -1
|
||||
};
|
||||
|
||||
static type_e fromInventoryFlags(U32 flags);
|
||||
static LLInventoryType::EIconName getIconName(type_e type);
|
||||
static std::string getDefaultName(type_e type);
|
||||
|
||||
static void initClass(LLTranslationBridge::ptr_t &trans);
|
||||
static void cleanupClass();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -85,6 +85,7 @@ LLInventoryDictionary::LLInventoryDictionary()
|
|||
addEntry(LLInventoryType::IT_MESH, new InventoryEntry("mesh", "mesh", 1, LLAssetType::AT_MESH));
|
||||
addEntry(LLInventoryType::IT_WIDGET, new InventoryEntry("widget", "widget", 1, LLAssetType::AT_WIDGET));
|
||||
addEntry(LLInventoryType::IT_PERSON, new InventoryEntry("person", "person", 1, LLAssetType::AT_PERSON));
|
||||
addEntry(LLInventoryType::IT_SETTINGS, new InventoryEntry("settings", "settings", 1, LLAssetType::AT_SETTINGS));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -145,6 +146,14 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
|
|||
LLInventoryType::IT_NONE, // 47 AT_NONE
|
||||
LLInventoryType::IT_NONE, // 48 AT_NONE
|
||||
LLInventoryType::IT_MESH, // 49 AT_MESH
|
||||
|
||||
LLInventoryType::IT_NONE, // 50 AT_RESERVED_1
|
||||
LLInventoryType::IT_NONE, // 51 AT_RESERVED_2
|
||||
LLInventoryType::IT_NONE, // 52 AT_RESERVED_3
|
||||
LLInventoryType::IT_NONE, // 53 AT_RESERVED_4
|
||||
LLInventoryType::IT_NONE, // 54 AT_RESERVED_5
|
||||
|
||||
LLInventoryType::IT_SETTINGS, // 55 AT_SETTINGS
|
||||
};
|
||||
|
||||
// static
|
||||
|
|
@ -200,6 +209,12 @@ bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type)
|
|||
}
|
||||
}
|
||||
|
||||
// Should show permissions that apply only to objects rezed in world.
|
||||
bool LLInventoryType::showInWorldPermissions(LLInventoryType::EType type)
|
||||
{
|
||||
return (type != IT_SETTINGS);
|
||||
}
|
||||
|
||||
bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
|
||||
LLAssetType::EType asset_type)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ public:
|
|||
IT_MESH = 22,
|
||||
IT_WIDGET = 23,
|
||||
IT_PERSON = 24,
|
||||
IT_COUNT = 25,
|
||||
IT_SETTINGS = 25,
|
||||
IT_COUNT = 26,
|
||||
|
||||
IT_UNKNOWN = 255,
|
||||
IT_NONE = -1
|
||||
|
|
@ -112,6 +113,11 @@ public:
|
|||
ICONNAME_LINKFOLDER,
|
||||
ICONNAME_MESH,
|
||||
|
||||
ICONNAME_SETTINGS,
|
||||
ICONNAME_SETTINGS_SKY,
|
||||
ICONNAME_SETTINGS_WATER,
|
||||
ICONNAME_SETTINGS_DAY,
|
||||
|
||||
ICONNAME_INVALID,
|
||||
ICONNAME_UNKNOWN,
|
||||
ICONNAME_COUNT,
|
||||
|
|
@ -131,6 +137,8 @@ public:
|
|||
// true if this type cannot have restricted permissions.
|
||||
static bool cannotRestrictPermissions(EType type);
|
||||
|
||||
static bool showInWorldPermissions(EType type);
|
||||
|
||||
private:
|
||||
// don't instantiate or derive one of these objects
|
||||
LLInventoryType( void );
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* @file llinvtranslationbrdg.h
|
||||
* @brief Translation adapter for inventory.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_TRANSLATIONBRDG_H
|
||||
#define LL_TRANSLATIONBRDG_H
|
||||
|
||||
class LLTranslationBridge
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr<LLTranslationBridge> ptr_t;
|
||||
|
||||
// clang needs this to be happy
|
||||
virtual ~LLTranslationBridge() {}
|
||||
|
||||
virtual std::string getString(const std::string &xml_desc) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -231,6 +231,9 @@ void LLParcel::init(const LLUUID &owner_id,
|
|||
setAllowGroupAVSounds(TRUE);
|
||||
setAllowAnyAVSounds(TRUE);
|
||||
setHaveNewParcelLimitData(FALSE);
|
||||
|
||||
setRegionAllowEnvironmentOverride(FALSE);
|
||||
setParcelEnvironmentVersion(INVALID_PARCEL_ENVIRONMENT_VERSION);
|
||||
}
|
||||
|
||||
void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llpermissions.h"
|
||||
#include "lltimer.h"
|
||||
#include "v3math.h"
|
||||
#include "llsettingsdaycycle.h"
|
||||
|
||||
// Grid out of which parcels taken is stepped every 4 meters.
|
||||
const F32 PARCEL_GRID_STEP_METERS = 4.f;
|
||||
|
|
@ -102,6 +103,10 @@ const U32 RT_SELL = 0x1 << 5;
|
|||
|
||||
const S32 INVALID_PARCEL_ID = -1;
|
||||
|
||||
const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
|
||||
// if Region settings are used, parcel env. version is -1
|
||||
const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
|
||||
|
||||
// Timeouts for parcels
|
||||
// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
|
||||
const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
|
||||
|
|
@ -510,6 +515,10 @@ public:
|
|||
{ return mRegionDenyAgeUnverifiedOverride; }
|
||||
BOOL getRegionAllowAccessOverride() const
|
||||
{ return mRegionAllowAccessoverride; }
|
||||
BOOL getRegionAllowEnvironmentOverride() const
|
||||
{ return mRegionAllowEnvironmentOverride; }
|
||||
S32 getParcelEnvironmentVersion() const
|
||||
{ return mCurrentEnvironmentVersion; }
|
||||
|
||||
|
||||
BOOL getAllowGroupAVSounds() const { return mAllowGroupAVSounds; }
|
||||
|
|
@ -580,6 +589,9 @@ public:
|
|||
void setRegionDenyAnonymousOverride(BOOL override) { mRegionDenyAnonymousOverride = override; }
|
||||
void setRegionDenyAgeUnverifiedOverride(BOOL override) { mRegionDenyAgeUnverifiedOverride = override; }
|
||||
void setRegionAllowAccessOverride(BOOL override) { mRegionAllowAccessoverride = override; }
|
||||
void setRegionAllowEnvironmentOverride(BOOL override) { mRegionAllowEnvironmentOverride = override; }
|
||||
|
||||
void setParcelEnvironmentVersion(S32 version) { mCurrentEnvironmentVersion = version; }
|
||||
|
||||
// Accessors for parcel sellWithObjects
|
||||
void setPreviousOwnerID(LLUUID prev_owner) { mPreviousOwnerID = prev_owner; }
|
||||
|
|
@ -589,8 +601,7 @@ public:
|
|||
LLUUID getPreviousOwnerID() const { return mPreviousOwnerID; }
|
||||
BOOL getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; }
|
||||
BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; }
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
LLUUID mID;
|
||||
LLUUID mOwnerID;
|
||||
|
|
@ -662,10 +673,13 @@ protected:
|
|||
BOOL mRegionDenyAnonymousOverride;
|
||||
BOOL mRegionDenyAgeUnverifiedOverride;
|
||||
BOOL mRegionAllowAccessoverride;
|
||||
BOOL mRegionAllowEnvironmentOverride;
|
||||
BOOL mAllowGroupAVSounds;
|
||||
BOOL mAllowAnyAVSounds;
|
||||
S32 mCurrentEnvironmentVersion;
|
||||
|
||||
|
||||
bool mIsDefaultDayCycle;
|
||||
|
||||
public:
|
||||
// HACK, make private
|
||||
S32 mLocalID;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,751 @@
|
|||
/**
|
||||
* @file llsettingsbase.cpp
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llsettingsbase.h"
|
||||
|
||||
#include "llmath.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "llsdserialize.h"
|
||||
|
||||
//=========================================================================
|
||||
namespace
|
||||
{
|
||||
const LLSettingsBase::TrackPosition BREAK_POINT = 0.5;
|
||||
}
|
||||
|
||||
const LLSettingsBase::TrackPosition LLSettingsBase::INVALID_TRACKPOS(-1.0);
|
||||
const std::string LLSettingsBase::DEFAULT_SETTINGS_NAME("_default_");
|
||||
|
||||
//=========================================================================
|
||||
std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings)
|
||||
{
|
||||
LLSDSerialize::serialize(settings.getSettings(), os, LLSDSerialize::LLSD_NOTATION);
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
const std::string LLSettingsBase::SETTING_ID("id");
|
||||
const std::string LLSettingsBase::SETTING_NAME("name");
|
||||
const std::string LLSettingsBase::SETTING_HASH("hash");
|
||||
const std::string LLSettingsBase::SETTING_TYPE("type");
|
||||
const std::string LLSettingsBase::SETTING_ASSETID("asset_id");
|
||||
const std::string LLSettingsBase::SETTING_FLAGS("flags");
|
||||
|
||||
const U32 LLSettingsBase::FLAG_NOCOPY(0x01 << 0);
|
||||
const U32 LLSettingsBase::FLAG_NOMOD(0x01 << 1);
|
||||
const U32 LLSettingsBase::FLAG_NOTRANS(0x01 << 2);
|
||||
const U32 LLSettingsBase::FLAG_NOSAVE(0x01 << 3);
|
||||
|
||||
const U32 LLSettingsBase::Validator::VALIDATION_PARTIAL(0x01 << 0);
|
||||
|
||||
//=========================================================================
|
||||
LLSettingsBase::LLSettingsBase():
|
||||
mSettings(LLSD::emptyMap()),
|
||||
mDirty(true),
|
||||
mBlendedFactor(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
LLSettingsBase::LLSettingsBase(const LLSD setting) :
|
||||
mSettings(setting),
|
||||
mDirty(true),
|
||||
mBlendedFactor(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void LLSettingsBase::lerpSettings(const LLSettingsBase &other, F64 mix)
|
||||
{
|
||||
mSettings = interpolateSDMap(mSettings, other.mSettings, other.getParameterMap(), mix);
|
||||
setDirtyFlag(true);
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other) const
|
||||
{
|
||||
LLSD newSettings;
|
||||
|
||||
for (LLSD::map_const_iterator it = settings.beginMap(); it != settings.endMap(); ++it)
|
||||
{
|
||||
std::string key_name = (*it).first;
|
||||
LLSD value = (*it).second;
|
||||
|
||||
LLSD::Type setting_type = value.type();
|
||||
switch (setting_type)
|
||||
{
|
||||
case LLSD::TypeMap:
|
||||
newSettings[key_name] = combineSDMaps(value, LLSD());
|
||||
break;
|
||||
case LLSD::TypeArray:
|
||||
newSettings[key_name] = LLSD::emptyArray();
|
||||
for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
|
||||
{
|
||||
newSettings[key_name].append(*ita);
|
||||
}
|
||||
break;
|
||||
//case LLSD::TypeInteger:
|
||||
//case LLSD::TypeReal:
|
||||
//case LLSD::TypeBoolean:
|
||||
//case LLSD::TypeString:
|
||||
//case LLSD::TypeUUID:
|
||||
//case LLSD::TypeURI:
|
||||
//case LLSD::TypeDate:
|
||||
//case LLSD::TypeBinary:
|
||||
default:
|
||||
newSettings[key_name] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!other.isUndefined())
|
||||
{
|
||||
for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it)
|
||||
{
|
||||
std::string key_name = (*it).first;
|
||||
LLSD value = (*it).second;
|
||||
|
||||
LLSD::Type setting_type = value.type();
|
||||
switch (setting_type)
|
||||
{
|
||||
case LLSD::TypeMap:
|
||||
newSettings[key_name] = combineSDMaps(value, LLSD());
|
||||
break;
|
||||
case LLSD::TypeArray:
|
||||
newSettings[key_name] = LLSD::emptyArray();
|
||||
for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
|
||||
{
|
||||
newSettings[key_name].append(*ita);
|
||||
}
|
||||
break;
|
||||
//case LLSD::TypeInteger:
|
||||
//case LLSD::TypeReal:
|
||||
//case LLSD::TypeBoolean:
|
||||
//case LLSD::TypeString:
|
||||
//case LLSD::TypeUUID:
|
||||
//case LLSD::TypeURI:
|
||||
//case LLSD::TypeDate:
|
||||
//case LLSD::TypeBinary:
|
||||
default:
|
||||
newSettings[key_name] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, F64 mix) const
|
||||
{
|
||||
LLSD newSettings;
|
||||
|
||||
stringset_t skip = getSkipInterpolateKeys();
|
||||
stringset_t slerps = getSlerpKeys();
|
||||
|
||||
llassert(mix >= 0.0f && mix <= 1.0f);
|
||||
|
||||
for (LLSD::map_const_iterator it = settings.beginMap(); it != settings.endMap(); ++it)
|
||||
{
|
||||
std::string key_name = (*it).first;
|
||||
LLSD value = (*it).second;
|
||||
|
||||
if (skip.find(key_name) != skip.end())
|
||||
continue;
|
||||
|
||||
LLSD other_value;
|
||||
if (other.has(key_name))
|
||||
{
|
||||
other_value = other[key_name];
|
||||
}
|
||||
else
|
||||
{
|
||||
parammapping_t::const_iterator def_iter = defaults.find(key_name);
|
||||
if (def_iter != defaults.end())
|
||||
{
|
||||
other_value = def_iter->second.getDefaultValue();
|
||||
}
|
||||
else if (value.type() == LLSD::TypeMap)
|
||||
{
|
||||
// interpolate in case there are defaults inside (part of legacy)
|
||||
other_value = LLSDMap();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The other or defaults does not contain this setting, keep the original value
|
||||
// TODO: Should I blend this out instead?
|
||||
newSettings[key_name] = value;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
newSettings[key_name] = interpolateSDValue(key_name, value, other_value, defaults, mix, slerps);
|
||||
}
|
||||
|
||||
// Special handling cases
|
||||
// Flags
|
||||
if (settings.has(SETTING_FLAGS))
|
||||
{
|
||||
U32 flags = (U32)settings[SETTING_FLAGS].asInteger();
|
||||
if (other.has(SETTING_FLAGS))
|
||||
flags |= (U32)other[SETTING_FLAGS].asInteger();
|
||||
|
||||
newSettings[SETTING_FLAGS] = LLSD::Integer(flags);
|
||||
}
|
||||
|
||||
// Now add anything that is in other but not in the settings
|
||||
for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it)
|
||||
{
|
||||
std::string key_name = (*it).first;
|
||||
|
||||
if (skip.find(key_name) != skip.end())
|
||||
continue;
|
||||
|
||||
if (settings.has(key_name))
|
||||
continue;
|
||||
|
||||
parammapping_t::const_iterator def_iter = defaults.find(key_name);
|
||||
if (def_iter != defaults.end())
|
||||
{
|
||||
// Blend against default value
|
||||
newSettings[key_name] = interpolateSDValue(key_name, def_iter->second.getDefaultValue(), (*it).second, defaults, mix, slerps);
|
||||
}
|
||||
else if ((*it).second.type() == LLSD::TypeMap)
|
||||
{
|
||||
// interpolate in case there are defaults inside (part of legacy)
|
||||
newSettings[key_name] = interpolateSDValue(key_name, LLSDMap(), (*it).second, defaults, mix, slerps);
|
||||
}
|
||||
// else do nothing when no known defaults
|
||||
// TODO: Should I blend this out instead?
|
||||
}
|
||||
|
||||
// Note: writes variables from skip list, bug?
|
||||
for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it)
|
||||
{
|
||||
// TODO: Should I blend this in instead?
|
||||
if (skip.find((*it).first) == skip.end())
|
||||
continue;
|
||||
|
||||
if (!settings.has((*it).first))
|
||||
continue;
|
||||
|
||||
newSettings[(*it).first] = (*it).second;
|
||||
}
|
||||
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD &value, const LLSD &other_value, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const
|
||||
{
|
||||
LLSD new_value;
|
||||
|
||||
LLSD::Type setting_type = value.type();
|
||||
|
||||
if (other_value.type() != setting_type)
|
||||
{
|
||||
// The data type mismatched between this and other. Hard switch when we pass the break point
|
||||
// but issue a warning.
|
||||
LL_WARNS("SETTINGS") << "Setting lerp between mismatched types for '" << key_name << "'." << LL_ENDL;
|
||||
new_value = (mix > BREAK_POINT) ? other_value : value;
|
||||
}
|
||||
|
||||
switch (setting_type)
|
||||
{
|
||||
case LLSD::TypeInteger:
|
||||
// lerp between the two values rounding the result to the nearest integer.
|
||||
new_value = LLSD::Integer(llroundf(lerp(value.asReal(), other_value.asReal(), mix)));
|
||||
break;
|
||||
case LLSD::TypeReal:
|
||||
// lerp between the two values.
|
||||
new_value = LLSD::Real(lerp(value.asReal(), other_value.asReal(), mix));
|
||||
break;
|
||||
case LLSD::TypeMap:
|
||||
// deep copy.
|
||||
new_value = interpolateSDMap(value, other_value, defaults, mix);
|
||||
break;
|
||||
|
||||
case LLSD::TypeArray:
|
||||
{
|
||||
LLSD new_array(LLSD::emptyArray());
|
||||
|
||||
if (slerps.find(key_name) != slerps.end())
|
||||
{
|
||||
LLQuaternion a(value);
|
||||
LLQuaternion b(other_value);
|
||||
LLQuaternion q = slerp(mix, a, b);
|
||||
new_array = q.getValue();
|
||||
}
|
||||
else
|
||||
{ // TODO: We could expand this to inspect the type and do a deep lerp based on type.
|
||||
// for now assume a heterogeneous array of reals.
|
||||
size_t len = std::max(value.size(), other_value.size());
|
||||
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
|
||||
new_array[i] = lerp(value[i].asReal(), other_value[i].asReal(), mix);
|
||||
}
|
||||
}
|
||||
|
||||
new_value = new_array;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LLSD::TypeUUID:
|
||||
new_value = value.asUUID();
|
||||
break;
|
||||
|
||||
// case LLSD::TypeBoolean:
|
||||
// case LLSD::TypeString:
|
||||
// case LLSD::TypeURI:
|
||||
// case LLSD::TypeBinary:
|
||||
// case LLSD::TypeDate:
|
||||
default:
|
||||
// atomic or unknown data types. Lerping between them does not make sense so switch at the break.
|
||||
new_value = (mix > BREAK_POINT) ? other_value : value;
|
||||
break;
|
||||
}
|
||||
|
||||
return new_value;
|
||||
}
|
||||
|
||||
LLSettingsBase::stringset_t LLSettingsBase::getSkipInterpolateKeys() const
|
||||
{
|
||||
static stringset_t skipSet;
|
||||
|
||||
if (skipSet.empty())
|
||||
{
|
||||
skipSet.insert(SETTING_FLAGS);
|
||||
skipSet.insert(SETTING_HASH);
|
||||
}
|
||||
|
||||
return skipSet;
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::getSettings() const
|
||||
{
|
||||
return mSettings;
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::cloneSettings() const
|
||||
{
|
||||
U32 flags = getFlags();
|
||||
LLSD settings (combineSDMaps(getSettings(), LLSD()));
|
||||
if (flags)
|
||||
settings[SETTING_FLAGS] = LLSD::Integer(flags);
|
||||
return settings;
|
||||
}
|
||||
|
||||
size_t LLSettingsBase::getHash() const
|
||||
{ // get a shallow copy of the LLSD filtering out values to not include in the hash
|
||||
LLSD hash_settings = llsd_shallow(getSettings(),
|
||||
LLSDMap(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false)("*", true));
|
||||
|
||||
boost::hash<LLSD> hasher;
|
||||
return hasher(hash_settings);
|
||||
}
|
||||
|
||||
bool LLSettingsBase::validate()
|
||||
{
|
||||
validation_list_t validations = getValidationList();
|
||||
|
||||
if (!mSettings.has(SETTING_TYPE))
|
||||
{
|
||||
mSettings[SETTING_TYPE] = getSettingsType();
|
||||
}
|
||||
|
||||
LLSD result = LLSettingsBase::settingValidation(mSettings, validations);
|
||||
|
||||
if (result["errors"].size() > 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Validation errors: " << result["errors"] << LL_ENDL;
|
||||
}
|
||||
if (result["warnings"].size() > 0)
|
||||
{
|
||||
LL_DEBUGS("SETTINGS") << "Validation warnings: " << result["warnings"] << LL_ENDL;
|
||||
}
|
||||
|
||||
return result["success"].asBoolean();
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::settingValidation(LLSD &settings, validation_list_t &validations, bool partial)
|
||||
{
|
||||
static Validator validateName(SETTING_NAME, false, LLSD::TypeString, boost::bind(&Validator::verifyStringLength, _1, 63));
|
||||
static Validator validateId(SETTING_ID, false, LLSD::TypeUUID);
|
||||
static Validator validateHash(SETTING_HASH, false, LLSD::TypeInteger);
|
||||
static Validator validateType(SETTING_TYPE, false, LLSD::TypeString);
|
||||
static Validator validateAssetId(SETTING_ASSETID, false, LLSD::TypeUUID);
|
||||
static Validator validateFlags(SETTING_FLAGS, false, LLSD::TypeInteger);
|
||||
stringset_t validated;
|
||||
stringset_t strip;
|
||||
bool isValid(true);
|
||||
LLSD errors(LLSD::emptyArray());
|
||||
LLSD warnings(LLSD::emptyArray());
|
||||
U32 flags(0);
|
||||
|
||||
if (partial)
|
||||
flags |= Validator::VALIDATION_PARTIAL;
|
||||
|
||||
// Fields common to all settings.
|
||||
if (!validateName.verify(settings, flags))
|
||||
{
|
||||
errors.append( LLSD::String("Unable to validate 'name'.") );
|
||||
isValid = false;
|
||||
}
|
||||
validated.insert(validateName.getName());
|
||||
|
||||
if (!validateId.verify(settings, flags))
|
||||
{
|
||||
errors.append( LLSD::String("Unable to validate 'id'.") );
|
||||
isValid = false;
|
||||
}
|
||||
validated.insert(validateId.getName());
|
||||
|
||||
if (!validateHash.verify(settings, flags))
|
||||
{
|
||||
errors.append( LLSD::String("Unable to validate 'hash'.") );
|
||||
isValid = false;
|
||||
}
|
||||
validated.insert(validateHash.getName());
|
||||
|
||||
if (!validateAssetId.verify(settings, flags))
|
||||
{
|
||||
errors.append(LLSD::String("Invalid asset Id"));
|
||||
isValid = false;
|
||||
}
|
||||
validated.insert(validateAssetId.getName());
|
||||
|
||||
if (!validateType.verify(settings, flags))
|
||||
{
|
||||
errors.append( LLSD::String("Unable to validate 'type'.") );
|
||||
isValid = false;
|
||||
}
|
||||
validated.insert(validateType.getName());
|
||||
|
||||
if (!validateFlags.verify(settings, flags))
|
||||
{
|
||||
errors.append(LLSD::String("Unable to validate 'flags'."));
|
||||
isValid = false;
|
||||
}
|
||||
validated.insert(validateFlags.getName());
|
||||
|
||||
// Fields for specific settings.
|
||||
for (validation_list_t::iterator itv = validations.begin(); itv != validations.end(); ++itv)
|
||||
{
|
||||
#ifdef VALIDATION_DEBUG
|
||||
LLSD oldvalue;
|
||||
if (settings.has((*itv).getName()))
|
||||
{
|
||||
oldvalue = llsd_clone(mSettings[(*itv).getName()]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(*itv).verify(settings, flags))
|
||||
{
|
||||
std::stringstream errtext;
|
||||
|
||||
errtext << "Settings LLSD fails validation and could not be corrected for '" << (*itv).getName() << "'!\n";
|
||||
errors.append( errtext.str() );
|
||||
isValid = false;
|
||||
}
|
||||
validated.insert((*itv).getName());
|
||||
|
||||
#ifdef VALIDATION_DEBUG
|
||||
if (!oldvalue.isUndefined())
|
||||
{
|
||||
if (!compare_llsd(settings[(*itv).getName()], oldvalue))
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Setting '" << (*itv).getName() << "' was changed: " << oldvalue << " -> " << settings[(*itv).getName()] << LL_ENDL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// strip extra entries
|
||||
for (LLSD::map_const_iterator itm = settings.beginMap(); itm != settings.endMap(); ++itm)
|
||||
{
|
||||
if (validated.find((*itm).first) == validated.end())
|
||||
{
|
||||
std::stringstream warntext;
|
||||
|
||||
warntext << "Stripping setting '" << (*itm).first << "'";
|
||||
warnings.append( warntext.str() );
|
||||
strip.insert((*itm).first);
|
||||
}
|
||||
}
|
||||
|
||||
for (stringset_t::iterator its = strip.begin(); its != strip.end(); ++its)
|
||||
{
|
||||
settings.erase(*its);
|
||||
}
|
||||
|
||||
return LLSDMap("success", LLSD::Boolean(isValid))
|
||||
("errors", errors)
|
||||
("warnings", warnings);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
||||
bool LLSettingsBase::Validator::verify(LLSD &data, U32 flags)
|
||||
{
|
||||
if (!data.has(mName) || (data.has(mName) && data[mName].isUndefined()))
|
||||
{
|
||||
if ((flags & VALIDATION_PARTIAL) != 0) // we are doing a partial validation. Do no attempt to set a default if missing (or fail even if required)
|
||||
return true;
|
||||
|
||||
if (!mDefault.isUndefined())
|
||||
{
|
||||
data[mName] = mDefault;
|
||||
return true;
|
||||
}
|
||||
if (mRequired)
|
||||
LL_WARNS("SETTINGS") << "Missing required setting '" << mName << "' with no default." << LL_ENDL;
|
||||
return !mRequired;
|
||||
}
|
||||
|
||||
if (data[mName].type() != mType)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Setting '" << mName << "' is incorrect type." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mVerify.empty() && !mVerify(data[mName]))
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Setting '" << mName << "' fails validation." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyColor(LLSD &value)
|
||||
{
|
||||
return (value.size() == 3 || value.size() == 4);
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyVector(LLSD &value, S32 length)
|
||||
{
|
||||
return (value.size() == length);
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, S32 length)
|
||||
{
|
||||
if (value.size() != length)
|
||||
return false;
|
||||
|
||||
LLSD newvector;
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
LLVector2 vect(value);
|
||||
|
||||
if (is_approx_equal(vect.normalize(), 1.0f))
|
||||
return true;
|
||||
newvector = vect.getValue();
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
LLVector3 vect(value);
|
||||
|
||||
if (is_approx_equal(vect.normalize(), 1.0f))
|
||||
return true;
|
||||
newvector = vect.getValue();
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
LLVector4 vect(value);
|
||||
|
||||
if (is_approx_equal(vect.normalize(), 1.0f))
|
||||
return true;
|
||||
newvector = vect.getValue();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals)
|
||||
{
|
||||
for (S32 index = 0; index < value.size(); ++index)
|
||||
{
|
||||
if (minvals[index].asString() != "*")
|
||||
{
|
||||
if (minvals[index].asReal() > value[index].asReal())
|
||||
{
|
||||
value[index] = minvals[index].asReal();
|
||||
}
|
||||
}
|
||||
if (maxvals[index].asString() != "*")
|
||||
{
|
||||
if (maxvals[index].asReal() < value[index].asReal())
|
||||
{
|
||||
value[index] = maxvals[index].asReal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyQuaternion(LLSD &value)
|
||||
{
|
||||
return (value.size() == 4);
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value)
|
||||
{
|
||||
if (value.size() != 4)
|
||||
return false;
|
||||
|
||||
LLQuaternion quat(value);
|
||||
|
||||
if (is_approx_equal(quat.normalize(), 1.0f))
|
||||
return true;
|
||||
|
||||
LLSD newquat = quat.getValue();
|
||||
for (S32 index = 0; index < 4; ++index)
|
||||
{
|
||||
value[index] = newquat[index];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, LLSD range)
|
||||
{
|
||||
F64 real = value.asReal();
|
||||
|
||||
F64 clampedval = llclamp(LLSD::Real(real), range[0].asReal(), range[1].asReal());
|
||||
|
||||
if (is_approx_equal(clampedval, real))
|
||||
return true;
|
||||
|
||||
value = LLSD::Real(clampedval);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, LLSD range)
|
||||
{
|
||||
S32 ival = value.asInteger();
|
||||
|
||||
S32 clampedval = llclamp(LLSD::Integer(ival), range[0].asInteger(), range[1].asInteger());
|
||||
|
||||
if (clampedval == ival)
|
||||
return true;
|
||||
|
||||
value = LLSD::Integer(clampedval);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, S32 length)
|
||||
{
|
||||
std::string sval = value.asString();
|
||||
|
||||
if (!sval.empty())
|
||||
{
|
||||
sval = sval.substr(0, length);
|
||||
value = LLSD::String(sval);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void LLSettingsBlender::update(const LLSettingsBase::BlendFactor& blendf)
|
||||
{
|
||||
F64 res = setBlendFactor(blendf);
|
||||
llassert(res >= 0.0 && res <= 1.0);
|
||||
(void)res;
|
||||
mTarget->update();
|
||||
}
|
||||
|
||||
F64 LLSettingsBlender::setBlendFactor(const LLSettingsBase::BlendFactor& blendf_in)
|
||||
{
|
||||
LLSettingsBase::TrackPosition blendf = blendf_in;
|
||||
if (blendf >= 1.0)
|
||||
{
|
||||
triggerComplete();
|
||||
}
|
||||
blendf = llclamp(blendf, 0.0f, 1.0f);
|
||||
|
||||
if (mTarget)
|
||||
{
|
||||
mTarget->replaceSettings(mInitial->getSettings());
|
||||
mTarget->blend(mFinal, blendf);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "No target for settings blender." << LL_ENDL;
|
||||
}
|
||||
|
||||
return blendf;
|
||||
}
|
||||
|
||||
void LLSettingsBlender::triggerComplete()
|
||||
{
|
||||
if (mTarget)
|
||||
mTarget->replaceSettings(mFinal->getSettings());
|
||||
LLSettingsBlender::ptr_t hold = shared_from_this(); // prevents this from deleting too soon
|
||||
mTarget->update();
|
||||
mOnFinished(shared_from_this());
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
const LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::MIN_BLEND_DELTA(FLT_EPSILON);
|
||||
|
||||
LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const
|
||||
{
|
||||
return LLSettingsBase::BlendFactor(fmod((F64)spanpos, (F64)spanlen) / (F64)spanlen);
|
||||
}
|
||||
|
||||
bool LLSettingsBlenderTimeDelta::applyTimeDelta(const LLSettingsBase::Seconds& timedelta)
|
||||
{
|
||||
mTimeSpent += timedelta;
|
||||
|
||||
if (mTimeSpent > mBlendSpan)
|
||||
{
|
||||
triggerComplete();
|
||||
return false;
|
||||
}
|
||||
|
||||
LLSettingsBase::BlendFactor blendf = calculateBlend(mTimeSpent, mBlendSpan);
|
||||
|
||||
if (fabs(mLastBlendF - blendf) < mBlendFMinDelta)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
mLastBlendF = blendf;
|
||||
update(blendf);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,518 @@
|
|||
/**
|
||||
* @file llsettingsbase.h
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, 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_SETTINGS_BASE_H
|
||||
#define LL_SETTINGS_BASE_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
#include "llsd.h"
|
||||
#include "llsdutil.h"
|
||||
#include "v2math.h"
|
||||
#include "v3math.h"
|
||||
#include "v4math.h"
|
||||
#include "llquaternion.h"
|
||||
#include "v4color.h"
|
||||
#include "v3color.h"
|
||||
#include "llunits.h"
|
||||
|
||||
#include "llinventorysettings.h"
|
||||
|
||||
#define PTR_NAMESPACE std
|
||||
#define SETTINGS_OVERRIDE override
|
||||
|
||||
class LLSettingsBase :
|
||||
public PTR_NAMESPACE::enable_shared_from_this<LLSettingsBase>,
|
||||
private boost::noncopyable
|
||||
{
|
||||
friend class LLEnvironment;
|
||||
friend class LLSettingsDay;
|
||||
|
||||
friend std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings);
|
||||
|
||||
protected:
|
||||
LOG_CLASS(LLSettingsBase);
|
||||
public:
|
||||
typedef F64Seconds Seconds;
|
||||
typedef F64 BlendFactor;
|
||||
typedef F32 TrackPosition; // 32-bit as these are stored in LLSD as such
|
||||
static const TrackPosition INVALID_TRACKPOS;
|
||||
static const std::string DEFAULT_SETTINGS_NAME;
|
||||
|
||||
static const std::string SETTING_ID;
|
||||
static const std::string SETTING_NAME;
|
||||
static const std::string SETTING_HASH;
|
||||
static const std::string SETTING_TYPE;
|
||||
static const std::string SETTING_ASSETID;
|
||||
static const std::string SETTING_FLAGS;
|
||||
|
||||
static const U32 FLAG_NOCOPY;
|
||||
static const U32 FLAG_NOMOD;
|
||||
static const U32 FLAG_NOTRANS;
|
||||
static const U32 FLAG_NOSAVE;
|
||||
|
||||
class DefaultParam
|
||||
{
|
||||
public:
|
||||
DefaultParam(S32 key, const LLSD& value) : mShaderKey(key), mDefaultValue(value) {}
|
||||
DefaultParam() : mShaderKey(-1) {}
|
||||
S32 getShaderKey() const { return mShaderKey; }
|
||||
const LLSD getDefaultValue() const { return mDefaultValue; }
|
||||
|
||||
private:
|
||||
S32 mShaderKey;
|
||||
LLSD mDefaultValue;
|
||||
};
|
||||
// Contains settings' names (map key), related shader id-key and default
|
||||
// value for revert in case we need to reset shader (no need to search each time)
|
||||
typedef std::map<std::string, DefaultParam> parammapping_t;
|
||||
|
||||
typedef PTR_NAMESPACE::shared_ptr<LLSettingsBase> ptr_t;
|
||||
|
||||
virtual ~LLSettingsBase() { };
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
virtual std::string getSettingsType() const = 0;
|
||||
|
||||
virtual LLSettingsType::type_e getSettingsTypeValue() const = 0;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Settings status
|
||||
inline bool hasSetting(const std::string ¶m) const { return mSettings.has(param); }
|
||||
virtual bool isDirty() const { return mDirty; }
|
||||
virtual bool isVeryDirty() const { return mReplaced; }
|
||||
inline void setDirtyFlag(bool dirty) { mDirty = dirty; clearAssetId(); }
|
||||
|
||||
size_t getHash() const; // Hash will not include Name, ID or a previously stored Hash
|
||||
|
||||
inline LLUUID getId() const
|
||||
{
|
||||
return getValue(SETTING_ID).asUUID();
|
||||
}
|
||||
|
||||
inline std::string getName() const
|
||||
{
|
||||
return getValue(SETTING_NAME).asString();
|
||||
}
|
||||
|
||||
inline void setName(std::string val)
|
||||
{
|
||||
setValue(SETTING_NAME, val);
|
||||
}
|
||||
|
||||
inline LLUUID getAssetId() const
|
||||
{
|
||||
if (mSettings.has(SETTING_ASSETID))
|
||||
return mSettings[SETTING_ASSETID].asUUID();
|
||||
return LLUUID();
|
||||
}
|
||||
|
||||
inline U32 getFlags() const
|
||||
{
|
||||
if (mSettings.has(SETTING_FLAGS))
|
||||
return static_cast<U32>(mSettings[SETTING_FLAGS].asInteger());
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void setFlags(U32 value)
|
||||
{
|
||||
setLLSD(SETTING_FLAGS, LLSD::Integer(value));
|
||||
}
|
||||
|
||||
inline bool getFlag(U32 flag) const
|
||||
{
|
||||
if (mSettings.has(SETTING_FLAGS))
|
||||
return ((U32)mSettings[SETTING_FLAGS].asInteger() & flag) == flag;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void setFlag(U32 flag)
|
||||
{
|
||||
U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0);
|
||||
|
||||
flags |= flag;
|
||||
|
||||
if (flags)
|
||||
mSettings[SETTING_FLAGS] = LLSD::Integer(flags);
|
||||
else
|
||||
mSettings.erase(SETTING_FLAGS);
|
||||
}
|
||||
|
||||
inline void clearFlag(U32 flag)
|
||||
{
|
||||
U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0);
|
||||
|
||||
flags &= ~flag;
|
||||
|
||||
if (flags)
|
||||
mSettings[SETTING_FLAGS] = LLSD::Integer(flags);
|
||||
else
|
||||
mSettings.erase(SETTING_FLAGS);
|
||||
}
|
||||
|
||||
virtual void replaceSettings(LLSD settings)
|
||||
{
|
||||
mBlendedFactor = 0.0;
|
||||
setDirtyFlag(true);
|
||||
mReplaced = true;
|
||||
mSettings = settings;
|
||||
}
|
||||
|
||||
virtual LLSD getSettings() const;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
inline void setLLSD(const std::string &name, const LLSD &value)
|
||||
{
|
||||
mSettings[name] = value;
|
||||
mDirty = true;
|
||||
if (name != SETTING_ASSETID)
|
||||
clearAssetId();
|
||||
}
|
||||
|
||||
inline void setValue(const std::string &name, const LLSD &value)
|
||||
{
|
||||
setLLSD(name, value);
|
||||
}
|
||||
|
||||
inline LLSD getValue(const std::string &name, const LLSD &deflt = LLSD()) const
|
||||
{
|
||||
if (!mSettings.has(name))
|
||||
return deflt;
|
||||
return mSettings[name];
|
||||
}
|
||||
|
||||
inline void setValue(const std::string &name, F32 v)
|
||||
{
|
||||
setLLSD(name, LLSD::Real(v));
|
||||
}
|
||||
|
||||
inline void setValue(const std::string &name, const LLVector2 &value)
|
||||
{
|
||||
setValue(name, value.getValue());
|
||||
}
|
||||
|
||||
inline void setValue(const std::string &name, const LLVector3 &value)
|
||||
{
|
||||
setValue(name, value.getValue());
|
||||
}
|
||||
|
||||
inline void setValue(const std::string &name, const LLVector4 &value)
|
||||
{
|
||||
setValue(name, value.getValue());
|
||||
}
|
||||
|
||||
inline void setValue(const std::string &name, const LLQuaternion &value)
|
||||
{
|
||||
setValue(name, value.getValue());
|
||||
}
|
||||
|
||||
inline void setValue(const std::string &name, const LLColor3 &value)
|
||||
{
|
||||
setValue(name, value.getValue());
|
||||
}
|
||||
|
||||
inline void setValue(const std::string &name, const LLColor4 &value)
|
||||
{
|
||||
setValue(name, value.getValue());
|
||||
}
|
||||
|
||||
inline BlendFactor getBlendFactor() const
|
||||
{
|
||||
return mBlendedFactor;
|
||||
}
|
||||
|
||||
// Note this method is marked const but may modify the settings object.
|
||||
// (note the internal const cast). This is so that it may be called without
|
||||
// special consideration from getters.
|
||||
inline void update() const
|
||||
{
|
||||
if ((!mDirty) && (!mReplaced))
|
||||
return;
|
||||
(const_cast<LLSettingsBase *>(this))->updateSettings();
|
||||
}
|
||||
|
||||
virtual void blend(const ptr_t &end, BlendFactor blendf) = 0;
|
||||
|
||||
virtual bool validate();
|
||||
|
||||
virtual ptr_t buildDerivedClone() const = 0;
|
||||
|
||||
class Validator
|
||||
{
|
||||
public:
|
||||
static const U32 VALIDATION_PARTIAL;
|
||||
|
||||
typedef boost::function<bool(LLSD &)> verify_pr;
|
||||
|
||||
Validator(std::string name, bool required, LLSD::Type type, verify_pr verify = verify_pr(), LLSD defval = LLSD()) :
|
||||
mName(name),
|
||||
mRequired(required),
|
||||
mType(type),
|
||||
mVerify(verify),
|
||||
mDefault(defval)
|
||||
{ }
|
||||
|
||||
std::string getName() const { return mName; }
|
||||
bool isRequired() const { return mRequired; }
|
||||
LLSD::Type getType() const { return mType; }
|
||||
|
||||
bool verify(LLSD &data, U32 flags);
|
||||
|
||||
// Some basic verifications
|
||||
static bool verifyColor(LLSD &value);
|
||||
static bool verifyVector(LLSD &value, S32 length);
|
||||
static bool verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals);
|
||||
static bool verifyVectorNormalized(LLSD &value, S32 length);
|
||||
static bool verifyQuaternion(LLSD &value);
|
||||
static bool verifyQuaternionNormal(LLSD &value);
|
||||
static bool verifyFloatRange(LLSD &value, LLSD range);
|
||||
static bool verifyIntegerRange(LLSD &value, LLSD range);
|
||||
static bool verifyStringLength(LLSD &value, S32 length);
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
bool mRequired;
|
||||
LLSD::Type mType;
|
||||
verify_pr mVerify;
|
||||
LLSD mDefault;
|
||||
};
|
||||
typedef std::vector<Validator> validation_list_t;
|
||||
|
||||
static LLSD settingValidation(LLSD &settings, validation_list_t &validations, bool partial = false);
|
||||
|
||||
inline void setAssetId(LLUUID value)
|
||||
{ // note that this skips setLLSD
|
||||
mSettings[SETTING_ASSETID] = value;
|
||||
}
|
||||
|
||||
inline void clearAssetId()
|
||||
{
|
||||
if (mSettings.has(SETTING_ASSETID))
|
||||
mSettings.erase(SETTING_ASSETID);
|
||||
}
|
||||
|
||||
// Calculate any custom settings that may need to be cached.
|
||||
virtual void updateSettings() { mDirty = false; mReplaced = false; }
|
||||
protected:
|
||||
|
||||
LLSettingsBase();
|
||||
LLSettingsBase(const LLSD setting);
|
||||
|
||||
static LLSD settingValidation(LLSD settings);
|
||||
|
||||
typedef std::set<std::string> stringset_t;
|
||||
|
||||
// combining settings objects. Customize for specific setting types
|
||||
virtual void lerpSettings(const LLSettingsBase &other, BlendFactor mix);
|
||||
|
||||
// combining settings maps where it can based on mix rate
|
||||
// @settings initial value (mix==0)
|
||||
// @other target value (mix==1)
|
||||
// @defaults list of default values for legacy fields and (re)setting shaders
|
||||
// @mix from 0 to 1, ratio or rate of transition from initial 'settings' to 'other'
|
||||
// return interpolated and combined LLSD map
|
||||
LLSD interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, BlendFactor mix) const;
|
||||
LLSD interpolateSDValue(const std::string& name, const LLSD &value, const LLSD &other, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const;
|
||||
|
||||
/// when lerping between settings, some may require special handling.
|
||||
/// Get a list of these key to be skipped by the default settings lerp.
|
||||
/// (handling should be performed in the override of lerpSettings.
|
||||
virtual stringset_t getSkipInterpolateKeys() const;
|
||||
|
||||
// A list of settings that represent quaternions and should be slerped
|
||||
// rather than lerped.
|
||||
virtual stringset_t getSlerpKeys() const { return stringset_t(); }
|
||||
|
||||
virtual validation_list_t getValidationList() const = 0;
|
||||
|
||||
// Apply any settings that need special handling.
|
||||
virtual void applySpecial(void *, bool force = false) { };
|
||||
|
||||
virtual parammapping_t getParameterMap() const { return parammapping_t(); }
|
||||
|
||||
LLSD mSettings;
|
||||
bool mIsValid;
|
||||
|
||||
LLSD cloneSettings() const;
|
||||
|
||||
inline void setBlendFactor(BlendFactor blendfactor)
|
||||
{
|
||||
mBlendedFactor = blendfactor;
|
||||
}
|
||||
|
||||
void replaceWith(LLSettingsBase::ptr_t other)
|
||||
{
|
||||
replaceSettings(other->cloneSettings());
|
||||
setBlendFactor(other->getBlendFactor());
|
||||
}
|
||||
|
||||
private:
|
||||
bool mDirty;
|
||||
bool mReplaced; // super dirty!
|
||||
|
||||
LLSD combineSDMaps(const LLSD &first, const LLSD &other) const;
|
||||
|
||||
BlendFactor mBlendedFactor;
|
||||
};
|
||||
|
||||
|
||||
class LLSettingsBlender : public PTR_NAMESPACE::enable_shared_from_this<LLSettingsBlender>
|
||||
{
|
||||
LOG_CLASS(LLSettingsBlender);
|
||||
public:
|
||||
typedef PTR_NAMESPACE::shared_ptr<LLSettingsBlender> ptr_t;
|
||||
typedef boost::signals2::signal<void(const ptr_t )> finish_signal_t;
|
||||
typedef boost::signals2::connection connection_t;
|
||||
|
||||
LLSettingsBlender(const LLSettingsBase::ptr_t &target,
|
||||
const LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting) :
|
||||
mOnFinished(),
|
||||
mTarget(target),
|
||||
mInitial(initsetting),
|
||||
mFinal(endsetting)
|
||||
{
|
||||
if (mInitial && mTarget)
|
||||
mTarget->replaceSettings(mInitial->getSettings());
|
||||
|
||||
if (!mFinal)
|
||||
mFinal = mInitial;
|
||||
}
|
||||
|
||||
virtual ~LLSettingsBlender() {}
|
||||
|
||||
virtual void reset( LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::TrackPosition&)
|
||||
{
|
||||
// note: the 'span' reset parameter is unused by the base class.
|
||||
if (!mInitial)
|
||||
LL_WARNS("BLENDER") << "Reseting blender with empty initial setting. Expect badness in the future." << LL_ENDL;
|
||||
|
||||
mInitial = initsetting;
|
||||
mFinal = endsetting;
|
||||
|
||||
if (!mFinal)
|
||||
mFinal = mInitial;
|
||||
|
||||
if (mTarget)
|
||||
mTarget->replaceSettings(mInitial->getSettings());
|
||||
}
|
||||
|
||||
LLSettingsBase::ptr_t getTarget() const
|
||||
{
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
LLSettingsBase::ptr_t getInitial() const
|
||||
{
|
||||
return mInitial;
|
||||
}
|
||||
|
||||
LLSettingsBase::ptr_t getFinal() const
|
||||
{
|
||||
return mFinal;
|
||||
}
|
||||
|
||||
connection_t setOnFinished(const finish_signal_t::slot_type &onfinished)
|
||||
{
|
||||
return mOnFinished.connect(onfinished);
|
||||
}
|
||||
|
||||
virtual void update(const LLSettingsBase::BlendFactor& blendf);
|
||||
virtual bool applyTimeDelta(const LLSettingsBase::Seconds& timedelta)
|
||||
{
|
||||
llassert(false);
|
||||
// your derived class needs to implement an override of this func
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual F64 setBlendFactor(const LLSettingsBase::BlendFactor& position);
|
||||
|
||||
virtual void switchTrack(S32 trackno, const LLSettingsBase::TrackPosition& position) { /*NoOp*/ }
|
||||
|
||||
protected:
|
||||
void triggerComplete();
|
||||
|
||||
finish_signal_t mOnFinished;
|
||||
|
||||
LLSettingsBase::ptr_t mTarget;
|
||||
LLSettingsBase::ptr_t mInitial;
|
||||
LLSettingsBase::ptr_t mFinal;
|
||||
};
|
||||
|
||||
class LLSettingsBlenderTimeDelta : public LLSettingsBlender
|
||||
{
|
||||
LOG_CLASS(LLSettingsBlenderTimeDelta);
|
||||
public:
|
||||
static const LLSettingsBase::BlendFactor MIN_BLEND_DELTA;
|
||||
|
||||
LLSettingsBlenderTimeDelta(const LLSettingsBase::ptr_t &target,
|
||||
const LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::Seconds& blend_span) :
|
||||
LLSettingsBlender(target, initsetting, endsetting),
|
||||
mBlendSpan(blend_span),
|
||||
mLastUpdate(0.0f),
|
||||
mTimeSpent(0.0f),
|
||||
mBlendFMinDelta(MIN_BLEND_DELTA),
|
||||
mLastBlendF(-1.0f)
|
||||
{
|
||||
mTimeStart = LLSettingsBase::Seconds(LLDate::now().secondsSinceEpoch());
|
||||
mLastUpdate = mTimeStart;
|
||||
}
|
||||
|
||||
virtual ~LLSettingsBlenderTimeDelta()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void reset(LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::TrackPosition& blend_span) SETTINGS_OVERRIDE
|
||||
{
|
||||
LLSettingsBlender::reset(initsetting, endsetting, blend_span);
|
||||
|
||||
mBlendSpan = blend_span;
|
||||
mTimeStart = LLSettingsBase::Seconds(LLDate::now().secondsSinceEpoch());
|
||||
mLastUpdate = mTimeStart;
|
||||
mTimeSpent = LLSettingsBase::Seconds(0.0f);
|
||||
mLastBlendF = LLSettingsBase::BlendFactor(-1.0f);
|
||||
}
|
||||
|
||||
virtual bool applyTimeDelta(const LLSettingsBase::Seconds& timedelta) SETTINGS_OVERRIDE;
|
||||
|
||||
inline void setTimeSpent(LLSettingsBase::Seconds time) { mTimeSpent = time; }
|
||||
protected:
|
||||
LLSettingsBase::BlendFactor calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const;
|
||||
|
||||
LLSettingsBase::TrackPosition mBlendSpan;
|
||||
LLSettingsBase::Seconds mLastUpdate;
|
||||
LLSettingsBase::Seconds mTimeSpent;
|
||||
LLSettingsBase::Seconds mTimeStart;
|
||||
LLSettingsBase::BlendFactor mBlendFMinDelta;
|
||||
LLSettingsBase::BlendFactor mLastBlendF;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,896 @@
|
|||
/**
|
||||
* @file llsettingsdaycycle.cpp
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llsettingsdaycycle.h"
|
||||
#include "llerror.h"
|
||||
#include <algorithm>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include "lltrace.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "v3colorutil.h"
|
||||
|
||||
#include "llsettingssky.h"
|
||||
#include "llsettingswater.h"
|
||||
|
||||
#include "llframetimer.h"
|
||||
|
||||
//=========================================================================
|
||||
namespace
|
||||
{
|
||||
LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment");
|
||||
LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment");
|
||||
|
||||
template<typename T>
|
||||
inline T get_wrapping_distance(T begin, T end)
|
||||
{
|
||||
if (begin < end)
|
||||
{
|
||||
return end - begin;
|
||||
}
|
||||
else if (begin > end)
|
||||
{
|
||||
return T(1.0) - (begin - end);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LLSettingsDay::CycleTrack_t::iterator get_wrapping_atafter(LLSettingsDay::CycleTrack_t &collection, const LLSettingsBase::TrackPosition& key)
|
||||
{
|
||||
if (collection.empty())
|
||||
return collection.end();
|
||||
|
||||
LLSettingsDay::CycleTrack_t::iterator it = collection.upper_bound(key);
|
||||
|
||||
if (it == collection.end())
|
||||
{ // wrap around
|
||||
it = collection.begin();
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
LLSettingsDay::CycleTrack_t::iterator get_wrapping_atbefore(LLSettingsDay::CycleTrack_t &collection, const LLSettingsBase::TrackPosition& key)
|
||||
{
|
||||
if (collection.empty())
|
||||
return collection.end();
|
||||
|
||||
LLSettingsDay::CycleTrack_t::iterator it = collection.lower_bound(key);
|
||||
|
||||
if (it == collection.end())
|
||||
{ // all keyframes are lower, take the last one.
|
||||
--it; // we know the range is not empty
|
||||
}
|
||||
else if ((*it).first > key)
|
||||
{ // the keyframe we are interested in is smaller than the found.
|
||||
if (it == collection.begin())
|
||||
it = collection.end();
|
||||
--it;
|
||||
}
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
const std::string LLSettingsDay::SETTING_KEYID("key_id");
|
||||
const std::string LLSettingsDay::SETTING_KEYNAME("key_name");
|
||||
const std::string LLSettingsDay::SETTING_KEYKFRAME("key_keyframe");
|
||||
const std::string LLSettingsDay::SETTING_KEYHASH("key_hash");
|
||||
const std::string LLSettingsDay::SETTING_TRACKS("tracks");
|
||||
const std::string LLSettingsDay::SETTING_FRAMES("frames");
|
||||
|
||||
const LLSettingsDay::Seconds LLSettingsDay::MINIMUM_DAYLENGTH(14400); // 4 hours
|
||||
const LLSettingsDay::Seconds LLSettingsDay::DEFAULT_DAYLENGTH(14400); // 4 hours
|
||||
const LLSettingsDay::Seconds LLSettingsDay::MAXIMUM_DAYLENGTH(604800); // 7 days
|
||||
|
||||
const LLSettingsDay::Seconds LLSettingsDay::MINIMUM_DAYOFFSET(0);
|
||||
const LLSettingsDay::Seconds LLSettingsDay::DEFAULT_DAYOFFSET(57600); // +16 hours == -8 hours (SLT time offset)
|
||||
const LLSettingsDay::Seconds LLSettingsDay::MAXIMUM_DAYOFFSET(86400); // 24 hours
|
||||
|
||||
const S32 LLSettingsDay::TRACK_WATER(0); // water track is 0
|
||||
const S32 LLSettingsDay::TRACK_GROUND_LEVEL(1);
|
||||
const S32 LLSettingsDay::TRACK_MAX(5); // 5 tracks, 4 skys, 1 water
|
||||
const S32 LLSettingsDay::FRAME_MAX(56);
|
||||
|
||||
const F32 LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR(0.02501f);
|
||||
|
||||
const LLUUID LLSettingsDay::DEFAULT_ASSET_ID("5646d39e-d3d7-6aff-ed71-30fc87d64a91");
|
||||
|
||||
// Minimum value to prevent multislider in edit floaters from eating up frames that 'encroach' on one another's space
|
||||
static const F32 DEFAULT_MULTISLIDER_INCREMENT(0.005f);
|
||||
//=========================================================================
|
||||
LLSettingsDay::LLSettingsDay(const LLSD &data) :
|
||||
LLSettingsBase(data),
|
||||
mInitialized(false)
|
||||
{
|
||||
mDayTracks.resize(TRACK_MAX);
|
||||
}
|
||||
|
||||
LLSettingsDay::LLSettingsDay() :
|
||||
LLSettingsBase(),
|
||||
mInitialized(false)
|
||||
{
|
||||
mDayTracks.resize(TRACK_MAX);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
LLSD LLSettingsDay::getSettings() const
|
||||
{
|
||||
LLSD settings(LLSD::emptyMap());
|
||||
|
||||
if (mSettings.has(SETTING_NAME))
|
||||
settings[SETTING_NAME] = mSettings[SETTING_NAME];
|
||||
|
||||
if (mSettings.has(SETTING_ID))
|
||||
settings[SETTING_ID] = mSettings[SETTING_ID];
|
||||
|
||||
if (mSettings.has(SETTING_ASSETID))
|
||||
settings[SETTING_ASSETID] = mSettings[SETTING_ASSETID];
|
||||
|
||||
settings[SETTING_TYPE] = getSettingsType();
|
||||
|
||||
std::map<std::string, LLSettingsBase::ptr_t> in_use;
|
||||
|
||||
LLSD tracks(LLSD::emptyArray());
|
||||
|
||||
for (CycleList_t::const_iterator itTrack = mDayTracks.begin(); itTrack != mDayTracks.end(); ++itTrack)
|
||||
{
|
||||
LLSD trackout(LLSD::emptyArray());
|
||||
|
||||
for (CycleTrack_t::const_iterator itFrame = (*itTrack).begin(); itFrame != (*itTrack).end(); ++itFrame)
|
||||
{
|
||||
F32 frame = (*itFrame).first;
|
||||
LLSettingsBase::ptr_t data = (*itFrame).second;
|
||||
size_t datahash = data->getHash();
|
||||
|
||||
std::stringstream keyname;
|
||||
keyname << datahash;
|
||||
|
||||
trackout.append(LLSD(LLSDMap(SETTING_KEYKFRAME, LLSD::Real(frame))(SETTING_KEYNAME, keyname.str())));
|
||||
in_use[keyname.str()] = data;
|
||||
}
|
||||
tracks.append(trackout);
|
||||
}
|
||||
settings[SETTING_TRACKS] = tracks;
|
||||
|
||||
LLSD frames(LLSD::emptyMap());
|
||||
for (std::map<std::string, LLSettingsBase::ptr_t>::iterator itFrame = in_use.begin(); itFrame != in_use.end(); ++itFrame)
|
||||
{
|
||||
LLSD framesettings = llsd_clone((*itFrame).second->getSettings(),
|
||||
LLSDMap("*", true)(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false));
|
||||
|
||||
frames[(*itFrame).first] = framesettings;
|
||||
}
|
||||
settings[SETTING_FRAMES] = frames;
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
bool LLSettingsDay::initialize(bool validate_frames)
|
||||
{
|
||||
LLSD tracks = mSettings[SETTING_TRACKS];
|
||||
LLSD frames = mSettings[SETTING_FRAMES];
|
||||
|
||||
// save for later...
|
||||
LLUUID assetid;
|
||||
if (mSettings.has(SETTING_ASSETID))
|
||||
{
|
||||
assetid = mSettings[SETTING_ASSETID].asUUID();
|
||||
}
|
||||
|
||||
std::map<std::string, LLSettingsBase::ptr_t> used;
|
||||
|
||||
for (LLSD::map_const_iterator itFrame = frames.beginMap(); itFrame != frames.endMap(); ++itFrame)
|
||||
{
|
||||
std::string name = (*itFrame).first;
|
||||
LLSD data = (*itFrame).second;
|
||||
LLSettingsBase::ptr_t keyframe;
|
||||
|
||||
if (data[SETTING_TYPE].asString() == "sky")
|
||||
{
|
||||
keyframe = buildSky(data);
|
||||
}
|
||||
else if (data[SETTING_TYPE].asString() == "water")
|
||||
{
|
||||
keyframe = buildWater(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Unknown child setting type '" << data[SETTING_TYPE].asString() << "' named '" << name << "'" << LL_ENDL;
|
||||
}
|
||||
if (!keyframe)
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Invalid frame data" << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
|
||||
used[name] = keyframe;
|
||||
}
|
||||
|
||||
bool haswater(false);
|
||||
bool hassky(false);
|
||||
|
||||
for (S32 i = 0; (i < tracks.size()) && (i < TRACK_MAX); ++i)
|
||||
{
|
||||
mDayTracks[i].clear();
|
||||
LLSD curtrack = tracks[i];
|
||||
for (LLSD::array_const_iterator it = curtrack.beginArray(); it != curtrack.endArray(); ++it)
|
||||
{
|
||||
LLSettingsBase::TrackPosition keyframe = LLSettingsBase::TrackPosition((*it)[SETTING_KEYKFRAME].asReal());
|
||||
keyframe = llclamp(keyframe, 0.0f, 1.0f);
|
||||
LLSettingsBase::ptr_t setting;
|
||||
|
||||
|
||||
if ((*it).has(SETTING_KEYNAME))
|
||||
{
|
||||
std::string key_name = (*it)[SETTING_KEYNAME];
|
||||
if (i == TRACK_WATER)
|
||||
{
|
||||
setting = used[key_name];
|
||||
if (setting && setting->getSettingsType() != "water")
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Water track referencing " << setting->getSettingsType() << " frame at " << keyframe << "." << LL_ENDL;
|
||||
setting.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setting = used[key_name];
|
||||
if (setting && setting->getSettingsType() != "sky")
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Sky track #" << i << " referencing " << setting->getSettingsType() << " frame at " << keyframe << "." << LL_ENDL;
|
||||
setting.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setting)
|
||||
{
|
||||
if (i == TRACK_WATER)
|
||||
haswater |= true;
|
||||
else
|
||||
hassky |= true;
|
||||
|
||||
if (validate_frames && mDayTracks[i].size() > 0)
|
||||
{
|
||||
// check if we hit close to anything in the list
|
||||
LLSettingsDay::CycleTrack_t::value_type frame = getSettingsNearKeyframe(keyframe, i, DEFAULT_FRAME_SLOP_FACTOR);
|
||||
if (frame.second)
|
||||
{
|
||||
// figure out direction of search
|
||||
LLSettingsBase::TrackPosition found = frame.first;
|
||||
LLSettingsBase::TrackPosition new_frame = keyframe;
|
||||
F32 total_frame_shift = 0;
|
||||
// We consider frame DEFAULT_FRAME_SLOP_FACTOR away as still encroaching, so add minimum increment
|
||||
F32 move_factor = DEFAULT_FRAME_SLOP_FACTOR + DEFAULT_MULTISLIDER_INCREMENT;
|
||||
bool move_forward = true;
|
||||
if ((new_frame < found && (found - new_frame) <= DEFAULT_FRAME_SLOP_FACTOR)
|
||||
|| (new_frame > found && (new_frame - found) > DEFAULT_FRAME_SLOP_FACTOR))
|
||||
{
|
||||
move_forward = false;
|
||||
}
|
||||
|
||||
if (move_forward)
|
||||
{
|
||||
CycleTrack_t::iterator iter = mDayTracks[i].find(found);
|
||||
new_frame = found; // for total_frame_shift
|
||||
while (total_frame_shift < 1)
|
||||
{
|
||||
// calculate shifted position from previous found point
|
||||
total_frame_shift += move_factor + (found >= new_frame ? found : found + 1) - new_frame;
|
||||
new_frame = found + move_factor;
|
||||
if (new_frame > 1) new_frame--;
|
||||
|
||||
// we know that current point is too close, go for next one
|
||||
iter++;
|
||||
if (iter == mDayTracks[i].end())
|
||||
{
|
||||
iter = mDayTracks[i].begin();
|
||||
}
|
||||
|
||||
if (((iter->first >= (new_frame - DEFAULT_MULTISLIDER_INCREMENT)) && ((new_frame + DEFAULT_FRAME_SLOP_FACTOR) >= iter->first))
|
||||
|| ((iter->first < new_frame) && ((new_frame + DEFAULT_FRAME_SLOP_FACTOR) >= (iter->first + 1))))
|
||||
{
|
||||
// we are encroaching at new point as well
|
||||
found = iter->first;
|
||||
}
|
||||
else // (new_frame + DEFAULT_FRAME_SLOP_FACTOR < iter->first)
|
||||
{
|
||||
//we found clear spot
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CycleTrack_t::reverse_iterator iter = mDayTracks[i].rbegin();
|
||||
while (iter->first != found)
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
new_frame = found; // for total_frame_shift
|
||||
while (total_frame_shift < 1)
|
||||
{
|
||||
// calculate shifted position from current found point
|
||||
total_frame_shift += move_factor + new_frame - (found <= new_frame ? found : found - 1);
|
||||
new_frame = found - move_factor;
|
||||
if (new_frame < 0) new_frame++;
|
||||
|
||||
// we know that current point is too close, go for next one
|
||||
iter++;
|
||||
if (iter == mDayTracks[i].rend())
|
||||
{
|
||||
iter = mDayTracks[i].rbegin();
|
||||
}
|
||||
|
||||
if ((iter->first <= (new_frame + DEFAULT_MULTISLIDER_INCREMENT) && (new_frame - DEFAULT_FRAME_SLOP_FACTOR) <= iter->first)
|
||||
|| ((iter->first > new_frame) && ((new_frame - DEFAULT_FRAME_SLOP_FACTOR) <= (iter->first - 1))))
|
||||
{
|
||||
// we are encroaching at new point as well
|
||||
found = iter->first;
|
||||
}
|
||||
else // (new_frame - DEFAULT_FRAME_SLOP_FACTOR > iter->first)
|
||||
{
|
||||
//we found clear spot
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (total_frame_shift >= 1)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Could not fix frame position, adding as is to position: " << keyframe << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mark as new position
|
||||
keyframe = new_frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
mDayTracks[i][keyframe] = setting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!haswater || !hassky)
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Must have at least one water and one sky frame!" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
// these are no longer needed and just take up space now.
|
||||
mSettings.erase(SETTING_TRACKS);
|
||||
mSettings.erase(SETTING_FRAMES);
|
||||
|
||||
if (!assetid.isNull())
|
||||
{
|
||||
mSettings[SETTING_ASSETID] = assetid;
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================
|
||||
LLSD LLSettingsDay::defaults()
|
||||
{
|
||||
static LLSD dfltsetting;
|
||||
|
||||
if (dfltsetting.size() == 0)
|
||||
{
|
||||
dfltsetting[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
|
||||
dfltsetting[SETTING_TYPE] = "daycycle";
|
||||
|
||||
LLSD frames(LLSD::emptyMap());
|
||||
LLSD waterTrack;
|
||||
LLSD skyTrack;
|
||||
|
||||
|
||||
const U32 FRAME_COUNT = 8;
|
||||
const F32 FRAME_STEP = 1.0f / F32(FRAME_COUNT);
|
||||
F32 time = 0.0f;
|
||||
for (U32 i = 0; i < FRAME_COUNT; i++)
|
||||
{
|
||||
std::string name(DEFAULT_SETTINGS_NAME);
|
||||
name += ('a' + i);
|
||||
|
||||
std::string water_frame_name("water:");
|
||||
std::string sky_frame_name("sky:");
|
||||
|
||||
water_frame_name += name;
|
||||
sky_frame_name += name;
|
||||
|
||||
waterTrack[SETTING_KEYKFRAME] = time;
|
||||
waterTrack[SETTING_KEYNAME] = water_frame_name;
|
||||
|
||||
skyTrack[SETTING_KEYKFRAME] = time;
|
||||
skyTrack[SETTING_KEYNAME] = sky_frame_name;
|
||||
|
||||
frames[water_frame_name] = LLSettingsWater::defaults(time);
|
||||
frames[sky_frame_name] = LLSettingsSky::defaults(time);
|
||||
|
||||
time += FRAME_STEP;
|
||||
}
|
||||
|
||||
LLSD tracks;
|
||||
tracks.append(LLSDArray(waterTrack));
|
||||
tracks.append(LLSDArray(skyTrack));
|
||||
|
||||
dfltsetting[SETTING_TRACKS] = tracks;
|
||||
dfltsetting[SETTING_FRAMES] = frames;
|
||||
}
|
||||
|
||||
return dfltsetting;
|
||||
}
|
||||
|
||||
void LLSettingsDay::blend(const LLSettingsBase::ptr_t &other, F64 mix)
|
||||
{
|
||||
LL_ERRS("DAYCYCLE") << "Day cycles are not blendable!" << LL_ENDL;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool validateDayCycleTrack(LLSD &value)
|
||||
{
|
||||
// Trim extra tracks.
|
||||
while (value.size() > LLSettingsDay::TRACK_MAX)
|
||||
{
|
||||
value.erase(value.size() - 1);
|
||||
}
|
||||
|
||||
S32 framecount(0);
|
||||
|
||||
for (LLSD::array_iterator track = value.beginArray(); track != value.endArray(); ++track)
|
||||
{
|
||||
S32 index = 0;
|
||||
while (index < (*track).size())
|
||||
{
|
||||
LLSD& elem = (*track)[index];
|
||||
|
||||
++framecount;
|
||||
if (index >= LLSettingsDay::FRAME_MAX)
|
||||
{
|
||||
(*track).erase(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!elem.has(LLSettingsDay::SETTING_KEYKFRAME))
|
||||
{
|
||||
(*track).erase(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!elem[LLSettingsDay::SETTING_KEYKFRAME].isReal())
|
||||
{
|
||||
(*track).erase(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!elem.has(LLSettingsDay::SETTING_KEYNAME) &&
|
||||
!elem.has(LLSettingsDay::SETTING_KEYID))
|
||||
{
|
||||
(*track).erase(index);
|
||||
continue;
|
||||
}
|
||||
|
||||
LLSettingsBase::TrackPosition frame = elem[LLSettingsDay::SETTING_KEYKFRAME].asReal();
|
||||
if ((frame < 0.0) || (frame > 1.0))
|
||||
{
|
||||
frame = llclamp(frame, 0.0f, 1.0f);
|
||||
elem[LLSettingsDay::SETTING_KEYKFRAME] = frame;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int waterTracks = value[0].size();
|
||||
int skyTracks = framecount - waterTracks;
|
||||
|
||||
if (waterTracks < 1)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Missing water track" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skyTracks < 1)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Missing sky tracks" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool validateDayCycleFrames(LLSD &value)
|
||||
{
|
||||
bool hasSky(false);
|
||||
bool hasWater(false);
|
||||
|
||||
for (LLSD::map_iterator itf = value.beginMap(); itf != value.endMap(); ++itf)
|
||||
{
|
||||
LLSD frame = (*itf).second;
|
||||
|
||||
std::string ftype = frame[LLSettingsBase::SETTING_TYPE];
|
||||
if (ftype == "sky")
|
||||
{
|
||||
LLSettingsSky::validation_list_t valid_sky = LLSettingsSky::validationList();
|
||||
LLSD res_sky = LLSettingsBase::settingValidation(frame, valid_sky);
|
||||
|
||||
if (res_sky["success"].asInteger() == 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Sky setting named '" << (*itf).first << "' validation failed!: " << res_sky << LL_ENDL;
|
||||
LL_WARNS("SETTINGS") << "Sky: " << frame << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
hasSky |= true;
|
||||
}
|
||||
else if (ftype == "water")
|
||||
{
|
||||
LLSettingsWater::validation_list_t valid_h2o = LLSettingsWater::validationList();
|
||||
LLSD res_h2o = LLSettingsBase::settingValidation(frame, valid_h2o);
|
||||
if (res_h2o["success"].asInteger() == 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Water setting named '" << (*itf).first << "' validation failed!: " << res_h2o << LL_ENDL;
|
||||
LL_WARNS("SETTINGS") << "Water: " << frame << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
hasWater |= true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Unknown settings block of type '" << ftype << "' named '" << (*itf).first << "'" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSky)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "No skies defined." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasWater)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "No waters defined." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LLSettingsDay::validation_list_t LLSettingsDay::getValidationList() const
|
||||
{
|
||||
return LLSettingsDay::validationList();
|
||||
}
|
||||
|
||||
LLSettingsDay::validation_list_t LLSettingsDay::validationList()
|
||||
{
|
||||
static validation_list_t validation;
|
||||
|
||||
if (validation.empty())
|
||||
{
|
||||
validation.push_back(Validator(SETTING_TRACKS, true, LLSD::TypeArray,
|
||||
&validateDayCycleTrack));
|
||||
validation.push_back(Validator(SETTING_FRAMES, true, LLSD::TypeMap,
|
||||
&validateDayCycleFrames));
|
||||
}
|
||||
|
||||
return validation;
|
||||
}
|
||||
|
||||
LLSettingsDay::CycleTrack_t& LLSettingsDay::getCycleTrack(S32 track)
|
||||
{
|
||||
static CycleTrack_t emptyTrack;
|
||||
if (mDayTracks.size() <= track)
|
||||
return emptyTrack;
|
||||
|
||||
return mDayTracks[track];
|
||||
}
|
||||
|
||||
const LLSettingsDay::CycleTrack_t& LLSettingsDay::getCycleTrackConst(S32 track) const
|
||||
{
|
||||
static CycleTrack_t emptyTrack;
|
||||
if (mDayTracks.size() <= track)
|
||||
return emptyTrack;
|
||||
|
||||
return mDayTracks[track];
|
||||
}
|
||||
|
||||
bool LLSettingsDay::clearCycleTrack(S32 track)
|
||||
{
|
||||
if ((track < 0) || (track >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to clear track (#" << track << ") out of range!" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
mDayTracks[track].clear();
|
||||
clearAssetId();
|
||||
setDirtyFlag(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsDay::replaceCycleTrack(S32 track, const CycleTrack_t &source)
|
||||
{
|
||||
if (source.empty())
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to copy an empty track." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
LLSettingsBase::ptr_t first((*source.begin()).second);
|
||||
std::string setting_type = first->getSettingsType();
|
||||
|
||||
if (((setting_type == "water") && (track != 0)) ||
|
||||
((setting_type == "sky") && (track == 0)))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to copy track missmatch" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!clearCycleTrack(track))
|
||||
return false;
|
||||
|
||||
mDayTracks[track] = source;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool LLSettingsDay::isTrackEmpty(S32 track) const
|
||||
{
|
||||
if ((track < 0) || (track >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to test track (#" << track << ") out of range!" << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
return mDayTracks[track].empty();
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void LLSettingsDay::startDayCycle()
|
||||
{
|
||||
if (!mInitialized)
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to start day cycle on uninitialized object." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLSettingsDay::updateSettings()
|
||||
{
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
LLSettingsDay::KeyframeList_t LLSettingsDay::getTrackKeyframes(S32 trackno)
|
||||
{
|
||||
if ((trackno < 0) || (trackno >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL;
|
||||
return KeyframeList_t();
|
||||
}
|
||||
|
||||
KeyframeList_t keyframes;
|
||||
CycleTrack_t &track = mDayTracks[trackno];
|
||||
|
||||
keyframes.reserve(track.size());
|
||||
|
||||
for (CycleTrack_t::iterator it = track.begin(); it != track.end(); ++it)
|
||||
{
|
||||
keyframes.push_back((*it).first);
|
||||
}
|
||||
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
bool LLSettingsDay::moveTrackKeyframe(S32 trackno, const LLSettingsBase::TrackPosition& old_frame, const LLSettingsBase::TrackPosition& new_frame)
|
||||
{
|
||||
if ((trackno < 0) || (trackno >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (llabs(old_frame - new_frame) < F_APPROXIMATELY_ZERO)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CycleTrack_t &track = mDayTracks[trackno];
|
||||
CycleTrack_t::iterator iter = track.find(old_frame);
|
||||
if (iter != track.end())
|
||||
{
|
||||
LLSettingsBase::ptr_t base = iter->second;
|
||||
track.erase(iter);
|
||||
track[llclamp(new_frame, 0.0f, 1.0f)] = base;
|
||||
track[new_frame] = base;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
bool LLSettingsDay::removeTrackKeyframe(S32 trackno, const LLSettingsBase::TrackPosition& frame)
|
||||
{
|
||||
if ((trackno < 0) || (trackno >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
CycleTrack_t &track = mDayTracks[trackno];
|
||||
CycleTrack_t::iterator iter = track.find(frame);
|
||||
if (iter != track.end())
|
||||
{
|
||||
LLSettingsBase::ptr_t base = iter->second;
|
||||
track.erase(iter);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLSettingsDay::setWaterAtKeyframe(const LLSettingsWaterPtr_t &water, const LLSettingsBase::TrackPosition& keyframe)
|
||||
{
|
||||
setSettingsAtKeyframe(water, keyframe, TRACK_WATER);
|
||||
}
|
||||
|
||||
LLSettingsWater::ptr_t LLSettingsDay::getWaterAtKeyframe(const LLSettingsBase::TrackPosition& keyframe) const
|
||||
{
|
||||
LLSettingsBase* p = getSettingsAtKeyframe(keyframe, TRACK_WATER).get();
|
||||
return LLSettingsWater::ptr_t((LLSettingsWater*)p);
|
||||
}
|
||||
|
||||
void LLSettingsDay::setSkyAtKeyframe(const LLSettingsSky::ptr_t &sky, const LLSettingsBase::TrackPosition& keyframe, S32 track)
|
||||
{
|
||||
if ((track < 1) || (track >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
setSettingsAtKeyframe(sky, keyframe, track);
|
||||
}
|
||||
|
||||
LLSettingsSky::ptr_t LLSettingsDay::getSkyAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const
|
||||
{
|
||||
if ((track < 1) || (track >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL;
|
||||
return LLSettingsSky::ptr_t();
|
||||
}
|
||||
|
||||
return PTR_NAMESPACE::dynamic_pointer_cast<LLSettingsSky>(getSettingsAtKeyframe(keyframe, track));
|
||||
}
|
||||
|
||||
void LLSettingsDay::setSettingsAtKeyframe(const LLSettingsBase::ptr_t &settings, const LLSettingsBase::TrackPosition& keyframe, S32 track)
|
||||
{
|
||||
if ((track < 0) || (track >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to set track (#" << track << ") out of range!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string type = settings->getSettingsType();
|
||||
if ((track == TRACK_WATER) && (type != "water"))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to add frame of type '" << type << "' to water track!" << LL_ENDL;
|
||||
llassert(type == "water");
|
||||
return;
|
||||
}
|
||||
else if ((track != TRACK_WATER) && (type != "sky"))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to add frame of type '" << type << "' to sky track!" << LL_ENDL;
|
||||
llassert(type == "sky");
|
||||
return;
|
||||
}
|
||||
|
||||
mDayTracks[track][llclamp(keyframe, 0.0f, 1.0f)] = settings;
|
||||
setDirtyFlag(true);
|
||||
}
|
||||
|
||||
LLSettingsBase::ptr_t LLSettingsDay::getSettingsAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const
|
||||
{
|
||||
if ((track < 0) || (track >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL;
|
||||
return LLSettingsBase::ptr_t();
|
||||
}
|
||||
|
||||
// todo: better way to identify keyframes?
|
||||
CycleTrack_t::const_iterator iter = mDayTracks[track].find(keyframe);
|
||||
if (iter != mDayTracks[track].end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return LLSettingsBase::ptr_t();
|
||||
}
|
||||
|
||||
LLSettingsDay::CycleTrack_t::value_type LLSettingsDay::getSettingsNearKeyframe(const LLSettingsBase::TrackPosition &keyframe, S32 track, F32 fudge) const
|
||||
{
|
||||
if ((track < 0) || (track >= TRACK_MAX))
|
||||
{
|
||||
LL_WARNS("DAYCYCLE") << "Attempt to get track (#" << track << ") out of range!" << LL_ENDL;
|
||||
return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t());
|
||||
}
|
||||
|
||||
if (mDayTracks[track].empty())
|
||||
{
|
||||
LL_INFOS("DAYCYCLE") << "Empty track" << LL_ENDL;
|
||||
return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t());
|
||||
}
|
||||
|
||||
TrackPosition startframe(keyframe - fudge);
|
||||
if (startframe < 0.0f)
|
||||
startframe = 1.0f + startframe;
|
||||
|
||||
LLSettingsDay::CycleTrack_t collection = const_cast<CycleTrack_t &>(mDayTracks[track]);
|
||||
CycleTrack_t::iterator it = get_wrapping_atafter(collection, startframe);
|
||||
|
||||
F32 dist = get_wrapping_distance(startframe, (*it).first);
|
||||
|
||||
CycleTrack_t::iterator next_it = std::next(it);
|
||||
if ((dist <= DEFAULT_MULTISLIDER_INCREMENT) && next_it != collection.end())
|
||||
return (*next_it);
|
||||
else if (dist <= (fudge * 2.0f))
|
||||
return (*it);
|
||||
|
||||
return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t());
|
||||
}
|
||||
|
||||
LLSettingsBase::TrackPosition LLSettingsDay::getUpperBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe)
|
||||
{
|
||||
return get_wrapping_atafter(mDayTracks[track], keyframe)->first;
|
||||
}
|
||||
|
||||
LLSettingsBase::TrackPosition LLSettingsDay::getLowerBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe)
|
||||
{
|
||||
return get_wrapping_atbefore(mDayTracks[track], keyframe)->first;
|
||||
}
|
||||
|
||||
LLSettingsDay::TrackBound_t LLSettingsDay::getBoundingEntries(LLSettingsDay::CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe)
|
||||
{
|
||||
return TrackBound_t(get_wrapping_atbefore(track, keyframe), get_wrapping_atafter(track, keyframe));
|
||||
}
|
||||
|
||||
LLUUID LLSettingsDay::GetDefaultAssetId()
|
||||
{
|
||||
return DEFAULT_ASSET_ID;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/**
|
||||
* @file llsettingsdaycycle.h
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, 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_SETTINGS_DAYCYCLE_H
|
||||
#define LL_SETTINGS_DAYCYCLE_H
|
||||
|
||||
#include "llsettingsbase.h"
|
||||
|
||||
class LLSettingsWater;
|
||||
class LLSettingsSky;
|
||||
|
||||
// These are alias for LLSettingsWater::ptr_t and LLSettingsSky::ptr_t respectively.
|
||||
// Here for definitions only.
|
||||
typedef PTR_NAMESPACE::shared_ptr<LLSettingsWater> LLSettingsWaterPtr_t;
|
||||
typedef PTR_NAMESPACE::shared_ptr<LLSettingsSky> LLSettingsSkyPtr_t;
|
||||
|
||||
class LLSettingsDay : public LLSettingsBase
|
||||
{
|
||||
public:
|
||||
// 32-bit as LLSD only supports that width at present
|
||||
typedef S32Seconds Seconds;
|
||||
|
||||
static const std::string SETTING_KEYID;
|
||||
static const std::string SETTING_KEYNAME;
|
||||
static const std::string SETTING_KEYKFRAME;
|
||||
static const std::string SETTING_KEYHASH;
|
||||
static const std::string SETTING_TRACKS;
|
||||
static const std::string SETTING_FRAMES;
|
||||
|
||||
static const Seconds MINIMUM_DAYLENGTH;
|
||||
static const Seconds DEFAULT_DAYLENGTH;
|
||||
static const Seconds MAXIMUM_DAYLENGTH;
|
||||
|
||||
static const Seconds MINIMUM_DAYOFFSET;
|
||||
static const Seconds DEFAULT_DAYOFFSET;
|
||||
static const Seconds MAXIMUM_DAYOFFSET;
|
||||
|
||||
static const S32 TRACK_WATER;
|
||||
static const S32 TRACK_GROUND_LEVEL;
|
||||
static const S32 TRACK_MAX;
|
||||
static const S32 FRAME_MAX;
|
||||
|
||||
static const F32 DEFAULT_FRAME_SLOP_FACTOR;
|
||||
|
||||
static const LLUUID DEFAULT_ASSET_ID;
|
||||
|
||||
typedef std::map<LLSettingsBase::TrackPosition, LLSettingsBase::ptr_t> CycleTrack_t;
|
||||
typedef std::vector<CycleTrack_t> CycleList_t;
|
||||
typedef PTR_NAMESPACE::shared_ptr<LLSettingsDay> ptr_t;
|
||||
typedef PTR_NAMESPACE::weak_ptr<LLSettingsDay> wptr_t;
|
||||
typedef std::vector<LLSettingsBase::TrackPosition> KeyframeList_t;
|
||||
typedef std::pair<CycleTrack_t::iterator, CycleTrack_t::iterator> TrackBound_t;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
LLSettingsDay(const LLSD &data);
|
||||
virtual ~LLSettingsDay() { };
|
||||
|
||||
bool initialize(bool validate_frames = false);
|
||||
|
||||
virtual ptr_t buildClone() const = 0;
|
||||
virtual ptr_t buildDeepCloneAndUncompress() const = 0;
|
||||
virtual LLSD getSettings() const SETTINGS_OVERRIDE;
|
||||
virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_DAYCYCLE; }
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("daycycle"); }
|
||||
|
||||
// Settings status
|
||||
virtual void blend(const LLSettingsBase::ptr_t &other, F64 mix) SETTINGS_OVERRIDE;
|
||||
|
||||
static LLSD defaults();
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
KeyframeList_t getTrackKeyframes(S32 track);
|
||||
bool moveTrackKeyframe(S32 track, const LLSettingsBase::TrackPosition& old_frame, const LLSettingsBase::TrackPosition& new_frame);
|
||||
bool removeTrackKeyframe(S32 track, const LLSettingsBase::TrackPosition& frame);
|
||||
|
||||
void setWaterAtKeyframe(const LLSettingsWaterPtr_t &water, const LLSettingsBase::TrackPosition& keyframe);
|
||||
LLSettingsWaterPtr_t getWaterAtKeyframe(const LLSettingsBase::TrackPosition& keyframe) const;
|
||||
void setSkyAtKeyframe(const LLSettingsSkyPtr_t &sky, const LLSettingsBase::TrackPosition& keyframe, S32 track);
|
||||
LLSettingsSkyPtr_t getSkyAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const;
|
||||
void setSettingsAtKeyframe(const LLSettingsBase::ptr_t &settings, const LLSettingsBase::TrackPosition& keyframe, S32 track);
|
||||
LLSettingsBase::ptr_t getSettingsAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const;
|
||||
CycleTrack_t::value_type getSettingsNearKeyframe(const LLSettingsBase::TrackPosition &keyframe, S32 track, F32 fudge) const;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void startDayCycle();
|
||||
|
||||
virtual LLSettingsSkyPtr_t getDefaultSky() const = 0;
|
||||
virtual LLSettingsWaterPtr_t getDefaultWater() const = 0;
|
||||
|
||||
virtual LLSettingsSkyPtr_t buildSky(LLSD) const = 0;
|
||||
virtual LLSettingsWaterPtr_t buildWater(LLSD) const = 0;
|
||||
|
||||
void setInitialized(bool value = true) { mInitialized = value; }
|
||||
CycleTrack_t & getCycleTrack(S32 track);
|
||||
const CycleTrack_t & getCycleTrackConst(S32 track) const;
|
||||
bool clearCycleTrack(S32 track);
|
||||
bool replaceCycleTrack(S32 track, const CycleTrack_t &source);
|
||||
bool isTrackEmpty(S32 track) const;
|
||||
|
||||
virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE;
|
||||
static validation_list_t validationList();
|
||||
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
|
||||
|
||||
LLSettingsBase::TrackPosition getUpperBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe);
|
||||
LLSettingsBase::TrackPosition getLowerBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe);
|
||||
|
||||
static LLUUID GetDefaultAssetId();
|
||||
|
||||
protected:
|
||||
LLSettingsDay();
|
||||
|
||||
virtual void updateSettings() SETTINGS_OVERRIDE;
|
||||
|
||||
bool mInitialized;
|
||||
|
||||
private:
|
||||
CycleList_t mDayTracks;
|
||||
|
||||
LLSettingsBase::Seconds mLastUpdateTime;
|
||||
|
||||
static CycleTrack_t::iterator getEntryAtOrBefore(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe);
|
||||
static CycleTrack_t::iterator getEntryAtOrAfter(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe);
|
||||
TrackBound_t getBoundingEntries(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe);
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,374 @@
|
|||
/**
|
||||
* @file llsettingssky.h
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, 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_SETTINGS_SKY_H
|
||||
#define LL_SETTINGS_SKY_H
|
||||
|
||||
#include "llsettingsbase.h"
|
||||
#include "v4coloru.h"
|
||||
|
||||
const F32 EARTH_RADIUS = 6.370e6f;
|
||||
const F32 SUN_RADIUS = 695.508e6f;
|
||||
const F32 SUN_DIST = 149598.260e6f;
|
||||
const F32 MOON_RADIUS = 1.737e6f;
|
||||
const F32 MOON_DIST = 384.400e6f;
|
||||
|
||||
class LLSettingsSky: public LLSettingsBase
|
||||
{
|
||||
public:
|
||||
static const std::string SETTING_AMBIENT;
|
||||
static const std::string SETTING_BLOOM_TEXTUREID;
|
||||
static const std::string SETTING_RAINBOW_TEXTUREID;
|
||||
static const std::string SETTING_HALO_TEXTUREID;
|
||||
static const std::string SETTING_BLUE_DENSITY;
|
||||
static const std::string SETTING_BLUE_HORIZON;
|
||||
static const std::string SETTING_DENSITY_MULTIPLIER;
|
||||
static const std::string SETTING_DISTANCE_MULTIPLIER;
|
||||
static const std::string SETTING_HAZE_DENSITY;
|
||||
static const std::string SETTING_HAZE_HORIZON;
|
||||
static const std::string SETTING_CLOUD_COLOR;
|
||||
static const std::string SETTING_CLOUD_POS_DENSITY1;
|
||||
static const std::string SETTING_CLOUD_POS_DENSITY2;
|
||||
static const std::string SETTING_CLOUD_SCALE;
|
||||
static const std::string SETTING_CLOUD_SCROLL_RATE;
|
||||
static const std::string SETTING_CLOUD_SHADOW;
|
||||
static const std::string SETTING_CLOUD_TEXTUREID;
|
||||
static const std::string SETTING_CLOUD_VARIANCE;
|
||||
|
||||
static const std::string SETTING_DOME_OFFSET;
|
||||
static const std::string SETTING_DOME_RADIUS;
|
||||
static const std::string SETTING_GAMMA;
|
||||
static const std::string SETTING_GLOW;
|
||||
static const std::string SETTING_LIGHT_NORMAL;
|
||||
static const std::string SETTING_MAX_Y;
|
||||
static const std::string SETTING_MOON_ROTATION;
|
||||
static const std::string SETTING_MOON_SCALE;
|
||||
static const std::string SETTING_MOON_TEXTUREID;
|
||||
static const std::string SETTING_MOON_BRIGHTNESS;
|
||||
|
||||
static const std::string SETTING_STAR_BRIGHTNESS;
|
||||
static const std::string SETTING_SUNLIGHT_COLOR;
|
||||
static const std::string SETTING_SUN_ROTATION;
|
||||
static const std::string SETTING_SUN_SCALE;
|
||||
static const std::string SETTING_SUN_TEXTUREID;
|
||||
|
||||
static const std::string SETTING_PLANET_RADIUS;
|
||||
static const std::string SETTING_SKY_BOTTOM_RADIUS;
|
||||
static const std::string SETTING_SKY_TOP_RADIUS;
|
||||
static const std::string SETTING_SUN_ARC_RADIANS;
|
||||
static const std::string SETTING_MIE_ANISOTROPY_FACTOR;
|
||||
|
||||
static const std::string SETTING_RAYLEIGH_CONFIG;
|
||||
static const std::string SETTING_MIE_CONFIG;
|
||||
static const std::string SETTING_ABSORPTION_CONFIG;
|
||||
|
||||
static const std::string KEY_DENSITY_PROFILE;
|
||||
static const std::string SETTING_DENSITY_PROFILE_WIDTH;
|
||||
static const std::string SETTING_DENSITY_PROFILE_EXP_TERM;
|
||||
static const std::string SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR;
|
||||
static const std::string SETTING_DENSITY_PROFILE_LINEAR_TERM;
|
||||
static const std::string SETTING_DENSITY_PROFILE_CONSTANT_TERM;
|
||||
|
||||
static const std::string SETTING_SKY_MOISTURE_LEVEL;
|
||||
static const std::string SETTING_SKY_DROPLET_RADIUS;
|
||||
static const std::string SETTING_SKY_ICE_LEVEL;
|
||||
|
||||
static const std::string SETTING_LEGACY_HAZE;
|
||||
|
||||
static const LLUUID DEFAULT_ASSET_ID;
|
||||
|
||||
typedef PTR_NAMESPACE::shared_ptr<LLSettingsSky> ptr_t;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
LLSettingsSky(const LLSD &data);
|
||||
virtual ~LLSettingsSky() { };
|
||||
|
||||
virtual ptr_t buildClone() const = 0;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("sky"); }
|
||||
virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_SKY; }
|
||||
|
||||
// Settings status
|
||||
virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE;
|
||||
|
||||
virtual void replaceSettings(LLSD settings) SETTINGS_OVERRIDE;
|
||||
|
||||
void replaceWithSky(LLSettingsSky::ptr_t pother);
|
||||
static LLSD defaults(const LLSettingsBase::TrackPosition& position = 0.0f);
|
||||
|
||||
F32 getPlanetRadius() const;
|
||||
F32 getSkyBottomRadius() const;
|
||||
F32 getSkyTopRadius() const;
|
||||
F32 getSunArcRadians() const;
|
||||
F32 getMieAnisotropy() const;
|
||||
|
||||
F32 getSkyMoistureLevel() const;
|
||||
F32 getSkyDropletRadius() const;
|
||||
F32 getSkyIceLevel() const;
|
||||
|
||||
// Return first (only) profile layer represented in LLSD
|
||||
LLSD getRayleighConfig() const;
|
||||
LLSD getMieConfig() const;
|
||||
LLSD getAbsorptionConfig() const;
|
||||
|
||||
// Return entire LLSDArray of profile layers represented in LLSD
|
||||
LLSD getRayleighConfigs() const;
|
||||
LLSD getMieConfigs() const;
|
||||
LLSD getAbsorptionConfigs() const;
|
||||
|
||||
LLUUID getBloomTextureId() const;
|
||||
LLUUID getRainbowTextureId() const;
|
||||
LLUUID getHaloTextureId() const;
|
||||
|
||||
void setRayleighConfigs(const LLSD& rayleighConfig);
|
||||
void setMieConfigs(const LLSD& mieConfig);
|
||||
void setAbsorptionConfigs(const LLSD& absorptionConfig);
|
||||
|
||||
void setPlanetRadius(F32 radius);
|
||||
void setSkyBottomRadius(F32 radius);
|
||||
void setSkyTopRadius(F32 radius);
|
||||
void setSunArcRadians(F32 radians);
|
||||
void setMieAnisotropy(F32 aniso_factor);
|
||||
|
||||
void setSkyMoistureLevel(F32 moisture_level);
|
||||
void setSkyDropletRadius(F32 radius);
|
||||
void setSkyIceLevel(F32 ice_level);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
LLColor3 getAmbientColor() const;
|
||||
void setAmbientColor(const LLColor3 &val);
|
||||
|
||||
LLColor3 getCloudColor() const;
|
||||
void setCloudColor(const LLColor3 &val);
|
||||
|
||||
LLUUID getCloudNoiseTextureId() const;
|
||||
void setCloudNoiseTextureId(const LLUUID &id);
|
||||
|
||||
LLColor3 getCloudPosDensity1() const;
|
||||
void setCloudPosDensity1(const LLColor3 &val);
|
||||
|
||||
LLColor3 getCloudPosDensity2() const;
|
||||
void setCloudPosDensity2(const LLColor3 &val);
|
||||
|
||||
F32 getCloudScale() const;
|
||||
void setCloudScale(F32 val);
|
||||
|
||||
LLVector2 getCloudScrollRate() const;
|
||||
void setCloudScrollRate(const LLVector2 &val);
|
||||
|
||||
void setCloudScrollRateX(F32 val);
|
||||
void setCloudScrollRateY(F32 val);
|
||||
|
||||
F32 getCloudShadow() const;
|
||||
void setCloudShadow(F32 val);
|
||||
|
||||
F32 getCloudVariance() const;
|
||||
void setCloudVariance(F32 val);
|
||||
|
||||
F32 getDomeOffset() const;
|
||||
F32 getDomeRadius() const;
|
||||
|
||||
F32 getGamma() const;
|
||||
|
||||
void setGamma(F32 val);
|
||||
|
||||
LLColor3 getGlow() const;
|
||||
void setGlow(const LLColor3 &val);
|
||||
|
||||
F32 getMaxY() const;
|
||||
|
||||
void setMaxY(F32 val);
|
||||
|
||||
LLQuaternion getMoonRotation() const;
|
||||
void setMoonRotation(const LLQuaternion &val);
|
||||
|
||||
F32 getMoonScale() const;
|
||||
void setMoonScale(F32 val);
|
||||
|
||||
LLUUID getMoonTextureId() const;
|
||||
void setMoonTextureId(LLUUID id);
|
||||
|
||||
F32 getMoonBrightness() const;
|
||||
void setMoonBrightness(F32 brightness_factor);
|
||||
|
||||
F32 getStarBrightness() const;
|
||||
void setStarBrightness(F32 val);
|
||||
|
||||
LLColor3 getSunlightColor() const;
|
||||
void setSunlightColor(const LLColor3 &val);
|
||||
|
||||
LLQuaternion getSunRotation() const;
|
||||
void setSunRotation(const LLQuaternion &val) ;
|
||||
|
||||
F32 getSunScale() const;
|
||||
void setSunScale(F32 val);
|
||||
|
||||
LLUUID getSunTextureId() const;
|
||||
void setSunTextureId(LLUUID id);
|
||||
|
||||
//=====================================================================
|
||||
// transient properties used in animations.
|
||||
LLUUID getNextSunTextureId() const;
|
||||
LLUUID getNextMoonTextureId() const;
|
||||
LLUUID getNextCloudNoiseTextureId() const;
|
||||
LLUUID getNextBloomTextureId() const;
|
||||
|
||||
//=====================================================================
|
||||
virtual void loadTextures() { };
|
||||
|
||||
//=====================================================================
|
||||
virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE;
|
||||
static validation_list_t validationList();
|
||||
|
||||
static LLSD translateLegacySettings(const LLSD& legacy);
|
||||
|
||||
// LEGACY_ATMOSPHERICS
|
||||
static LLSD translateLegacyHazeSettings(const LLSD& legacy);
|
||||
|
||||
LLColor3 getLightAttenuation(F32 distance) const;
|
||||
LLColor3 getLightTransmittance(F32 distance) const;
|
||||
LLColor3 getTotalDensity() const;
|
||||
LLColor3 gammaCorrect(const LLColor3& in) const;
|
||||
|
||||
LLColor3 getBlueDensity() const;
|
||||
LLColor3 getBlueHorizon() const;
|
||||
F32 getHazeDensity() const;
|
||||
F32 getHazeHorizon() const;
|
||||
F32 getDensityMultiplier() const;
|
||||
F32 getDistanceMultiplier() const;
|
||||
|
||||
void setBlueDensity(const LLColor3 &val);
|
||||
void setBlueHorizon(const LLColor3 &val);
|
||||
void setDensityMultiplier(F32 val);
|
||||
void setDistanceMultiplier(F32 val);
|
||||
void setHazeDensity(F32 val);
|
||||
void setHazeHorizon(F32 val);
|
||||
|
||||
// Internal/calculated settings
|
||||
bool getIsSunUp() const;
|
||||
bool getIsMoonUp() const;
|
||||
|
||||
// determines how much the haze glow effect occurs in rendering
|
||||
F32 getSunMoonGlowFactor() const;
|
||||
|
||||
LLVector3 getLightDirection() const;
|
||||
LLColor3 getLightDiffuse() const;
|
||||
|
||||
LLVector3 getSunDirection() const;
|
||||
LLVector3 getMoonDirection() const;
|
||||
|
||||
// color based on brightness
|
||||
LLColor3 getMoonlightColor() const;
|
||||
|
||||
LLColor4 getMoonAmbient() const;
|
||||
LLColor3 getMoonDiffuse() const;
|
||||
LLColor4 getSunAmbient() const;
|
||||
LLColor3 getSunDiffuse() const;
|
||||
LLColor4 getTotalAmbient() const;
|
||||
LLColor4 getHazeColor() const;
|
||||
|
||||
LLColor3 getSunlightColorClamped() const;
|
||||
LLColor3 getAmbientColorClamped() const;
|
||||
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
|
||||
|
||||
static LLUUID GetDefaultAssetId();
|
||||
static LLUUID GetDefaultSunTextureId();
|
||||
static LLUUID GetBlankSunTextureId();
|
||||
static LLUUID GetDefaultMoonTextureId();
|
||||
static LLUUID GetDefaultCloudNoiseTextureId();
|
||||
static LLUUID GetDefaultBloomTextureId();
|
||||
static LLUUID GetDefaultRainbowTextureId();
|
||||
static LLUUID GetDefaultHaloTextureId();
|
||||
|
||||
static LLSD createDensityProfileLayer(
|
||||
F32 width,
|
||||
F32 exponential_term,
|
||||
F32 exponential_scale_factor,
|
||||
F32 linear_term,
|
||||
F32 constant_term,
|
||||
F32 aniso_factor = 0.0f);
|
||||
|
||||
static LLSD createSingleLayerDensityProfile(
|
||||
F32 width,
|
||||
F32 exponential_term,
|
||||
F32 exponential_scale_factor,
|
||||
F32 linear_term,
|
||||
F32 constant_term,
|
||||
F32 aniso_factor = 0.0f);
|
||||
|
||||
virtual void updateSettings() SETTINGS_OVERRIDE;
|
||||
protected:
|
||||
static const std::string SETTING_LEGACY_EAST_ANGLE;
|
||||
static const std::string SETTING_LEGACY_ENABLE_CLOUD_SCROLL;
|
||||
static const std::string SETTING_LEGACY_SUN_ANGLE;
|
||||
|
||||
LLSettingsSky();
|
||||
|
||||
virtual stringset_t getSlerpKeys() const SETTINGS_OVERRIDE;
|
||||
virtual stringset_t getSkipInterpolateKeys() const SETTINGS_OVERRIDE;
|
||||
|
||||
LLUUID mNextSunTextureId;
|
||||
LLUUID mNextMoonTextureId;
|
||||
LLUUID mNextCloudTextureId;
|
||||
LLUUID mNextBloomTextureId;
|
||||
LLUUID mNextRainbowTextureId;
|
||||
LLUUID mNextHaloTextureId;
|
||||
|
||||
private:
|
||||
static LLSD rayleighConfigDefault();
|
||||
static LLSD absorptionConfigDefault();
|
||||
static LLSD mieConfigDefault();
|
||||
|
||||
LLColor3 getColor(const std::string& key, const LLColor3& default_value) const;
|
||||
F32 getFloat(const std::string& key, F32 default_value) const;
|
||||
|
||||
void calculateHeavenlyBodyPositions() const;
|
||||
void calculateLightSettings() const;
|
||||
void clampColor(LLColor3& color, F32 gamma, const F32 scale = 1.0f) const;
|
||||
|
||||
mutable LLVector3 mSunDirection;
|
||||
mutable LLVector3 mMoonDirection;
|
||||
mutable LLVector3 mLightDirection;
|
||||
|
||||
static const F32 DOME_RADIUS;
|
||||
static const F32 DOME_OFFSET;
|
||||
|
||||
mutable LLColor4 mMoonAmbient;
|
||||
mutable LLColor3 mMoonDiffuse;
|
||||
mutable LLColor4 mSunAmbient;
|
||||
mutable LLColor3 mSunDiffuse;
|
||||
mutable LLColor4 mTotalAmbient;
|
||||
mutable LLColor4 mHazeColor;
|
||||
|
||||
typedef std::map<std::string, S32> mapNameToUniformId_t;
|
||||
|
||||
static mapNameToUniformId_t sNameToUniformMapping;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,304 @@
|
|||
/**
|
||||
* @file llsettingswater.h
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llsettingswater.h"
|
||||
#include <algorithm>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include "lltrace.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "v3colorutil.h"
|
||||
#include "indra_constants.h"
|
||||
|
||||
//=========================================================================
|
||||
namespace
|
||||
{
|
||||
LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment");
|
||||
LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment");
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
const std::string LLSettingsWater::SETTING_BLUR_MULTIPLIER("blur_multiplier");
|
||||
const std::string LLSettingsWater::SETTING_FOG_COLOR("water_fog_color");
|
||||
const std::string LLSettingsWater::SETTING_FOG_DENSITY("water_fog_density");
|
||||
const std::string LLSettingsWater::SETTING_FOG_MOD("underwater_fog_mod");
|
||||
const std::string LLSettingsWater::SETTING_FRESNEL_OFFSET("fresnel_offset");
|
||||
const std::string LLSettingsWater::SETTING_FRESNEL_SCALE("fresnel_scale");
|
||||
const std::string LLSettingsWater::SETTING_TRANSPARENT_TEXTURE("transparent_texture");
|
||||
const std::string LLSettingsWater::SETTING_NORMAL_MAP("normal_map");
|
||||
const std::string LLSettingsWater::SETTING_NORMAL_SCALE("normal_scale");
|
||||
const std::string LLSettingsWater::SETTING_SCALE_ABOVE("scale_above");
|
||||
const std::string LLSettingsWater::SETTING_SCALE_BELOW("scale_below");
|
||||
const std::string LLSettingsWater::SETTING_WAVE1_DIR("wave1_direction");
|
||||
const std::string LLSettingsWater::SETTING_WAVE2_DIR("wave2_direction");
|
||||
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_BLUR_MULTIPLIER("blurMultiplier");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_FOG_COLOR("waterFogColor");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_FOG_DENSITY("waterFogDensity");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_FOG_MOD("underWaterFogMod");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_FRESNEL_OFFSET("fresnelOffset");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_FRESNEL_SCALE("fresnelScale");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_NORMAL_MAP("normalMap");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_NORMAL_SCALE("normScale");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_SCALE_ABOVE("scaleAbove");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_SCALE_BELOW("scaleBelow");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_WAVE1_DIR("wave1Dir");
|
||||
const std::string LLSettingsWater::SETTING_LEGACY_WAVE2_DIR("wave2Dir");
|
||||
|
||||
const LLUUID LLSettingsWater::DEFAULT_ASSET_ID("59d1a851-47e7-0e5f-1ed7-6b715154f41a");
|
||||
|
||||
static const LLUUID DEFAULT_TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004");
|
||||
static const LLUUID DEFAULT_OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055");
|
||||
|
||||
//=========================================================================
|
||||
LLSettingsWater::LLSettingsWater(const LLSD &data) :
|
||||
LLSettingsBase(data),
|
||||
mNextNormalMapID()
|
||||
{
|
||||
}
|
||||
|
||||
LLSettingsWater::LLSettingsWater() :
|
||||
LLSettingsBase(),
|
||||
mNextNormalMapID()
|
||||
{
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
LLSD LLSettingsWater::defaults(const LLSettingsBase::TrackPosition& position)
|
||||
{
|
||||
static LLSD dfltsetting;
|
||||
|
||||
if (dfltsetting.size() == 0)
|
||||
{
|
||||
// give the normal scale offset some variability over track time...
|
||||
F32 normal_scale_offset = (position * 0.5f) - 0.25f;
|
||||
|
||||
// Magic constants copied form defaults.xml
|
||||
dfltsetting[SETTING_BLUR_MULTIPLIER] = LLSD::Real(0.04000f);
|
||||
dfltsetting[SETTING_FOG_COLOR] = LLColor3(0.0156f, 0.1490f, 0.2509f).getValue();
|
||||
dfltsetting[SETTING_FOG_DENSITY] = LLSD::Real(2.0f);
|
||||
dfltsetting[SETTING_FOG_MOD] = LLSD::Real(0.25f);
|
||||
dfltsetting[SETTING_FRESNEL_OFFSET] = LLSD::Real(0.5f);
|
||||
dfltsetting[SETTING_FRESNEL_SCALE] = LLSD::Real(0.3999);
|
||||
dfltsetting[SETTING_TRANSPARENT_TEXTURE] = GetDefaultTransparentTextureAssetId();
|
||||
dfltsetting[SETTING_NORMAL_MAP] = GetDefaultWaterNormalAssetId();
|
||||
dfltsetting[SETTING_NORMAL_SCALE] = LLVector3(2.0f + normal_scale_offset, 2.0f + normal_scale_offset, 2.0f + normal_scale_offset).getValue();
|
||||
dfltsetting[SETTING_SCALE_ABOVE] = LLSD::Real(0.0299f);
|
||||
dfltsetting[SETTING_SCALE_BELOW] = LLSD::Real(0.2000f);
|
||||
dfltsetting[SETTING_WAVE1_DIR] = LLVector2(1.04999f, -0.42000f).getValue();
|
||||
dfltsetting[SETTING_WAVE2_DIR] = LLVector2(1.10999f, -1.16000f).getValue();
|
||||
|
||||
dfltsetting[SETTING_TYPE] = "water";
|
||||
}
|
||||
|
||||
return dfltsetting;
|
||||
}
|
||||
|
||||
LLSD LLSettingsWater::translateLegacySettings(LLSD legacy)
|
||||
{
|
||||
bool converted_something(false);
|
||||
LLSD newsettings(defaults());
|
||||
|
||||
if (legacy.has(SETTING_LEGACY_BLUR_MULTIPLIER))
|
||||
{
|
||||
newsettings[SETTING_BLUR_MULTIPLIER] = LLSD::Real(legacy[SETTING_LEGACY_BLUR_MULTIPLIER].asReal());
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_FOG_COLOR))
|
||||
{
|
||||
newsettings[SETTING_FOG_COLOR] = LLColor3(legacy[SETTING_LEGACY_FOG_COLOR]).getValue();
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_FOG_DENSITY))
|
||||
{
|
||||
newsettings[SETTING_FOG_DENSITY] = LLSD::Real(legacy[SETTING_LEGACY_FOG_DENSITY]);
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_FOG_MOD))
|
||||
{
|
||||
newsettings[SETTING_FOG_MOD] = LLSD::Real(legacy[SETTING_LEGACY_FOG_MOD].asReal());
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_FRESNEL_OFFSET))
|
||||
{
|
||||
newsettings[SETTING_FRESNEL_OFFSET] = LLSD::Real(legacy[SETTING_LEGACY_FRESNEL_OFFSET].asReal());
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_FRESNEL_SCALE))
|
||||
{
|
||||
newsettings[SETTING_FRESNEL_SCALE] = LLSD::Real(legacy[SETTING_LEGACY_FRESNEL_SCALE].asReal());
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_NORMAL_MAP))
|
||||
{
|
||||
newsettings[SETTING_NORMAL_MAP] = LLSD::UUID(legacy[SETTING_LEGACY_NORMAL_MAP].asUUID());
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_NORMAL_SCALE))
|
||||
{
|
||||
newsettings[SETTING_NORMAL_SCALE] = LLVector3(legacy[SETTING_LEGACY_NORMAL_SCALE]).getValue();
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_SCALE_ABOVE))
|
||||
{
|
||||
newsettings[SETTING_SCALE_ABOVE] = LLSD::Real(legacy[SETTING_LEGACY_SCALE_ABOVE].asReal());
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_SCALE_BELOW))
|
||||
{
|
||||
newsettings[SETTING_SCALE_BELOW] = LLSD::Real(legacy[SETTING_LEGACY_SCALE_BELOW].asReal());
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_WAVE1_DIR))
|
||||
{
|
||||
newsettings[SETTING_WAVE1_DIR] = LLVector2(legacy[SETTING_LEGACY_WAVE1_DIR]).getValue();
|
||||
converted_something |= true;
|
||||
}
|
||||
if (legacy.has(SETTING_LEGACY_WAVE2_DIR))
|
||||
{
|
||||
newsettings[SETTING_WAVE2_DIR] = LLVector2(legacy[SETTING_LEGACY_WAVE2_DIR]).getValue();
|
||||
converted_something |= true;
|
||||
}
|
||||
|
||||
if (!converted_something)
|
||||
return LLSD();
|
||||
return newsettings;
|
||||
}
|
||||
|
||||
void LLSettingsWater::blend(const LLSettingsBase::ptr_t &end, F64 blendf)
|
||||
{
|
||||
LLSettingsWater::ptr_t other = PTR_NAMESPACE::static_pointer_cast<LLSettingsWater>(end);
|
||||
if (other)
|
||||
{
|
||||
LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, other->getParameterMap(), blendf);
|
||||
replaceSettings(blenddata);
|
||||
mNextNormalMapID = other->getNormalMapID();
|
||||
mNextTransparentTextureID = other->getTransparentTextureID();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Could not cast end settings to water. No blend performed." << LL_ENDL;
|
||||
}
|
||||
setBlendFactor(blendf);
|
||||
}
|
||||
|
||||
void LLSettingsWater::replaceSettings(LLSD settings)
|
||||
{
|
||||
LLSettingsBase::replaceSettings(settings);
|
||||
mNextNormalMapID.setNull();
|
||||
mNextTransparentTextureID.setNull();
|
||||
}
|
||||
|
||||
void LLSettingsWater::replaceWithWater(LLSettingsWater::ptr_t other)
|
||||
{
|
||||
replaceWith(other);
|
||||
|
||||
mNextNormalMapID = other->mNextNormalMapID;
|
||||
mNextTransparentTextureID = other->mNextTransparentTextureID;
|
||||
}
|
||||
|
||||
LLSettingsWater::validation_list_t LLSettingsWater::getValidationList() const
|
||||
{
|
||||
return LLSettingsWater::validationList();
|
||||
}
|
||||
|
||||
LLSettingsWater::validation_list_t LLSettingsWater::validationList()
|
||||
{
|
||||
static validation_list_t validation;
|
||||
|
||||
if (validation.empty())
|
||||
{ // Note the use of LLSD(LLSDArray()()()...) This is due to an issue with the
|
||||
// copy constructor for LLSDArray. Directly binding the LLSDArray as
|
||||
// a parameter without first wrapping it in a pure LLSD object will result
|
||||
// in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]]
|
||||
|
||||
validation.push_back(Validator(SETTING_BLUR_MULTIPLIER, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-0.5f)(0.5f)))));
|
||||
validation.push_back(Validator(SETTING_FOG_COLOR, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)(1.0f)),
|
||||
LLSD(LLSDArray(1.0f)(1.0f)(1.0f)(1.0f)))));
|
||||
validation.push_back(Validator(SETTING_FOG_DENSITY, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-10.0f)(10.0f)))));
|
||||
validation.push_back(Validator(SETTING_FOG_MOD, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f)))));
|
||||
validation.push_back(Validator(SETTING_FRESNEL_OFFSET, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
validation.push_back(Validator(SETTING_FRESNEL_SCALE, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
validation.push_back(Validator(SETTING_NORMAL_MAP, true, LLSD::TypeUUID));
|
||||
validation.push_back(Validator(SETTING_NORMAL_SCALE, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)),
|
||||
LLSD(LLSDArray(10.0f)(10.0f)(10.0f)))));
|
||||
validation.push_back(Validator(SETTING_SCALE_ABOVE, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f)))));
|
||||
validation.push_back(Validator(SETTING_SCALE_BELOW, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f)))));
|
||||
validation.push_back(Validator(SETTING_WAVE1_DIR, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
LLSD(LLSDArray(-20.0f)(-20.0f)),
|
||||
LLSD(LLSDArray(20.0f)(20.0f)))));
|
||||
validation.push_back(Validator(SETTING_WAVE2_DIR, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
LLSD(LLSDArray(-20.0f)(-20.0f)),
|
||||
LLSD(LLSDArray(20.0f)(20.0f)))));
|
||||
}
|
||||
|
||||
return validation;
|
||||
}
|
||||
|
||||
LLUUID LLSettingsWater::GetDefaultAssetId()
|
||||
{
|
||||
return DEFAULT_ASSET_ID;
|
||||
}
|
||||
|
||||
LLUUID LLSettingsWater::GetDefaultWaterNormalAssetId()
|
||||
{
|
||||
return DEFAULT_WATER_NORMAL;
|
||||
}
|
||||
|
||||
LLUUID LLSettingsWater::GetDefaultTransparentTextureAssetId()
|
||||
{
|
||||
return DEFAULT_TRANSPARENT_WATER_TEXTURE;
|
||||
}
|
||||
|
||||
LLUUID LLSettingsWater::GetDefaultOpaqueTextureAssetId()
|
||||
{
|
||||
return DEFAULT_OPAQUE_WATER_TEXTURE;
|
||||
}
|
||||
|
||||
F32 LLSettingsWater::getModifiedWaterFogDensity(bool underwater) const
|
||||
{
|
||||
F32 fog_density = getWaterFogDensity();
|
||||
F32 underwater_fog_mod = getFogMod();
|
||||
if (underwater && underwater_fog_mod > 0.0f)
|
||||
{
|
||||
underwater_fog_mod = llclamp(underwater_fog_mod, 0.0f, 10.0f);
|
||||
fog_density = pow(fog_density, underwater_fog_mod);
|
||||
}
|
||||
return fog_density;
|
||||
}
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
* @file llsettingssky.h
|
||||
* @author optional
|
||||
* @brief A base class for asset based settings groups.
|
||||
*
|
||||
* $LicenseInfo:2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2017, 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_SETTINGS_WATER_H
|
||||
#define LL_SETTINGS_WATER_H
|
||||
|
||||
#include "llsettingsbase.h"
|
||||
|
||||
class LLSettingsWater : public LLSettingsBase
|
||||
{
|
||||
public:
|
||||
static const std::string SETTING_BLUR_MULTIPLIER;
|
||||
static const std::string SETTING_FOG_COLOR;
|
||||
static const std::string SETTING_FOG_DENSITY;
|
||||
static const std::string SETTING_FOG_MOD;
|
||||
static const std::string SETTING_FRESNEL_OFFSET;
|
||||
static const std::string SETTING_FRESNEL_SCALE;
|
||||
static const std::string SETTING_TRANSPARENT_TEXTURE;
|
||||
static const std::string SETTING_NORMAL_MAP;
|
||||
static const std::string SETTING_NORMAL_SCALE;
|
||||
static const std::string SETTING_SCALE_ABOVE;
|
||||
static const std::string SETTING_SCALE_BELOW;
|
||||
static const std::string SETTING_WAVE1_DIR;
|
||||
static const std::string SETTING_WAVE2_DIR;
|
||||
|
||||
static const LLUUID DEFAULT_ASSET_ID;
|
||||
|
||||
typedef PTR_NAMESPACE::shared_ptr<LLSettingsWater> ptr_t;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
LLSettingsWater(const LLSD &data);
|
||||
virtual ~LLSettingsWater() { };
|
||||
|
||||
virtual ptr_t buildClone() const = 0;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("water"); }
|
||||
virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_WATER; }
|
||||
|
||||
// Settings status
|
||||
virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE;
|
||||
|
||||
virtual void replaceSettings(LLSD settings) SETTINGS_OVERRIDE;
|
||||
void replaceWithWater(LLSettingsWater::ptr_t other);
|
||||
|
||||
static LLSD defaults(const LLSettingsBase::TrackPosition& position = 0.0f);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
F32 getBlurMultiplier() const
|
||||
{
|
||||
return mSettings[SETTING_BLUR_MULTIPLIER].asReal();
|
||||
}
|
||||
|
||||
void setBlurMultiplier(F32 val)
|
||||
{
|
||||
setValue(SETTING_BLUR_MULTIPLIER, val);
|
||||
}
|
||||
|
||||
LLColor3 getWaterFogColor() const
|
||||
{
|
||||
return LLColor3(mSettings[SETTING_FOG_COLOR]);
|
||||
}
|
||||
|
||||
void setWaterFogColor(LLColor3 val)
|
||||
{
|
||||
setValue(SETTING_FOG_COLOR, val);
|
||||
}
|
||||
|
||||
F32 getWaterFogDensity() const
|
||||
{
|
||||
return mSettings[SETTING_FOG_DENSITY].asReal();
|
||||
}
|
||||
|
||||
F32 getModifiedWaterFogDensity(bool underwater) const;
|
||||
|
||||
void setWaterFogDensity(F32 val)
|
||||
{
|
||||
setValue(SETTING_FOG_DENSITY, val);
|
||||
}
|
||||
|
||||
F32 getFogMod() const
|
||||
{
|
||||
return mSettings[SETTING_FOG_MOD].asReal();
|
||||
}
|
||||
|
||||
void setFogMod(F32 val)
|
||||
{
|
||||
setValue(SETTING_FOG_MOD, val);
|
||||
}
|
||||
|
||||
F32 getFresnelOffset() const
|
||||
{
|
||||
return mSettings[SETTING_FRESNEL_OFFSET].asReal();
|
||||
}
|
||||
|
||||
void setFresnelOffset(F32 val)
|
||||
{
|
||||
setValue(SETTING_FRESNEL_OFFSET, val);
|
||||
}
|
||||
|
||||
F32 getFresnelScale() const
|
||||
{
|
||||
return mSettings[SETTING_FRESNEL_SCALE].asReal();
|
||||
}
|
||||
|
||||
void setFresnelScale(F32 val)
|
||||
{
|
||||
setValue(SETTING_FRESNEL_SCALE, val);
|
||||
}
|
||||
|
||||
LLUUID getTransparentTextureID() const
|
||||
{
|
||||
return mSettings[SETTING_TRANSPARENT_TEXTURE].asUUID();
|
||||
}
|
||||
|
||||
void setTransparentTextureID(LLUUID val)
|
||||
{
|
||||
setValue(SETTING_TRANSPARENT_TEXTURE, val);
|
||||
}
|
||||
|
||||
LLUUID getNormalMapID() const
|
||||
{
|
||||
return mSettings[SETTING_NORMAL_MAP].asUUID();
|
||||
}
|
||||
|
||||
void setNormalMapID(LLUUID val)
|
||||
{
|
||||
setValue(SETTING_NORMAL_MAP, val);
|
||||
}
|
||||
|
||||
LLVector3 getNormalScale() const
|
||||
{
|
||||
return LLVector3(mSettings[SETTING_NORMAL_SCALE]);
|
||||
}
|
||||
|
||||
void setNormalScale(LLVector3 val)
|
||||
{
|
||||
setValue(SETTING_NORMAL_SCALE, val);
|
||||
}
|
||||
|
||||
F32 getScaleAbove() const
|
||||
{
|
||||
return mSettings[SETTING_SCALE_ABOVE].asReal();
|
||||
}
|
||||
|
||||
void setScaleAbove(F32 val)
|
||||
{
|
||||
setValue(SETTING_SCALE_ABOVE, val);
|
||||
}
|
||||
|
||||
F32 getScaleBelow() const
|
||||
{
|
||||
return mSettings[SETTING_SCALE_BELOW].asReal();
|
||||
}
|
||||
|
||||
void setScaleBelow(F32 val)
|
||||
{
|
||||
setValue(SETTING_SCALE_BELOW, val);
|
||||
}
|
||||
|
||||
LLVector2 getWave1Dir() const
|
||||
{
|
||||
return LLVector2(mSettings[SETTING_WAVE1_DIR]);
|
||||
}
|
||||
|
||||
void setWave1Dir(LLVector2 val)
|
||||
{
|
||||
setValue(SETTING_WAVE1_DIR, val);
|
||||
}
|
||||
|
||||
LLVector2 getWave2Dir() const
|
||||
{
|
||||
return LLVector2(mSettings[SETTING_WAVE2_DIR]);
|
||||
}
|
||||
|
||||
void setWave2Dir(LLVector2 val)
|
||||
{
|
||||
setValue(SETTING_WAVE2_DIR, val);
|
||||
}
|
||||
|
||||
//-------------------------------------------
|
||||
LLUUID getNextNormalMapID() const
|
||||
{
|
||||
return mNextNormalMapID;
|
||||
}
|
||||
|
||||
LLUUID getNextTransparentTextureID() const
|
||||
{
|
||||
return mNextTransparentTextureID;
|
||||
}
|
||||
|
||||
virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE;
|
||||
static validation_list_t validationList();
|
||||
|
||||
static LLSD translateLegacySettings(LLSD legacy);
|
||||
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
|
||||
|
||||
static LLUUID GetDefaultAssetId();
|
||||
static LLUUID GetDefaultWaterNormalAssetId();
|
||||
static LLUUID GetDefaultTransparentTextureAssetId();
|
||||
static LLUUID GetDefaultOpaqueTextureAssetId();
|
||||
|
||||
protected:
|
||||
static const std::string SETTING_LEGACY_BLUR_MULTIPLIER;
|
||||
static const std::string SETTING_LEGACY_FOG_COLOR;
|
||||
static const std::string SETTING_LEGACY_FOG_DENSITY;
|
||||
static const std::string SETTING_LEGACY_FOG_MOD;
|
||||
static const std::string SETTING_LEGACY_FRESNEL_OFFSET;
|
||||
static const std::string SETTING_LEGACY_FRESNEL_SCALE;
|
||||
static const std::string SETTING_LEGACY_NORMAL_MAP;
|
||||
static const std::string SETTING_LEGACY_NORMAL_SCALE;
|
||||
static const std::string SETTING_LEGACY_SCALE_ABOVE;
|
||||
static const std::string SETTING_LEGACY_SCALE_BELOW;
|
||||
static const std::string SETTING_LEGACY_WAVE1_DIR;
|
||||
static const std::string SETTING_LEGACY_WAVE2_DIR;
|
||||
|
||||
LLSettingsWater();
|
||||
|
||||
LLUUID mNextTransparentTextureID;
|
||||
LLUUID mNextNormalMapID;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -90,6 +90,7 @@ set(llmath_HEADER_FILES
|
|||
raytrace.h
|
||||
v2math.h
|
||||
v3color.h
|
||||
v3colorutil.h
|
||||
v3dmath.h
|
||||
v3math.h
|
||||
v4color.h
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ F32 LLCamera::getMaxView() const
|
|||
: MAX_FIELD_OF_VIEW; // narrow views
|
||||
}
|
||||
|
||||
LLPlane LLCamera::getUserClipPlane()
|
||||
{
|
||||
return mAgentPlanes[AGENT_PLANE_USER_CLIP];
|
||||
}
|
||||
|
||||
// ---------------- LLCamera::setFoo() member functions ----------------
|
||||
|
||||
void LLCamera::setUserClipPlane(LLPlane& plane)
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ public:
|
|||
|
||||
bool isChanged(); //check if mAgentPlanes changed since last frame.
|
||||
|
||||
LLPlane getUserClipPlane();
|
||||
void setUserClipPlane(LLPlane& plane);
|
||||
void disableUserClipPlane();
|
||||
virtual void setView(F32 vertical_fov_rads);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,20 @@
|
|||
#include "llquaternion.h"
|
||||
#include "llcoordframe.h"
|
||||
|
||||
#define CHECK_FINITE(var) \
|
||||
if (!var.isFinite()) \
|
||||
{ \
|
||||
LL_WARNS() << "Non Finite " << std::string(#var) << LL_ENDL; \
|
||||
reset(); \
|
||||
}
|
||||
|
||||
#define CHECK_FINITE_OBJ() \
|
||||
if (!isFinite()) \
|
||||
{ \
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame " << LL_ENDL; \
|
||||
reset(); \
|
||||
}
|
||||
|
||||
#ifndef X_AXIS
|
||||
#define X_AXIS 1.0f,0.0f,0.0f
|
||||
#define Y_AXIS 0.0f,1.0f,0.0f
|
||||
|
|
@ -56,11 +70,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin) :
|
|||
mYAxis(Y_AXIS),
|
||||
mZAxis(Z_AXIS)
|
||||
{
|
||||
if( !mOrigin.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE(mOrigin);
|
||||
}
|
||||
|
||||
LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLVector3 &direction) :
|
||||
|
|
@ -68,11 +78,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLVector3 &direction)
|
|||
{
|
||||
lookDir(direction);
|
||||
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
LLCoordFrame::LLCoordFrame(const LLVector3 &x_axis,
|
||||
|
|
@ -83,11 +89,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &x_axis,
|
|||
mYAxis(y_axis),
|
||||
mZAxis(z_axis)
|
||||
{
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
LLCoordFrame::LLCoordFrame(const LLVector3 &origin,
|
||||
|
|
@ -99,11 +101,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin,
|
|||
mYAxis(y_axis),
|
||||
mZAxis(z_axis)
|
||||
{
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -114,11 +112,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin,
|
|||
mYAxis(rotation.mMatrix[VY]),
|
||||
mZAxis(rotation.mMatrix[VZ])
|
||||
{
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
LLCoordFrame::LLCoordFrame(const LLQuaternion &q) :
|
||||
|
|
@ -129,11 +123,7 @@ LLCoordFrame::LLCoordFrame(const LLQuaternion &q) :
|
|||
mYAxis.setVec(rotation_matrix.mMatrix[VY]);
|
||||
mZAxis.setVec(rotation_matrix.mMatrix[VZ]);
|
||||
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLQuaternion &q) :
|
||||
|
|
@ -144,11 +134,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLQuaternion &q) :
|
|||
mYAxis.setVec(rotation_matrix.mMatrix[VY]);
|
||||
mZAxis.setVec(rotation_matrix.mMatrix[VZ]);
|
||||
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
LLCoordFrame::LLCoordFrame(const LLMatrix4 &mat) :
|
||||
|
|
@ -157,11 +143,7 @@ LLCoordFrame::LLCoordFrame(const LLMatrix4 &mat) :
|
|||
mYAxis(mat.mMatrix[VY]),
|
||||
mZAxis(mat.mMatrix[VZ])
|
||||
{
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -173,11 +155,7 @@ LLCoordFrame::LLCoordFrame(const F32 *origin, const F32 *rotation) :
|
|||
mYAxis(rotation+3*VY),
|
||||
mZAxis(rotation+3*VZ)
|
||||
{
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
@ -188,11 +166,7 @@ LLCoordFrame::LLCoordFrame(const F32 *origin_and_rotation) :
|
|||
mYAxis(origin_and_rotation + 3*(VY+1)),
|
||||
mZAxis(origin_and_rotation + 3*(VZ+1))
|
||||
{
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
@ -217,21 +191,13 @@ void LLCoordFrame::setOrigin(F32 x, F32 y, F32 z)
|
|||
{
|
||||
mOrigin.setVec(x, y, z);
|
||||
|
||||
if( !mOrigin.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setOrigin()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE(mOrigin);
|
||||
}
|
||||
|
||||
void LLCoordFrame::setOrigin(const LLVector3 &new_origin)
|
||||
{
|
||||
mOrigin = new_origin;
|
||||
if( !mOrigin.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setOrigin()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE(mOrigin);
|
||||
}
|
||||
|
||||
void LLCoordFrame::setOrigin(const F32 *origin)
|
||||
|
|
@ -239,23 +205,13 @@ void LLCoordFrame::setOrigin(const F32 *origin)
|
|||
mOrigin.mV[VX] = *(origin + VX);
|
||||
mOrigin.mV[VY] = *(origin + VY);
|
||||
mOrigin.mV[VZ] = *(origin + VZ);
|
||||
|
||||
if( !mOrigin.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setOrigin()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE(mOrigin);
|
||||
}
|
||||
|
||||
void LLCoordFrame::setOrigin(const LLCoordFrame &frame)
|
||||
{
|
||||
mOrigin = frame.getOrigin();
|
||||
|
||||
if( !mOrigin.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setOrigin()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE(mOrigin);
|
||||
}
|
||||
|
||||
// setAxes() member functions set the axes, and assume that
|
||||
|
|
@ -268,11 +224,7 @@ void LLCoordFrame::setAxes(const LLVector3 &x_axis,
|
|||
mXAxis = x_axis;
|
||||
mYAxis = y_axis;
|
||||
mZAxis = z_axis;
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -281,11 +233,7 @@ void LLCoordFrame::setAxes(const LLMatrix3 &rotation_matrix)
|
|||
mXAxis.setVec(rotation_matrix.mMatrix[VX]);
|
||||
mYAxis.setVec(rotation_matrix.mMatrix[VY]);
|
||||
mZAxis.setVec(rotation_matrix.mMatrix[VZ]);
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -293,11 +241,7 @@ void LLCoordFrame::setAxes(const LLQuaternion &q )
|
|||
{
|
||||
LLMatrix3 rotation_matrix(q);
|
||||
setAxes(rotation_matrix);
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -313,11 +257,7 @@ void LLCoordFrame::setAxes( const F32 *rotation_matrix )
|
|||
mZAxis.mV[VY] = *(rotation_matrix + 3*VZ + VY);
|
||||
mZAxis.mV[VZ] = *(rotation_matrix + 3*VZ + VZ);
|
||||
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -326,40 +266,22 @@ void LLCoordFrame::setAxes(const LLCoordFrame &frame)
|
|||
mXAxis = frame.getXAxis();
|
||||
mYAxis = frame.getYAxis();
|
||||
mZAxis = frame.getZAxis();
|
||||
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
// translate() member functions move mOrigin to a relative position
|
||||
|
||||
void LLCoordFrame::translate(F32 x, F32 y, F32 z)
|
||||
{
|
||||
mOrigin.mV[VX] += x;
|
||||
mOrigin.mV[VY] += y;
|
||||
mOrigin.mV[VZ] += z;
|
||||
|
||||
if( !mOrigin.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::translate()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE(mOrigin);
|
||||
}
|
||||
|
||||
|
||||
void LLCoordFrame::translate(const LLVector3 &v)
|
||||
{
|
||||
mOrigin += v;
|
||||
|
||||
if( !mOrigin.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::translate()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE(mOrigin);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -368,12 +290,7 @@ void LLCoordFrame::translate(const F32 *origin)
|
|||
mOrigin.mV[VX] += *(origin + VX);
|
||||
mOrigin.mV[VY] += *(origin + VY);
|
||||
mOrigin.mV[VZ] += *(origin + VZ);
|
||||
|
||||
if( !mOrigin.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::translate()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE(mOrigin);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -383,6 +300,7 @@ void LLCoordFrame::rotate(F32 angle, F32 x, F32 y, F32 z)
|
|||
{
|
||||
LLQuaternion q(angle, LLVector3(x,y,z));
|
||||
rotate(q);
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -390,6 +308,7 @@ void LLCoordFrame::rotate(F32 angle, const LLVector3 &rotation_axis)
|
|||
{
|
||||
LLQuaternion q(angle, rotation_axis);
|
||||
rotate(q);
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -397,6 +316,7 @@ void LLCoordFrame::rotate(const LLQuaternion &q)
|
|||
{
|
||||
LLMatrix3 rotation_matrix(q);
|
||||
rotate(rotation_matrix);
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -405,12 +325,7 @@ void LLCoordFrame::rotate(const LLMatrix3 &rotation_matrix)
|
|||
mXAxis.rotVec(rotation_matrix);
|
||||
mYAxis.rotVec(rotation_matrix);
|
||||
orthonormalize();
|
||||
|
||||
if( !isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::rotate()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -419,12 +334,7 @@ void LLCoordFrame::roll(F32 angle)
|
|||
LLQuaternion q(angle, mXAxis);
|
||||
LLMatrix3 rotation_matrix(q);
|
||||
rotate(rotation_matrix);
|
||||
|
||||
if( !mYAxis.isFinite() || !mZAxis.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::roll()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
void LLCoordFrame::pitch(F32 angle)
|
||||
|
|
@ -432,12 +342,7 @@ void LLCoordFrame::pitch(F32 angle)
|
|||
LLQuaternion q(angle, mYAxis);
|
||||
LLMatrix3 rotation_matrix(q);
|
||||
rotate(rotation_matrix);
|
||||
|
||||
if( !mXAxis.isFinite() || !mZAxis.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::pitch()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
void LLCoordFrame::yaw(F32 angle)
|
||||
|
|
@ -445,12 +350,7 @@ void LLCoordFrame::yaw(F32 angle)
|
|||
LLQuaternion q(angle, mZAxis);
|
||||
LLMatrix3 rotation_matrix(q);
|
||||
rotate(rotation_matrix);
|
||||
|
||||
if( !mXAxis.isFinite() || !mYAxis.isFinite() )
|
||||
{
|
||||
reset();
|
||||
LL_WARNS() << "Non Finite in LLCoordFrame::yaw()" << LL_ENDL;
|
||||
}
|
||||
CHECK_FINITE_OBJ();
|
||||
}
|
||||
|
||||
// get*() routines
|
||||
|
|
|
|||
|
|
@ -537,6 +537,35 @@ inline void ll_remove_outliers(std::vector<VEC_TYPE>& data, F32 k)
|
|||
}
|
||||
}
|
||||
|
||||
// Converts given value from a linear RGB floating point value (0..1) to a gamma corrected (sRGB) value.
|
||||
// Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space.
|
||||
// Note: in our code, values labeled as sRGB are ALWAYS gamma corrected linear values, NOT linear values with monitor gamma applied
|
||||
// Note: stored color values should always be gamma corrected linear (i.e. the values returned from an on-screen color swatch)
|
||||
// Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses
|
||||
inline float linearTosRGB(const float val) {
|
||||
if (val < 0.0031308f) {
|
||||
return val * 12.92f;
|
||||
}
|
||||
else {
|
||||
return 1.055f * pow(val, 1.0f / 2.4f) - 0.055f;
|
||||
}
|
||||
}
|
||||
|
||||
// Converts given value from a gamma corrected (sRGB) floating point value (0..1) to a linear color value.
|
||||
// Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space.
|
||||
// Note: In our code, values labeled as sRGB are gamma corrected linear values, NOT linear values with monitor gamma applied
|
||||
// Note: Stored color values should generally be gamma corrected sRGB.
|
||||
// If you're serializing the return value of this function, you're probably doing it wrong.
|
||||
// Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses.
|
||||
inline float sRGBtoLinear(const float val) {
|
||||
if (val < 0.04045f) {
|
||||
return val / 12.92f;
|
||||
}
|
||||
else {
|
||||
return pow((val + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
}
|
||||
|
||||
// Include simd math header
|
||||
#include "llsimdmath.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,11 @@ LLQuaternion::LLQuaternion(const LLVector3 &x_axis,
|
|||
normalize();
|
||||
}
|
||||
|
||||
LLQuaternion::LLQuaternion(const LLSD &sd)
|
||||
{
|
||||
setValue(sd);
|
||||
}
|
||||
|
||||
// Quatizations
|
||||
void LLQuaternion::quantize16(F32 lower, F32 upper)
|
||||
{
|
||||
|
|
@ -860,6 +865,26 @@ void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const
|
|||
}
|
||||
}
|
||||
|
||||
const LLQuaternion& LLQuaternion::setFromAzimuthAndAltitude(F32 azimuthRadians, F32 altitudeRadians)
|
||||
{
|
||||
// euler angle inputs are complements of azimuth/altitude which are measured from zenith
|
||||
F32 pitch = llclamp(F_PI_BY_TWO - altitudeRadians, 0.0f, F_PI_BY_TWO);
|
||||
F32 yaw = llclamp(F_PI_BY_TWO - azimuthRadians, 0.0f, F_PI_BY_TWO);
|
||||
setEulerAngles(0.0f, pitch, yaw);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void LLQuaternion::getAzimuthAndAltitude(F32 &azimuthRadians, F32 &altitudeRadians)
|
||||
{
|
||||
F32 rick_roll;
|
||||
F32 pitch;
|
||||
F32 yaw;
|
||||
getEulerAngles(&rick_roll, &pitch, &yaw);
|
||||
// make these measured from zenith
|
||||
altitudeRadians = llclamp(F_PI_BY_TWO - pitch, 0.0f, F_PI_BY_TWO);
|
||||
azimuthRadians = llclamp(F_PI_BY_TWO - yaw, 0.0f, F_PI_BY_TWO);
|
||||
}
|
||||
|
||||
// quaternion does not need to be normalized
|
||||
void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#define LLQUATERNION_H
|
||||
|
||||
#include <iostream>
|
||||
#include "llsd.h"
|
||||
|
||||
#ifndef LLMATH_H //enforce specific include order to avoid tangling inline dependencies
|
||||
#error "Please include llmath.h first."
|
||||
|
|
@ -63,6 +64,10 @@ public:
|
|||
LLQuaternion(const LLVector3 &x_axis,
|
||||
const LLVector3 &y_axis,
|
||||
const LLVector3 &z_axis); // Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis]
|
||||
explicit LLQuaternion(const LLSD &sd); // Initializes Quaternion from LLSD array.
|
||||
|
||||
LLSD getValue() const;
|
||||
void setValue(const LLSD& sd);
|
||||
|
||||
BOOL isIdentity() const;
|
||||
BOOL isNotIdentity() const;
|
||||
|
|
@ -79,7 +84,8 @@ public:
|
|||
const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW])
|
||||
const LLQuaternion& set(const LLMatrix3 &mat); // Sets Quaternion to mat2quat(mat)
|
||||
const LLQuaternion& set(const LLMatrix4 &mat); // Sets Quaternion to mat2quat(mat)
|
||||
|
||||
const LLQuaternion& setFromAzimuthAndAltitude(F32 azimuth, F32 altitude);
|
||||
|
||||
const LLQuaternion& setAngleAxis(F32 angle, F32 x, F32 y, F32 z); // Sets Quaternion to axis_angle2quat(angle, x, y, z)
|
||||
const LLQuaternion& setAngleAxis(F32 angle, const LLVector3 &vec); // Sets Quaternion to axis_angle2quat(angle, vec)
|
||||
const LLQuaternion& setAngleAxis(F32 angle, const LLVector4 &vec); // Sets Quaternion to axis_angle2quat(angle, vec)
|
||||
|
|
@ -100,6 +106,7 @@ public:
|
|||
void getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const; // returns rotation in radians about axis x,y,z
|
||||
void getAngleAxis(F32* angle, LLVector3 &vec) const;
|
||||
void getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const;
|
||||
void getAzimuthAndAltitude(F32 &azimuth, F32 &altitude);
|
||||
|
||||
F32 normalize(); // Normalizes Quaternion and returns magnitude
|
||||
F32 normQuat(); // deprecated
|
||||
|
|
@ -166,6 +173,24 @@ public:
|
|||
//static U32 mMultCount;
|
||||
};
|
||||
|
||||
inline LLSD LLQuaternion::getValue() const
|
||||
{
|
||||
LLSD ret;
|
||||
ret[0] = mQ[0];
|
||||
ret[1] = mQ[1];
|
||||
ret[2] = mQ[2];
|
||||
ret[3] = mQ[3];
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline void LLQuaternion::setValue(const LLSD& sd)
|
||||
{
|
||||
mQ[0] = sd[0].asReal();
|
||||
mQ[1] = sd[1].asReal();
|
||||
mQ[2] = sd[2].asReal();
|
||||
mQ[3] = sd[3].asReal();
|
||||
}
|
||||
|
||||
// checker
|
||||
inline BOOL LLQuaternion::isFinite() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2205,7 +2205,6 @@ BOOL LLVolume::generate()
|
|||
{
|
||||
rot_mat.rotate(*profile++, tmp);
|
||||
dst->setAdd(tmp,offset);
|
||||
llassert(dst->isFinite3()); // MAINT-5660; don't know why this happens, does not affect Release builds
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
|
@ -4665,6 +4664,10 @@ LLVolumeFace::LLVolumeFace() :
|
|||
mTexCoords(NULL),
|
||||
mIndices(NULL),
|
||||
mWeights(NULL),
|
||||
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
|
||||
mJustWeights(NULL),
|
||||
mJointIndices(NULL),
|
||||
#endif
|
||||
mWeightsScrubbed(FALSE),
|
||||
mOctree(NULL),
|
||||
mOptimized(FALSE)
|
||||
|
|
@ -4691,6 +4694,10 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
|
|||
mTexCoords(NULL),
|
||||
mIndices(NULL),
|
||||
mWeights(NULL),
|
||||
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
|
||||
mJustWeights(NULL),
|
||||
mJointIndices(NULL),
|
||||
#endif
|
||||
mWeightsScrubbed(FALSE),
|
||||
mOctree(NULL)
|
||||
{
|
||||
|
|
@ -4755,24 +4762,46 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
|
|||
|
||||
if (src.mWeights)
|
||||
{
|
||||
llassert(!mWeights); // don't orphan an old alloc here accidentally
|
||||
allocateWeights(src.mNumVertices);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size);
|
||||
mWeightsScrubbed = src.mWeightsScrubbed;
|
||||
}
|
||||
else
|
||||
{
|
||||
ll_aligned_free_16(mWeights);
|
||||
mWeights = NULL;
|
||||
}
|
||||
mWeightsScrubbed = src.mWeightsScrubbed;
|
||||
}
|
||||
ll_aligned_free_16(mWeights);
|
||||
mWeights = NULL;
|
||||
mWeightsScrubbed = FALSE;
|
||||
}
|
||||
|
||||
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
|
||||
if (src.mJointIndices)
|
||||
{
|
||||
llassert(!mJointIndices); // don't orphan an old alloc here accidentally
|
||||
allocateJointIndices(src.mNumVertices);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mJointIndices, (F32*) src.mJointIndices, src.mNumVertices * sizeof(U8) * 4);
|
||||
}
|
||||
else*/
|
||||
{
|
||||
ll_aligned_free_16(mJointIndices);
|
||||
mJointIndices = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (mNumIndices)
|
||||
{
|
||||
S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF;
|
||||
|
||||
LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ll_aligned_free_16(mIndices);
|
||||
mIndices = NULL;
|
||||
}
|
||||
|
||||
mOptimized = src.mOptimized;
|
||||
|
||||
//delete
|
||||
|
|
@ -4804,6 +4833,13 @@ void LLVolumeFace::freeData()
|
|||
ll_aligned_free_16(mWeights);
|
||||
mWeights = NULL;
|
||||
|
||||
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
|
||||
ll_aligned_free_16(mJointIndices);
|
||||
mJointIndices = NULL;
|
||||
ll_aligned_free_16(mJustWeights);
|
||||
mJustWeights = NULL;
|
||||
#endif
|
||||
|
||||
delete mOctree;
|
||||
mOctree = NULL;
|
||||
}
|
||||
|
|
@ -5457,11 +5493,17 @@ bool LLVolumeFace::cacheOptimize()
|
|||
// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||
ll_aligned_free_16(mWeights);
|
||||
ll_aligned_free_16(mTangents);
|
||||
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
|
||||
ll_aligned_free_16(mJointIndices);
|
||||
ll_aligned_free_16(mJustWeights);
|
||||
mJustWeights = NULL;
|
||||
mJointIndices = NULL; // filled in later as necessary by skinning code for acceleration
|
||||
#endif
|
||||
|
||||
mPositions = pos;
|
||||
mNormals = norm;
|
||||
mTexCoords = tc;
|
||||
mWeights = wght;
|
||||
mWeights = wght;
|
||||
mTangents = binorm;
|
||||
|
||||
//std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
|
||||
|
|
@ -6371,7 +6413,19 @@ void LLVolumeFace::allocateTangents(S32 num_verts)
|
|||
void LLVolumeFace::allocateWeights(S32 num_verts)
|
||||
{
|
||||
ll_aligned_free_16(mWeights);
|
||||
mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||
mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||
|
||||
}
|
||||
|
||||
void LLVolumeFace::allocateJointIndices(S32 num_verts)
|
||||
{
|
||||
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
|
||||
ll_aligned_free_16(mJointIndices);
|
||||
ll_aligned_free_16(mJustWeights);
|
||||
|
||||
mJointIndices = (U8*)ll_aligned_malloc_16(sizeof(U8) * 4 * num_verts);
|
||||
mJustWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * num_verts);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLVolumeFace::resizeIndices(S32 num_indices)
|
||||
|
|
|
|||
|
|
@ -875,6 +875,7 @@ public:
|
|||
void resizeVertices(S32 num_verts);
|
||||
void allocateTangents(S32 num_verts);
|
||||
void allocateWeights(S32 num_verts);
|
||||
void allocateJointIndices(S32 num_verts);
|
||||
void resizeIndices(S32 num_indices);
|
||||
void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
|
||||
|
||||
|
|
@ -956,6 +957,11 @@ public:
|
|||
// mWeights.size() should be empty or match mVertices.size()
|
||||
LLVector4a* mWeights;
|
||||
|
||||
#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
|
||||
LLVector4a* mJustWeights;
|
||||
U8* mJointIndices;
|
||||
#endif
|
||||
|
||||
mutable BOOL mWeightsScrubbed;
|
||||
|
||||
// Which joints are rigged to, and the bounding box of any rigged
|
||||
|
|
|
|||
|
|
@ -75,13 +75,6 @@ LLMatrix3::LLMatrix3(const F32 angle, const LLVector4 &vec)
|
|||
setRot(quat);
|
||||
}
|
||||
|
||||
LLMatrix3::LLMatrix3(const F32 angle, const F32 x, const F32 y, const F32 z)
|
||||
{
|
||||
LLVector3 vec(x, y, z);
|
||||
LLQuaternion quat(angle, vec);
|
||||
setRot(quat);
|
||||
}
|
||||
|
||||
LLMatrix3::LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw)
|
||||
{
|
||||
setRot(roll,pitch,yaw);
|
||||
|
|
@ -294,14 +287,6 @@ LLQuaternion LLMatrix3::quaternion() const
|
|||
return quat;
|
||||
}
|
||||
|
||||
|
||||
// These functions take Rotation arguments
|
||||
const LLMatrix3& LLMatrix3::setRot(const F32 angle, const F32 x, const F32 y, const F32 z)
|
||||
{
|
||||
setRot(LLQuaternion(angle,x,y,z));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const LLMatrix3& LLMatrix3::setRot(const F32 angle, const LLVector3 &vec)
|
||||
{
|
||||
setRot(LLQuaternion(angle, vec));
|
||||
|
|
@ -394,15 +379,6 @@ const LLMatrix3& LLMatrix3::setCol( U32 colIndex, const LLVector3& col )
|
|||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Rotate exisitng mMatrix
|
||||
const LLMatrix3& LLMatrix3::rotate(const F32 angle, const F32 x, const F32 y, const F32 z)
|
||||
{
|
||||
LLMatrix3 mat(angle, x, y, z);
|
||||
*this *= mat;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
const LLMatrix3& LLMatrix3::rotate(const F32 angle, const LLVector3 &vec)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ class LLMatrix3
|
|||
explicit LLMatrix3(const F32 *mat); // Initializes Matrix to values in mat
|
||||
explicit LLMatrix3(const LLQuaternion &q); // Initializes Matrix with rotation q
|
||||
|
||||
LLMatrix3(const F32 angle, const F32 x, const F32 y, const F32 z); // Initializes Matrix with axis angle
|
||||
LLMatrix3(const F32 angle, const LLVector3 &vec); // Initializes Matrix with axis angle
|
||||
LLMatrix3(const F32 angle, const LLVector3d &vec); // Initializes Matrix with axis angle
|
||||
LLMatrix3(const F32 angle, const LLVector4 &vec); // Initializes Matrix with axis angle
|
||||
|
|
@ -81,8 +80,7 @@ class LLMatrix3
|
|||
// Matrix setters - set some properties without modifying others
|
||||
//
|
||||
|
||||
// These functions take Rotation arguments
|
||||
const LLMatrix3& setRot(const F32 angle, const F32 x, const F32 y, const F32 z); // Calculate rotation matrix for rotating angle radians about (x, y, z)
|
||||
// These functions take Rotation arguments
|
||||
const LLMatrix3& setRot(const F32 angle, const LLVector3 &vec); // Calculate rotation matrix for rotating angle radians about vec
|
||||
const LLMatrix3& setRot(const F32 roll, const F32 pitch, const F32 yaw); // Calculate rotation matrix from Euler angles
|
||||
const LLMatrix3& setRot(const LLQuaternion &q); // Transform matrix by Euler angles and translating by pos
|
||||
|
|
|
|||
|
|
@ -384,13 +384,6 @@ void LLMatrix4::initRows(const LLVector4 &row0,
|
|||
}
|
||||
|
||||
|
||||
const LLMatrix4& LLMatrix4::initRotation(const F32 angle, const F32 x, const F32 y, const F32 z)
|
||||
{
|
||||
LLMatrix3 mat(angle, x, y, z);
|
||||
return initMatrix(mat);
|
||||
}
|
||||
|
||||
|
||||
const LLMatrix4& LLMatrix4::initRotation(F32 angle, const LLVector4 &vec)
|
||||
{
|
||||
LLMatrix3 mat(angle, vec);
|
||||
|
|
@ -412,17 +405,6 @@ const LLMatrix4& LLMatrix4::initRotation(const LLQuaternion &q)
|
|||
}
|
||||
|
||||
|
||||
// Position and Rotation
|
||||
const LLMatrix4& LLMatrix4::initRotTrans(const F32 angle, const F32 rx, const F32 ry, const F32 rz,
|
||||
const F32 tx, const F32 ty, const F32 tz)
|
||||
{
|
||||
LLMatrix3 mat(angle, rx, ry, rz);
|
||||
LLVector3 translation(tx, ty, tz);
|
||||
initMatrix(mat);
|
||||
setTranslation(translation);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
const LLMatrix4& LLMatrix4::initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3&translation)
|
||||
{
|
||||
LLMatrix3 mat(angle, axis);
|
||||
|
|
@ -513,15 +495,6 @@ const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion &
|
|||
return (*this);
|
||||
}
|
||||
|
||||
// Rotate exisitng mMatrix
|
||||
const LLMatrix4& LLMatrix4::rotate(const F32 angle, const F32 x, const F32 y, const F32 z)
|
||||
{
|
||||
LLVector4 vec4(x, y, z);
|
||||
LLMatrix4 mat(angle, vec4);
|
||||
*this *= mat;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const LLMatrix4& LLMatrix4::rotate(const F32 angle, const LLVector4 &vec)
|
||||
{
|
||||
LLMatrix4 mat(angle, vec);
|
||||
|
|
|
|||
|
|
@ -137,7 +137,6 @@ public:
|
|||
bool isIdentity() const;
|
||||
const LLMatrix4& setZero(); // Clears matrix to all zeros.
|
||||
|
||||
const LLMatrix4& initRotation(const F32 angle, const F32 x, const F32 y, const F32 z); // Calculate rotation matrix by rotating angle radians about (x, y, z)
|
||||
const LLMatrix4& initRotation(const F32 angle, const LLVector4 &axis); // Calculate rotation matrix for rotating angle radians about vec
|
||||
const LLMatrix4& initRotation(const F32 roll, const F32 pitch, const F32 yaw); // Calculate rotation matrix from Euler angles
|
||||
const LLMatrix4& initRotation(const LLQuaternion &q); // Set with Quaternion and position
|
||||
|
|
@ -148,10 +147,6 @@ public:
|
|||
|
||||
// These operation create a matrix that will rotate and translate by the
|
||||
// specified amounts.
|
||||
const LLMatrix4& initRotTrans(const F32 angle,
|
||||
const F32 rx, const F32 ry, const F32 rz,
|
||||
const F32 px, const F32 py, const F32 pz);
|
||||
|
||||
const LLMatrix4& initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3 &translation); // Rotation from axis angle + translation
|
||||
const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation
|
||||
const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos); // Set with Quaternion and position
|
||||
|
|
@ -211,7 +206,6 @@ public:
|
|||
|
||||
// Rotate existing matrix
|
||||
// These are really, really, inefficient as implemented! - djs
|
||||
const LLMatrix4& rotate(const F32 angle, const F32 x, const F32 y, const F32 z); // Rotate matrix by rotating angle radians about (x, y, z)
|
||||
const LLMatrix4& rotate(const F32 angle, const LLVector4 &vec); // Rotate matrix by rotating angle radians about vec
|
||||
const LLMatrix4& rotate(const F32 roll, const F32 pitch, const F32 yaw); // Rotate matrix by Euler angles
|
||||
const LLMatrix4& rotate(const LLQuaternion &q); // Rotate matrix by Quaternion
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ namespace tut
|
|||
template<> template<>
|
||||
void m3math_test_object_t::test<2>()
|
||||
{
|
||||
LLMatrix3 llmat3_obj(30, 1, 2, 3);
|
||||
LLMatrix3 llmat3_obj;
|
||||
llmat3_obj.setZero();
|
||||
|
||||
ensure("LLMatrix3::setZero failed", 0.f == llmat3_obj.setZero().mMatrix[0][0] &&
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ LLSD LLVector2::getValue() const
|
|||
return ret;
|
||||
}
|
||||
|
||||
void LLVector2::setValue(LLSD& sd)
|
||||
void LLVector2::setValue(const LLSD& sd)
|
||||
{
|
||||
mV[0] = (F32) sd[0].asReal();
|
||||
mV[1] = (F32) sd[1].asReal();
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ class LLVector2
|
|||
LLVector2(F32 x, F32 y); // Initializes LLVector2 to (x. y)
|
||||
LLVector2(const F32 *vec); // Initializes LLVector2 to (vec[0]. vec[1])
|
||||
explicit LLVector2(const LLVector3 &vec); // Initializes LLVector2 to (vec[0]. vec[1])
|
||||
explicit LLVector2(const LLSD &sd);
|
||||
|
||||
// Clears LLVector2 to (0, 0). DEPRECATED - prefer zeroVec.
|
||||
void clear();
|
||||
|
|
@ -61,7 +62,7 @@ class LLVector2
|
|||
void set(const F32 *vec); // Sets LLVector2 to vec
|
||||
|
||||
LLSD getValue() const;
|
||||
void setValue(LLSD& sd);
|
||||
void setValue(const LLSD& sd);
|
||||
|
||||
void setVec(F32 x, F32 y); // deprecated
|
||||
void setVec(const LLVector2 &vec); // deprecated
|
||||
|
|
@ -145,6 +146,10 @@ inline LLVector2::LLVector2(const LLVector3 &vec)
|
|||
mV[VY] = vec.mV[VY];
|
||||
}
|
||||
|
||||
inline LLVector2::LLVector2(const LLSD &sd)
|
||||
{
|
||||
setValue(sd);
|
||||
}
|
||||
|
||||
// Clear and Assignment Functions
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,23 @@ public:
|
|||
|
||||
const LLColor3& operator=(const LLColor4 &a);
|
||||
|
||||
LL_FORCE_INLINE LLColor3 divide(const LLColor3 &col2)
|
||||
{
|
||||
return LLColor3(
|
||||
mV[0] / col2.mV[0],
|
||||
mV[1] / col2.mV[1],
|
||||
mV[2] / col2.mV[2] );
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE LLColor3 color_norm()
|
||||
{
|
||||
F32 l = length();
|
||||
return LLColor3(
|
||||
mV[0] / l,
|
||||
mV[1] / l,
|
||||
mV[2] / l );
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const LLColor3 &a); // Print a
|
||||
friend LLColor3 operator+(const LLColor3 &a, const LLColor3 &b); // Return vector a + b
|
||||
friend LLColor3 operator-(const LLColor3 &a, const LLColor3 &b); // Return vector a minus b
|
||||
|
|
@ -458,5 +475,22 @@ inline LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u)
|
|||
a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u);
|
||||
}
|
||||
|
||||
inline const LLColor3 srgbColor3(const LLColor3 &a) {
|
||||
LLColor3 srgbColor;
|
||||
srgbColor.mV[0] = linearTosRGB(a.mV[0]);
|
||||
srgbColor.mV[1] = linearTosRGB(a.mV[1]);
|
||||
srgbColor.mV[2] = linearTosRGB(a.mV[2]);
|
||||
|
||||
return srgbColor;
|
||||
}
|
||||
|
||||
inline const LLColor3 linearColor3(const LLColor3 &a) {
|
||||
LLColor3 linearColor;
|
||||
linearColor.mV[0] = sRGBtoLinear(a.mV[0]);
|
||||
linearColor.mV[1] = sRGBtoLinear(a.mV[1]);
|
||||
linearColor.mV[2] = sRGBtoLinear(a.mV[2]);
|
||||
|
||||
return linearColor;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* @file v3color.h
|
||||
* @brief LLColor3 class header file.
|
||||
*
|
||||
* $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_V3COLORUTIL_H
|
||||
#define LL_V3COLORUTIL_H
|
||||
|
||||
#include "v3color.h"
|
||||
|
||||
inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right)
|
||||
{
|
||||
return LLColor3(left.mV[0] / right.mV[0],
|
||||
left.mV[1] / right.mV[1],
|
||||
left.mV[2] / right.mV[2]);
|
||||
}
|
||||
|
||||
|
||||
inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right)
|
||||
{
|
||||
return LLColor3(left.mV[0] * right.mV[0],
|
||||
left.mV[1] * right.mV[1],
|
||||
left.mV[2] * right.mV[2]);
|
||||
}
|
||||
|
||||
|
||||
inline LLColor3 componentExp(LLColor3 const &v)
|
||||
{
|
||||
return LLColor3(exp(v.mV[0]),
|
||||
exp(v.mV[1]),
|
||||
exp(v.mV[2]));
|
||||
}
|
||||
|
||||
inline LLColor3 componentPow(LLColor3 const &v, F32 exponent)
|
||||
{
|
||||
return LLColor3(pow(v.mV[0], exponent),
|
||||
pow(v.mV[1], exponent),
|
||||
pow(v.mV[2], exponent));
|
||||
}
|
||||
|
||||
inline LLColor3 componentSaturate(LLColor3 const &v)
|
||||
{
|
||||
return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f),
|
||||
std::max(std::min(v.mV[1], 1.f), 0.f),
|
||||
std::max(std::min(v.mV[2], 1.f), 0.f));
|
||||
}
|
||||
|
||||
|
||||
inline LLColor3 componentSqrt(LLColor3 const &v)
|
||||
{
|
||||
return LLColor3(sqrt(v.mV[0]),
|
||||
sqrt(v.mV[1]),
|
||||
sqrt(v.mV[2]));
|
||||
}
|
||||
|
||||
inline void componentMultBy(LLColor3 & left, LLColor3 const & right)
|
||||
{
|
||||
left.mV[0] *= right.mV[0];
|
||||
left.mV[1] *= right.mV[1];
|
||||
left.mV[2] *= right.mV[2];
|
||||
}
|
||||
|
||||
inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount)
|
||||
{
|
||||
return (left + ((right - left) * amount));
|
||||
}
|
||||
|
||||
inline LLColor3 smear(F32 val)
|
||||
{
|
||||
return LLColor3(val, val, val);
|
||||
}
|
||||
|
||||
inline F32 color_intens(const LLColor3 &col)
|
||||
{
|
||||
return col.mV[0] + col.mV[1] + col.mV[2];
|
||||
}
|
||||
|
||||
inline F32 color_max(const LLColor3 &col)
|
||||
{
|
||||
return llmax(col.mV[0], col.mV[1], col.mV[2]);
|
||||
}
|
||||
|
||||
inline F32 color_max(const LLColor4 &col)
|
||||
{
|
||||
return llmax(col.mV[0], col.mV[1], col.mV[2]);
|
||||
}
|
||||
|
||||
|
||||
inline F32 color_min(const LLColor3 &col)
|
||||
{
|
||||
return llmin(col.mV[0], col.mV[1], col.mV[2]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -114,9 +114,11 @@ class LLColor4
|
|||
friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b
|
||||
friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b); // Return component wise a * b
|
||||
friend LLColor4 operator*(const LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change)
|
||||
friend LLColor4 operator/(const LLColor4 &a, F32 k); // Return rgb divided by scalar k (no alpha change)
|
||||
friend LLColor4 operator*(F32 k, const LLColor4 &a); // Return rgb times scaler k (no alpha change)
|
||||
friend LLColor4 operator%(const LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change)
|
||||
friend LLColor4 operator%(F32 k, const LLColor4 &a); // Return alpha times scaler k (no rgb change)
|
||||
|
||||
friend bool operator==(const LLColor4 &a, const LLColor4 &b); // Return a == b
|
||||
friend bool operator!=(const LLColor4 &a, const LLColor4 &b); // Return a != b
|
||||
|
||||
|
|
@ -477,6 +479,15 @@ inline LLColor4 operator*(const LLColor4 &a, F32 k)
|
|||
a.mV[VW]);
|
||||
}
|
||||
|
||||
inline LLColor4 operator/(const LLColor4 &a, F32 k)
|
||||
{
|
||||
return LLColor4(
|
||||
a.mV[VX] / k,
|
||||
a.mV[VY] / k,
|
||||
a.mV[VZ] / k,
|
||||
a.mV[VW]);
|
||||
}
|
||||
|
||||
inline LLColor4 operator*(F32 k, const LLColor4 &a)
|
||||
{
|
||||
// only affects rgb (not a!)
|
||||
|
|
@ -645,5 +656,29 @@ void LLColor4::clamp()
|
|||
}
|
||||
}
|
||||
|
||||
// Return the given linear space color value in gamma corrected (sRGB) space
|
||||
inline const LLColor4 srgbColor4(const LLColor4 &a) {
|
||||
LLColor4 srgbColor;
|
||||
|
||||
srgbColor.mV[0] = linearTosRGB(a.mV[0]);
|
||||
srgbColor.mV[1] = linearTosRGB(a.mV[1]);
|
||||
srgbColor.mV[2] = linearTosRGB(a.mV[2]);
|
||||
srgbColor.mV[3] = a.mV[3];
|
||||
|
||||
return srgbColor;
|
||||
}
|
||||
|
||||
// Return the given gamma corrected (sRGB) color in linear space
|
||||
inline const LLColor4 linearColor4(const LLColor4 &a)
|
||||
{
|
||||
LLColor4 linearColor;
|
||||
linearColor.mV[0] = sRGBtoLinear(a.mV[0]);
|
||||
linearColor.mV[1] = sRGBtoLinear(a.mV[1]);
|
||||
linearColor.mV[2] = sRGBtoLinear(a.mV[2]);
|
||||
linearColor.mV[3] = a.mV[3];
|
||||
|
||||
return linearColor;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "llerror.h"
|
||||
#include "llmath.h"
|
||||
#include "v3math.h"
|
||||
#include "v2math.h"
|
||||
|
||||
class LLMatrix3;
|
||||
class LLMatrix4;
|
||||
|
|
@ -46,8 +47,11 @@ class LLVector4
|
|||
LLVector4(); // Initializes LLVector4 to (0, 0, 0, 1)
|
||||
explicit LLVector4(const F32 *vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2], vec[3])
|
||||
explicit LLVector4(const F64 *vec); // Initialized LLVector4 to ((F32) vec[0], (F32) vec[1], (F32) vec[3], (F32) vec[4]);
|
||||
explicit LLVector4(const LLVector2 &vec);
|
||||
explicit LLVector4(const LLVector2 &vec, F32 z, F32 w);
|
||||
explicit LLVector4(const LLVector3 &vec); // Initializes LLVector4 to (vec, 1)
|
||||
explicit LLVector4(const LLVector3 &vec, F32 w); // Initializes LLVector4 to (vec, w)
|
||||
explicit LLVector4(const LLSD &sd);
|
||||
LLVector4(F32 x, F32 y, F32 z); // Initializes LLVector4 to (x. y, z, 1)
|
||||
LLVector4(F32 x, F32 y, F32 z, F32 w);
|
||||
|
||||
|
|
@ -61,6 +65,15 @@ class LLVector4
|
|||
return ret;
|
||||
}
|
||||
|
||||
void setValue(const LLSD& sd)
|
||||
{
|
||||
mV[0] = sd[0].asReal();
|
||||
mV[1] = sd[1].asReal();
|
||||
mV[2] = sd[2].asReal();
|
||||
mV[3] = sd[3].asReal();
|
||||
}
|
||||
|
||||
|
||||
inline BOOL isFinite() const; // checks to see if all values of LLVector3 are finite
|
||||
|
||||
inline void clear(); // Clears LLVector4 to (0, 0, 0, 1)
|
||||
|
|
@ -175,6 +188,22 @@ inline LLVector4::LLVector4(const F64 *vec)
|
|||
mV[VW] = (F32) vec[VW];
|
||||
}
|
||||
|
||||
inline LLVector4::LLVector4(const LLVector2 &vec)
|
||||
{
|
||||
mV[VX] = vec[VX];
|
||||
mV[VY] = vec[VY];
|
||||
mV[VZ] = 0.f;
|
||||
mV[VW] = 0.f;
|
||||
}
|
||||
|
||||
inline LLVector4::LLVector4(const LLVector2 &vec, F32 z, F32 w)
|
||||
{
|
||||
mV[VX] = vec[VX];
|
||||
mV[VY] = vec[VY];
|
||||
mV[VZ] = z;
|
||||
mV[VW] = w;
|
||||
}
|
||||
|
||||
inline LLVector4::LLVector4(const LLVector3 &vec)
|
||||
{
|
||||
mV[VX] = vec.mV[VX];
|
||||
|
|
@ -191,6 +220,11 @@ inline LLVector4::LLVector4(const LLVector3 &vec, F32 w)
|
|||
mV[VW] = w;
|
||||
}
|
||||
|
||||
inline LLVector4::LLVector4(const LLSD &sd)
|
||||
{
|
||||
setValue(sd);
|
||||
}
|
||||
|
||||
|
||||
inline BOOL LLVector4::isFinite() const
|
||||
{
|
||||
|
|
@ -500,6 +534,18 @@ inline F32 LLVector4::normVec(void)
|
|||
return (mag);
|
||||
}
|
||||
|
||||
// Because apparently some parts of the viewer use this for color info.
|
||||
inline const LLVector4 srgbVector4(const LLVector4 &a) {
|
||||
LLVector4 srgbColor;
|
||||
|
||||
srgbColor.mV[0] = linearTosRGB(a.mV[0]);
|
||||
srgbColor.mV[1] = linearTosRGB(a.mV[1]);
|
||||
srgbColor.mV[2] = linearTosRGB(a.mV[2]);
|
||||
srgbColor.mV[3] = a.mV[3];
|
||||
|
||||
return srgbColor;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,42 @@ const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-0
|
|||
|
||||
const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds
|
||||
|
||||
namespace
|
||||
{
|
||||
bool operator == (const LLAssetStorage::LLGetAssetCallback &lhs, const LLAssetStorage::LLGetAssetCallback &rhs)
|
||||
{
|
||||
auto fnPtrLhs = lhs.target<LLAssetStorage::LLGetAssetCallback>();
|
||||
auto fnPtrRhs = rhs.target<LLAssetStorage::LLGetAssetCallback>();
|
||||
if (fnPtrLhs && fnPtrRhs)
|
||||
return (*fnPtrLhs == *fnPtrRhs);
|
||||
else if (!fnPtrLhs && !fnPtrRhs)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rider: This is the general case of the operator declared above. The code compares the callback
|
||||
// passed into the LLAssetStorage functions to determine if there are duplicated requests for an
|
||||
// asset. Unfortunately std::function does not provide a direct way to compare two variables so
|
||||
// we define the operator here.
|
||||
// XCode is not very happy with the variadic temples in use below so we will just define the specific
|
||||
// case of comparing two LLGetAssetCallback objects since that is all we really use.
|
||||
//
|
||||
// template<typename T, typename... U>
|
||||
// bool operator == (const std::function<T(U...)> &a, const std::function <T(U...)> &b)
|
||||
// {
|
||||
// typedef T(fnType)(U...);
|
||||
//
|
||||
// auto fnPtrA = a.target<T(*)(U...)>();
|
||||
// auto fnPtrB = b.target<T(*)(U...)>();
|
||||
// if (fnPtrA && fnPtrB)
|
||||
// return (*fnPtrA == *fnPtrB);
|
||||
// else if (!fnPtrA && !fnPtrB)
|
||||
// return true;
|
||||
// return false;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// LLAssetInfo
|
||||
///----------------------------------------------------------------------------
|
||||
|
|
@ -160,7 +196,7 @@ void LLAssetInfo::setFromNameValue( const LLNameValue& nv )
|
|||
LLBaseDownloadRequest::LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType type)
|
||||
: mUUID(uuid),
|
||||
mType(type),
|
||||
mDownCallback(NULL),
|
||||
mDownCallback(),
|
||||
mUserData(NULL),
|
||||
mHost(),
|
||||
mIsTemp(FALSE),
|
||||
|
|
@ -191,7 +227,7 @@ LLBaseDownloadRequest* LLBaseDownloadRequest::getCopy()
|
|||
|
||||
LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
|
||||
: LLBaseDownloadRequest(uuid, type),
|
||||
mUpCallback( NULL ),
|
||||
mUpCallback(),
|
||||
mInfoCallback( NULL ),
|
||||
mIsLocal(FALSE),
|
||||
mIsUserWaiting(FALSE),
|
||||
|
|
@ -449,7 +485,7 @@ bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAsse
|
|||
// IW - uuid is passed by value to avoid side effects, please don't re-add &
|
||||
void LLAssetStorage::getAssetData(const LLUUID uuid,
|
||||
LLAssetType::EType type,
|
||||
LLGetAssetCallback callback,
|
||||
LLAssetStorage::LLGetAssetCallback callback,
|
||||
void *user_data,
|
||||
BOOL is_priority)
|
||||
{
|
||||
|
|
@ -496,7 +532,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
|
|||
BOOL exists = mVFS->getExists(uuid, type);
|
||||
LLVFile file(mVFS, uuid, type);
|
||||
U32 size = exists ? file.getSize() : 0;
|
||||
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
// we've already got the file
|
||||
|
|
@ -1326,9 +1362,13 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
|
|||
iter != mPendingDownloads.end(); )
|
||||
{
|
||||
LLAssetRequest* tmp = *iter++;
|
||||
|
||||
//void(*const* cbptr)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat)
|
||||
auto cbptr = tmp->mDownCallback.target<void(*)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat)>();
|
||||
|
||||
if (type == tmp->getType() &&
|
||||
uuid == tmp->getUUID() &&
|
||||
legacyGetDataCallback == tmp->mDownCallback &&
|
||||
(cbptr && (*cbptr == legacyGetDataCallback)) &&
|
||||
callback == ((LLLegacyAssetRequest *)tmp->mUserData)->mDownCallback &&
|
||||
user_data == ((LLLegacyAssetRequest *)tmp->mUserData)->mUserData)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#ifndef LL_LLASSETSTORAGE_H
|
||||
#define LL_LLASSETSTORAGE_H
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#include "lluuid.h"
|
||||
#include "lltimer.h"
|
||||
|
|
@ -59,6 +60,14 @@ const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
|
|||
const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
|
||||
const int LL_ERR_PRICE_MISMATCH = -23018;
|
||||
|
||||
// *TODO: these typedefs are passed into the VFS via a legacy C function pointer
|
||||
// future project would be to convert these to C++ callables (std::function<>) so that
|
||||
// we can use bind and remove the userData parameter.
|
||||
//
|
||||
typedef std::function<void(LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)> LLGetAssetCallback;
|
||||
typedef std::function<void(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status)> LLStoreAssetCallback;
|
||||
|
||||
|
||||
class LLAssetInfo
|
||||
{
|
||||
protected:
|
||||
|
|
@ -110,7 +119,8 @@ protected:
|
|||
LLAssetType::EType mType;
|
||||
|
||||
public:
|
||||
void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
|
||||
LLGetAssetCallback mDownCallback;
|
||||
// void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
|
||||
|
||||
void *mUserData;
|
||||
LLHost mHost;
|
||||
|
|
@ -131,7 +141,8 @@ public:
|
|||
|
||||
virtual LLBaseDownloadRequest* getCopy();
|
||||
|
||||
void (*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
|
||||
LLStoreAssetCallback mUpCallback;
|
||||
// void (*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
|
||||
void (*mInfoCallback)(LLAssetInfo *, void *, S32);
|
||||
|
||||
BOOL mIsLocal;
|
||||
|
|
@ -182,12 +193,7 @@ protected:
|
|||
// Map of known bad assets
|
||||
typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
|
||||
|
||||
// *TODO: these typedefs are passed into the VFS via a legacy C function pointer
|
||||
// future project would be to convert these to C++ callables (std::function<>) so that
|
||||
// we can use bind and remove the userData parameter.
|
||||
//
|
||||
typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id,
|
||||
LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
|
||||
|
||||
|
||||
class LLAssetStorage
|
||||
{
|
||||
|
|
@ -195,7 +201,8 @@ public:
|
|||
// VFS member is public because static child methods need it :(
|
||||
LLVFS *mVFS;
|
||||
LLVFS *mStaticVFS;
|
||||
typedef void (*LLStoreAssetCallback)(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status);
|
||||
typedef ::LLStoreAssetCallback LLStoreAssetCallback;
|
||||
typedef ::LLGetAssetCallback LLGetAssetCallback;
|
||||
|
||||
enum ERequestType
|
||||
{
|
||||
|
|
@ -377,8 +384,8 @@ protected:
|
|||
void _cleanupRequests(BOOL all, S32 error);
|
||||
void _callUploadCallbacks(const LLUUID &uuid, const LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status);
|
||||
|
||||
virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type,
|
||||
void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
|
||||
virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback,
|
||||
// void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
|
||||
void *user_data, BOOL duplicate,
|
||||
BOOL is_priority) = 0;
|
||||
|
||||
|
|
@ -424,7 +431,7 @@ class LLLegacyAssetRequest
|
|||
{
|
||||
public:
|
||||
void (*mDownCallback)(const char *, const LLUUID&, void *, S32, LLExtStat);
|
||||
LLAssetStorage::LLStoreAssetCallback mUpCallback;
|
||||
LLStoreAssetCallback mUpCallback;
|
||||
|
||||
void *mUserData;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ void LLCircuitData::checkPeriodTime()
|
|||
mBytesOutLastPeriod = mBytesOutThisPeriod;
|
||||
mBytesInThisPeriod = S32Bytes(0);
|
||||
mBytesOutThisPeriod = S32Bytes(0);
|
||||
mLastPeriodLength = period_length;
|
||||
mLastPeriodLength = F32Seconds::convert(period_length);
|
||||
|
||||
mPeriodTime = mt_sec;
|
||||
}
|
||||
|
|
@ -1378,8 +1378,8 @@ F32Milliseconds LLCircuitData::getPingInTransitTime()
|
|||
|
||||
if (mPingsInTransit)
|
||||
{
|
||||
time_since_ping_was_sent = ((mPingsInTransit*mHeartbeatInterval - F32Seconds(1))
|
||||
+ (LLMessageSystem::getMessageTimeSeconds() - mPingTime));
|
||||
time_since_ping_was_sent = F32Milliseconds::convert(((mPingsInTransit*mHeartbeatInterval - F32Seconds(1))
|
||||
+ (LLMessageSystem::getMessageTimeSeconds() - mPingTime)));
|
||||
}
|
||||
|
||||
return time_since_ping_was_sent;
|
||||
|
|
|
|||
|
|
@ -101,48 +101,70 @@ LLDispatchHandler* LLDispatcher::addHandler(
|
|||
|
||||
// static
|
||||
bool LLDispatcher::unpackMessage(
|
||||
LLMessageSystem* msg,
|
||||
LLDispatcher::key_t& method,
|
||||
LLUUID& invoice,
|
||||
LLDispatcher::sparam_t& parameters)
|
||||
LLMessageSystem* msg,
|
||||
LLDispatcher::key_t& method,
|
||||
LLUUID& invoice,
|
||||
LLDispatcher::sparam_t& parameters)
|
||||
{
|
||||
char buf[MAX_STRING]; /*Flawfinder: ignore*/
|
||||
msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
|
||||
msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
|
||||
S32 size;
|
||||
S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
|
||||
for (S32 i = 0; i < count; ++i)
|
||||
{
|
||||
// we treat the SParam as binary data (since it might be an
|
||||
// LLUUID in compressed form which may have embedded \0's,)
|
||||
size = msg->getSizeFast(_PREHASH_ParamList, i, _PREHASH_Parameter);
|
||||
if (size >= 0)
|
||||
{
|
||||
msg->getBinaryDataFast(
|
||||
_PREHASH_ParamList, _PREHASH_Parameter,
|
||||
buf, size, i, MAX_STRING-1);
|
||||
char buf[MAX_STRING]; /*Flawfinder: ignore*/
|
||||
msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
|
||||
msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
|
||||
S32 size;
|
||||
S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
|
||||
for (S32 i = 0; i < count; ++i)
|
||||
{
|
||||
// we treat the SParam as binary data (since it might be an
|
||||
// LLUUID in compressed form which may have embedded \0's,)
|
||||
size = msg->getSizeFast(_PREHASH_ParamList, i, _PREHASH_Parameter);
|
||||
if (size >= 0)
|
||||
{
|
||||
msg->getBinaryDataFast(
|
||||
_PREHASH_ParamList, _PREHASH_Parameter,
|
||||
buf, size, i, MAX_STRING - 1);
|
||||
|
||||
// If the last byte of the data is 0x0, this is either a normally
|
||||
// packed string, or a binary packed UUID (which for these messages
|
||||
// are packed with a 17th byte 0x0). Unpack into a std::string
|
||||
// without the trailing \0, so "abc\0" becomes std::string("abc", 3)
|
||||
// which matches const char* "abc".
|
||||
if (size > 0
|
||||
&& buf[size-1] == 0x0)
|
||||
{
|
||||
// special char*/size constructor because UUIDs may have embedded
|
||||
// 0x0 bytes.
|
||||
std::string binary_data(buf, size-1);
|
||||
parameters.push_back(binary_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is either a NULL string, or a string that was packed
|
||||
// incorrectly as binary data, without the usual trailing '\0'.
|
||||
std::string string_data(buf, size);
|
||||
parameters.push_back(string_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
// If the last byte of the data is 0x0, this is either a normally
|
||||
// packed string, or a binary packed UUID (which for these messages
|
||||
// are packed with a 17th byte 0x0). Unpack into a std::string
|
||||
// without the trailing \0, so "abc\0" becomes std::string("abc", 3)
|
||||
// which matches const char* "abc".
|
||||
if (size > 0
|
||||
&& buf[size - 1] == 0x0)
|
||||
{
|
||||
// special char*/size constructor because UUIDs may have embedded
|
||||
// 0x0 bytes.
|
||||
std::string binary_data(buf, size - 1);
|
||||
parameters.push_back(binary_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is either a NULL string, or a string that was packed
|
||||
// incorrectly as binary data, without the usual trailing '\0'.
|
||||
std::string string_data(buf, size);
|
||||
parameters.push_back(string_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLDispatcher::unpackLargeMessage(
|
||||
LLMessageSystem* msg,
|
||||
LLDispatcher::key_t& method,
|
||||
LLUUID& invoice,
|
||||
LLDispatcher::sparam_t& parameters)
|
||||
{
|
||||
msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
|
||||
msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
|
||||
S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
|
||||
for (S32 i = 0; i < count; ++i)
|
||||
{
|
||||
// This method treats all Parameter List params as strings and unpacks
|
||||
// them regardless of length. If there is binary data it is the callers
|
||||
// responsibility to decode it.
|
||||
std::string param;
|
||||
msg->getStringFast(_PREHASH_ParamList, _PREHASH_Parameter, param, i);
|
||||
parameters.push_back(param);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,12 @@ public:
|
|||
LLUUID& invoice,
|
||||
sparam_t& parameters);
|
||||
|
||||
static bool unpackLargeMessage(
|
||||
LLMessageSystem* msg,
|
||||
key_t& method,
|
||||
LLUUID& invoice,
|
||||
sparam_t& parameters);
|
||||
|
||||
protected:
|
||||
typedef std::map<key_t, LLDispatchHandler*> dispatch_map_t;
|
||||
dispatch_map_t mHandlers;
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ const U64 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7);
|
|||
|
||||
// All content wiped once per night
|
||||
const U64 REGION_FLAGS_SANDBOX = (1 << 8);
|
||||
|
||||
const U64 REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE = (1 << 9);
|
||||
|
||||
const U64 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies
|
||||
const U64 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13);
|
||||
const U64 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics
|
||||
|
|
|
|||
|
|
@ -1376,7 +1376,9 @@ char const* const _PREHASH_RegionDenyAgeUnverified = LLMessageStringTable::getIn
|
|||
char const* const _PREHASH_AgeVerificationBlock = LLMessageStringTable::getInstance()->getString("AgeVerificationBlock");
|
||||
char const* const _PREHASH_RegionAllowAccessBlock = LLMessageStringTable::getInstance()->getString("RegionAllowAccessBlock");
|
||||
char const* const _PREHASH_RegionAllowAccessOverride = LLMessageStringTable::getInstance()->getString("RegionAllowAccessOverride");
|
||||
|
||||
char const* const _PREHASH_ParcelEnvironmentBlock = LLMessageStringTable::getInstance()->getString("ParcelEnvironmentBlock");
|
||||
char const* const _PREHASH_ParcelEnvironmentVersion = LLMessageStringTable::getInstance()->getString("ParcelEnvironmentVersion");
|
||||
char const* const _PREHASH_RegionAllowEnvironmentOverride = LLMessageStringTable::getInstance()->getString("RegionAllowEnvironmentOverride");
|
||||
char const* const _PREHASH_UCoord = LLMessageStringTable::getInstance()->getString("UCoord");
|
||||
char const* const _PREHASH_VCoord = LLMessageStringTable::getInstance()->getString("VCoord");
|
||||
char const* const _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex");
|
||||
|
|
@ -1392,3 +1394,4 @@ char const* const _PREHASH_AppearanceHover = LLMessageStringTable::getInstance()
|
|||
char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->getString("HoverHeight");
|
||||
char const* const _PREHASH_Experience = LLMessageStringTable::getInstance()->getString("Experience");
|
||||
char const* const _PREHASH_ExperienceID = LLMessageStringTable::getInstance()->getString("ExperienceID");
|
||||
char const* const _PREHASH_LargeGenericMessage = LLMessageStringTable::getInstance()->getString("LargeGenericMessage");
|
||||
|
|
|
|||
|
|
@ -1376,6 +1376,9 @@ extern char const* const _PREHASH_RegionDenyAgeUnverified;
|
|||
extern char const* const _PREHASH_AgeVerificationBlock;
|
||||
extern char const* const _PREHASH_RegionAllowAccessBlock;
|
||||
extern char const* const _PREHASH_RegionAllowAccessOverride;
|
||||
extern char const* const _PREHASH_ParcelEnvironmentBlock;
|
||||
extern char const* const _PREHASH_ParcelEnvironmentVersion;
|
||||
extern char const* const _PREHASH_RegionAllowEnvironmentOverride;
|
||||
extern char const* const _PREHASH_UCoord;
|
||||
extern char const* const _PREHASH_VCoord;
|
||||
extern char const* const _PREHASH_FaceIndex;
|
||||
|
|
@ -1391,4 +1394,6 @@ extern char const* const _PREHASH_AppearanceHover;
|
|||
extern char const* const _PREHASH_HoverHeight;
|
||||
extern char const* const _PREHASH_Experience;
|
||||
extern char const* const _PREHASH_ExperienceID;
|
||||
extern char const* const _PREHASH_LargeGenericMessage;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ void LLPluginProcessChild::sleep(F64 seconds)
|
|||
}
|
||||
else
|
||||
{
|
||||
ms_sleep((int)(seconds * 1000.0f));
|
||||
ms_sleep((int)(seconds * 1000.0f));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1784,7 +1784,7 @@ void LLDAELoader::extractTranslationViaElement( daeElement* pTranslateElement, L
|
|||
{
|
||||
if ( pTranslateElement )
|
||||
{
|
||||
domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
|
||||
domTranslate* pTranslateChild = static_cast<domTranslate*>( pTranslateElement );
|
||||
domFloat3 translateChild = pTranslateChild->getValue();
|
||||
LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
|
||||
transform.setTranslation( singleJointTranslation );
|
||||
|
|
|
|||
|
|
@ -1659,7 +1659,7 @@ BOOL LLLightParams::unpack(LLDataPacker &dp)
|
|||
{
|
||||
LLColor4U color;
|
||||
dp.unpackColor4U(color, "color");
|
||||
setColor(LLColor4(color));
|
||||
setLinearColor(LLColor4(color));
|
||||
|
||||
F32 radius;
|
||||
dp.unpackF32(radius, "radius");
|
||||
|
|
@ -1707,7 +1707,7 @@ LLSD LLLightParams::asLLSD() const
|
|||
{
|
||||
LLSD sd;
|
||||
|
||||
sd["color"] = ll_sd_from_color4(getColor());
|
||||
sd["color"] = ll_sd_from_color4(getLinearColor());
|
||||
sd["radius"] = getRadius();
|
||||
sd["falloff"] = getFalloff();
|
||||
sd["cutoff"] = getCutoff();
|
||||
|
|
@ -1721,7 +1721,7 @@ bool LLLightParams::fromLLSD(LLSD& sd)
|
|||
w = "color";
|
||||
if (sd.has(w))
|
||||
{
|
||||
setColor( ll_color4_from_sd(sd["color"]) );
|
||||
setLinearColor( ll_color4_from_sd(sd["color"]) );
|
||||
} else goto fail;
|
||||
w = "radius";
|
||||
if (sd.has(w))
|
||||
|
|
|
|||
|
|
@ -131,8 +131,8 @@ extern const F32 LIGHT_MAX_CUTOFF;
|
|||
|
||||
class LLLightParams : public LLNetworkData
|
||||
{
|
||||
protected:
|
||||
LLColor4 mColor; // alpha = intensity
|
||||
private:
|
||||
LLColor4 mColor; // linear color (not gamma corrected), alpha = intensity
|
||||
F32 mRadius;
|
||||
F32 mFalloff;
|
||||
F32 mCutoff;
|
||||
|
|
@ -149,13 +149,22 @@ public:
|
|||
operator LLSD() const { return asLLSD(); }
|
||||
bool fromLLSD(LLSD& sd);
|
||||
|
||||
|
||||
void setColor(const LLColor4& color) { mColor = color; mColor.clamp(); }
|
||||
// set the color by gamma corrected color value
|
||||
// color - gamma corrected color value (directly taken from an on-screen color swatch)
|
||||
void setSRGBColor(const LLColor4& color) { setLinearColor(linearColor4(color)); }
|
||||
|
||||
// set the color by linear color value
|
||||
// color - linear color value (value as it appears in shaders)
|
||||
void setLinearColor(const LLColor4& color) { mColor = color; mColor.clamp(); }
|
||||
void setRadius(F32 radius) { mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); }
|
||||
void setFalloff(F32 falloff) { mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); }
|
||||
void setCutoff(F32 cutoff) { mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); }
|
||||
|
||||
LLColor4 getColor() const { return mColor; }
|
||||
// get the linear space color of this light. This value can be fed directly to shaders
|
||||
LLColor4 getLinearColor() const { return mColor; }
|
||||
// get the sRGB (gamma corrected) color of this light, this is the value that should be displayed in the UI
|
||||
LLColor4 getSRGBColor() const { return srgbColor4(mColor); }
|
||||
|
||||
F32 getRadius() const { return mRadius; }
|
||||
F32 getFalloff() const { return mFalloff; }
|
||||
F32 getCutoff() const { return mCutoff; }
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ include_directories(SYSTEM
|
|||
)
|
||||
|
||||
set(llrender_SOURCE_FILES
|
||||
llatmosphere.cpp
|
||||
llcubemap.cpp
|
||||
llfontbitmapcache.cpp
|
||||
llfontfreetype.cpp
|
||||
|
|
@ -57,6 +58,7 @@ set(llrender_SOURCE_FILES
|
|||
set(llrender_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
llatmosphere.h
|
||||
llcubemap.h
|
||||
llfontgl.h
|
||||
llfontfreetype.h
|
||||
|
|
@ -78,6 +80,7 @@ set(llrender_HEADER_FILES
|
|||
llshadermgr.h
|
||||
lltexture.h
|
||||
lluiimage.h
|
||||
lluiimage.inl
|
||||
llvertexbuffer.h
|
||||
llglcommonfunc.h
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,290 @@
|
|||
/**
|
||||
* @file llatmosphere.cpp
|
||||
* @brief LLAtmosphere integration impl
|
||||
*
|
||||
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2018, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llatmosphere.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "llsys.h"
|
||||
#include "llglheaders.h"
|
||||
#include "llrender.h"
|
||||
#include "llshadermgr.h"
|
||||
#include "llglslshader.h"
|
||||
|
||||
LLAtmosphere* gAtmosphere = nullptr;
|
||||
|
||||
// Values from "Reference Solar Spectral Irradiance: ASTM G-173", ETR column
|
||||
// (see http://rredc.nrel.gov/solar/spectra/am1.5/ASTMG173/ASTMG173.html),
|
||||
// summed and averaged in each bin (e.g. the value for 360nm is the average
|
||||
// of the ASTM G-173 values for all wavelengths between 360 and 370nm).
|
||||
// Values in W.m^-2.
|
||||
const int kLambdaMin = 360;
|
||||
const int kLambdaMax = 830;
|
||||
const double kSolarIrradiance[48] = {
|
||||
1.11776, 1.14259, 1.01249, 1.14716, 1.72765, 1.73054, 1.6887, 1.61253,
|
||||
1.91198, 2.03474, 2.02042, 2.02212, 1.93377, 1.95809, 1.91686, 1.8298,
|
||||
1.8685, 1.8931, 1.85149, 1.8504, 1.8341, 1.8345, 1.8147, 1.78158, 1.7533,
|
||||
1.6965, 1.68194, 1.64654, 1.6048, 1.52143, 1.55622, 1.5113, 1.474, 1.4482,
|
||||
1.41018, 1.36775, 1.34188, 1.31429, 1.28303, 1.26758, 1.2367, 1.2082,
|
||||
1.18737, 1.14683, 1.12362, 1.1058, 1.07124, 1.04992
|
||||
};
|
||||
|
||||
// Values from http://www.iup.uni-bremen.de/gruppen/molspec/databases/
|
||||
// referencespectra/o3spectra2011/index.html for 233K, summed and averaged in
|
||||
// each bin (e.g. the value for 360nm is the average of the original values
|
||||
// for all wavelengths between 360 and 370nm). Values in m^2.
|
||||
const double kOzoneCrossSection[48] = {
|
||||
1.18e-27, 2.182e-28, 2.818e-28, 6.636e-28, 1.527e-27, 2.763e-27, 5.52e-27,
|
||||
8.451e-27, 1.582e-26, 2.316e-26, 3.669e-26, 4.924e-26, 7.752e-26, 9.016e-26,
|
||||
1.48e-25, 1.602e-25, 2.139e-25, 2.755e-25, 3.091e-25, 3.5e-25, 4.266e-25,
|
||||
4.672e-25, 4.398e-25, 4.701e-25, 5.019e-25, 4.305e-25, 3.74e-25, 3.215e-25,
|
||||
2.662e-25, 2.238e-25, 1.852e-25, 1.473e-25, 1.209e-25, 9.423e-26, 7.455e-26,
|
||||
6.566e-26, 5.105e-26, 4.15e-26, 4.228e-26, 3.237e-26, 2.451e-26, 2.801e-26,
|
||||
2.534e-26, 1.624e-26, 1.465e-26, 2.078e-26, 1.383e-26, 7.105e-27
|
||||
};
|
||||
|
||||
// From https://en.wikipedia.org/wiki/Dobson_unit, in molecules.m^-2.
|
||||
const double kDobsonUnit = 2.687e20;
|
||||
// Maximum number density of ozone molecules, in m^-3 (computed so at to get
|
||||
// 300 Dobson units of ozone - for this we divide 300 DU by the integral of
|
||||
// the ozone density profile defined below, which is equal to 15km).
|
||||
const double kMaxOzoneNumberDensity = 300.0 * kDobsonUnit / 15000.0;
|
||||
const double kRayleigh = 1.24062e-6;
|
||||
const double kRayleighScaleHeight = 8000.0;
|
||||
const double kMieScaleHeight = 1200.0;
|
||||
const double kMieAngstromAlpha = 0.0;
|
||||
const double kMieAngstromBeta = 5.328e-3;
|
||||
const double kMieSingleScatteringAlbedo = 0.9;
|
||||
const double kGroundAlbedo = 0.1;
|
||||
|
||||
AtmosphericModelSettings::AtmosphericModelSettings()
|
||||
: m_skyBottomRadius(6360.0f)
|
||||
, m_skyTopRadius(6420.0f)
|
||||
, m_sunArcRadians(0.00045f)
|
||||
, m_mieAnisotropy(0.8f)
|
||||
{
|
||||
DensityLayer rayleigh_density(0.0, 1.0, -1.0 / kRayleighScaleHeight, 0.0, 0.0);
|
||||
DensityLayer mie_density(0.0, 1.0, -1.0 / kMieScaleHeight, 0.0, 0.0);
|
||||
|
||||
m_rayleighProfile.push_back(rayleigh_density);
|
||||
m_mieProfile.push_back(mie_density);
|
||||
|
||||
// Density profile increasing linearly from 0 to 1 between 10 and 25km, and
|
||||
// decreasing linearly from 1 to 0 between 25 and 40km. This is an approximate
|
||||
// profile from http://www.kln.ac.lk/science/Chemistry/Teaching_Resources/
|
||||
// Documents/Introduction%20to%20atmospheric%20chemistry.pdf (page 10).
|
||||
m_absorptionProfile.push_back(DensityLayer(25000.0, 0.0, 0.0, 1.0 / 15000.0, -2.0 / 3.0));
|
||||
m_absorptionProfile.push_back(DensityLayer(0.0, 0.0, 0.0, -1.0 / 15000.0, 8.0 / 3.0));
|
||||
}
|
||||
|
||||
AtmosphericModelSettings::AtmosphericModelSettings(
|
||||
DensityProfile& rayleighProfile,
|
||||
DensityProfile& mieProfile,
|
||||
DensityProfile& absorptionProfile)
|
||||
: m_skyBottomRadius(6360.0f)
|
||||
, m_skyTopRadius(6420.0f)
|
||||
, m_rayleighProfile(rayleighProfile)
|
||||
, m_mieProfile(mieProfile)
|
||||
, m_absorptionProfile(absorptionProfile)
|
||||
, m_sunArcRadians(0.00045f)
|
||||
, m_mieAnisotropy(0.8f)
|
||||
{
|
||||
}
|
||||
|
||||
AtmosphericModelSettings::AtmosphericModelSettings(
|
||||
F32 skyBottomRadius,
|
||||
F32 skyTopRadius,
|
||||
DensityProfile& rayleighProfile,
|
||||
DensityProfile& mieProfile,
|
||||
DensityProfile& absorptionProfile,
|
||||
F32 sunArcRadians,
|
||||
F32 mieAniso)
|
||||
: m_skyBottomRadius(skyBottomRadius)
|
||||
, m_skyTopRadius(skyTopRadius)
|
||||
, m_rayleighProfile(rayleighProfile)
|
||||
, m_mieProfile(mieProfile)
|
||||
, m_absorptionProfile(absorptionProfile)
|
||||
, m_sunArcRadians(sunArcRadians)
|
||||
, m_mieAnisotropy(mieAniso)
|
||||
{
|
||||
}
|
||||
|
||||
bool AtmosphericModelSettings::operator==(const AtmosphericModelSettings& rhs) const
|
||||
{
|
||||
if (m_skyBottomRadius != rhs.m_skyBottomRadius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_skyTopRadius != rhs.m_skyTopRadius)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_sunArcRadians != rhs.m_sunArcRadians)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_mieAnisotropy != rhs.m_mieAnisotropy)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_rayleighProfile != rhs.m_rayleighProfile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_mieProfile != rhs.m_mieProfile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_absorptionProfile != rhs.m_absorptionProfile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLAtmosphere::initClass()
|
||||
{
|
||||
if (!gAtmosphere)
|
||||
{
|
||||
gAtmosphere = new LLAtmosphere;
|
||||
}
|
||||
}
|
||||
|
||||
void LLAtmosphere::cleanupClass()
|
||||
{
|
||||
if(gAtmosphere)
|
||||
{
|
||||
delete gAtmosphere;
|
||||
}
|
||||
gAtmosphere = NULL;
|
||||
}
|
||||
|
||||
LLAtmosphere::LLAtmosphere()
|
||||
{
|
||||
for (int l = kLambdaMin; l <= kLambdaMax; l += 10)
|
||||
{
|
||||
double lambda = static_cast<double>(l) * 1e-3; // micro-meters
|
||||
double mie = kMieAngstromBeta / kMieScaleHeight * pow(lambda, -kMieAngstromAlpha);
|
||||
m_wavelengths.push_back(l);
|
||||
m_solar_irradiance.push_back(kSolarIrradiance[(l - kLambdaMin) / 10]);
|
||||
m_rayleigh_scattering.push_back(kRayleigh * pow(lambda, -4));
|
||||
m_mie_scattering.push_back(mie * kMieSingleScatteringAlbedo);
|
||||
m_mie_extinction.push_back(mie);
|
||||
m_absorption_extinction.push_back(kMaxOzoneNumberDensity * kOzoneCrossSection[(l - kLambdaMin) / 10]);
|
||||
m_ground_albedo.push_back(kGroundAlbedo);
|
||||
}
|
||||
|
||||
AtmosphericModelSettings defaults;
|
||||
configureAtmosphericModel(defaults);
|
||||
}
|
||||
|
||||
LLAtmosphere::~LLAtmosphere()
|
||||
{
|
||||
// Cease referencing textures from atmosphere::model from our LLGLTextures wrappers for same.
|
||||
if (m_transmittance)
|
||||
{
|
||||
m_transmittance->setTexName(0);
|
||||
}
|
||||
|
||||
if (m_scattering)
|
||||
{
|
||||
m_scattering->setTexName(0);
|
||||
}
|
||||
|
||||
if (m_mie_scatter_texture)
|
||||
{
|
||||
m_mie_scatter_texture->setTexName(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLAtmosphere::configureAtmosphericModel(AtmosphericModelSettings& settings)
|
||||
{
|
||||
// TBD
|
||||
return true;
|
||||
}
|
||||
|
||||
LLGLTexture* LLAtmosphere::getTransmittance()
|
||||
{
|
||||
if (!m_transmittance)
|
||||
{
|
||||
m_transmittance = new LLGLTexture;
|
||||
m_transmittance->generateGLTexture();
|
||||
m_transmittance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
|
||||
m_transmittance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
|
||||
m_transmittance->setExplicitFormat(GL_RGB32F_ARB, GL_RGB, GL_FLOAT);
|
||||
m_transmittance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
return m_transmittance;
|
||||
}
|
||||
|
||||
LLGLTexture* LLAtmosphere::getScattering()
|
||||
{
|
||||
if (!m_scattering)
|
||||
{
|
||||
m_scattering = new LLGLTexture;
|
||||
m_scattering->generateGLTexture();
|
||||
m_scattering->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
|
||||
m_scattering->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
|
||||
m_scattering->setExplicitFormat(GL_RGB16F_ARB, GL_RGB, GL_FLOAT);
|
||||
m_scattering->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
|
||||
}
|
||||
return m_scattering;
|
||||
}
|
||||
|
||||
LLGLTexture* LLAtmosphere::getMieScattering()
|
||||
{
|
||||
if (!m_mie_scatter_texture)
|
||||
{
|
||||
m_mie_scatter_texture = new LLGLTexture;
|
||||
m_mie_scatter_texture->generateGLTexture();
|
||||
m_mie_scatter_texture->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
|
||||
m_mie_scatter_texture->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
|
||||
m_mie_scatter_texture->setExplicitFormat(GL_RGB16F_ARB, GL_RGB, GL_FLOAT);
|
||||
m_mie_scatter_texture->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
|
||||
}
|
||||
return m_mie_scatter_texture;
|
||||
}
|
||||
|
||||
LLGLTexture* LLAtmosphere::getIlluminance()
|
||||
{
|
||||
if (!m_illuminance)
|
||||
{
|
||||
m_illuminance = new LLGLTexture;
|
||||
m_illuminance->generateGLTexture();
|
||||
m_illuminance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
|
||||
m_illuminance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
|
||||
m_illuminance->setExplicitFormat(GL_RGB32F_ARB, GL_RGB, GL_FLOAT);
|
||||
m_illuminance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
return m_illuminance;
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
/**
|
||||
* @file llatmosphere.h
|
||||
* @brief LLAtmosphere class
|
||||
*
|
||||
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2018, 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_ATMOSPHERE_H
|
||||
#define LL_ATMOSPHERE_H
|
||||
|
||||
#include "llglheaders.h"
|
||||
#include "llgltexture.h"
|
||||
|
||||
// An atmosphere layer of width 'width' (in m), and whose density is defined as
|
||||
// 'exp_term' * exp('exp_scale' * h) + 'linear_term' * h + 'constant_term',
|
||||
// clamped to [0,1], and where h is the altitude (in m). 'exp_term' and
|
||||
// 'constant_term' are unitless, while 'exp_scale' and 'linear_term' are in
|
||||
// m^-1.
|
||||
class DensityLayer {
|
||||
public:
|
||||
DensityLayer()
|
||||
: width(0.0f)
|
||||
, exp_term(0.0f)
|
||||
, exp_scale(0.0f)
|
||||
, linear_term(0.0f)
|
||||
, constant_term(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
DensityLayer(float width, float exp_term, float exp_scale, float linear_term, float constant_term)
|
||||
: width(width)
|
||||
, exp_term(exp_term)
|
||||
, exp_scale(exp_scale)
|
||||
, linear_term(linear_term)
|
||||
, constant_term(constant_term)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const DensityLayer& rhs) const
|
||||
{
|
||||
if (width != rhs.width)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exp_term != rhs.exp_term)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exp_scale != rhs.exp_scale)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (linear_term != rhs.linear_term)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (constant_term != rhs.constant_term)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float width = 1024.0f;
|
||||
float exp_term = 1.0f;
|
||||
float exp_scale = 1.0f;
|
||||
float linear_term = 1.0f;
|
||||
float constant_term = 0.0f;
|
||||
};
|
||||
|
||||
typedef std::vector<DensityLayer> DensityProfile;
|
||||
|
||||
class AtmosphericModelSettings
|
||||
{
|
||||
public:
|
||||
AtmosphericModelSettings();
|
||||
|
||||
AtmosphericModelSettings(
|
||||
DensityProfile& rayleighProfile,
|
||||
DensityProfile& mieProfile,
|
||||
DensityProfile& absorptionProfile);
|
||||
|
||||
AtmosphericModelSettings(
|
||||
F32 skyBottomRadius,
|
||||
F32 skyTopRadius,
|
||||
DensityProfile& rayleighProfile,
|
||||
DensityProfile& mieProfile,
|
||||
DensityProfile& absorptionProfile,
|
||||
F32 sunArcRadians,
|
||||
F32 mieAniso);
|
||||
|
||||
bool operator==(const AtmosphericModelSettings& rhs) const;
|
||||
|
||||
F32 m_skyBottomRadius;
|
||||
F32 m_skyTopRadius;
|
||||
DensityProfile m_rayleighProfile;
|
||||
DensityProfile m_mieProfile;
|
||||
DensityProfile m_absorptionProfile;
|
||||
F32 m_sunArcRadians;
|
||||
F32 m_mieAnisotropy;
|
||||
};
|
||||
|
||||
class LLAtmosphere
|
||||
{
|
||||
public:
|
||||
LLAtmosphere();
|
||||
~LLAtmosphere();
|
||||
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
|
||||
const LLAtmosphere& operator=(const LLAtmosphere& rhs)
|
||||
{
|
||||
LL_ERRS() << "Illegal operation!" << LL_ENDL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLGLTexture* getTransmittance();
|
||||
LLGLTexture* getScattering();
|
||||
LLGLTexture* getMieScattering();
|
||||
LLGLTexture* getIlluminance();
|
||||
|
||||
bool configureAtmosphericModel(AtmosphericModelSettings& settings);
|
||||
|
||||
protected:
|
||||
LLAtmosphere(const LLAtmosphere& rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
LLPointer<LLGLTexture> m_transmittance;
|
||||
LLPointer<LLGLTexture> m_scattering;
|
||||
LLPointer<LLGLTexture> m_mie_scatter_texture;
|
||||
LLPointer<LLGLTexture> m_illuminance;
|
||||
|
||||
std::vector<double> m_wavelengths;
|
||||
std::vector<double> m_solar_irradiance;
|
||||
std::vector<double> m_rayleigh_scattering;
|
||||
std::vector<double> m_mie_scattering;
|
||||
std::vector<double> m_mie_extinction;
|
||||
std::vector<double> m_absorption_extinction;
|
||||
std::vector<double> m_ground_albedo;
|
||||
|
||||
AtmosphericModelSettings m_settings;
|
||||
};
|
||||
|
||||
extern LLAtmosphere* gAtmosphere;
|
||||
|
||||
#endif // LL_ATMOSPHERE_H
|
||||
|
|
@ -43,20 +43,13 @@
|
|||
const F32 epsilon = 1e-7f;
|
||||
const U16 RESOLUTION = 64;
|
||||
|
||||
#if LL_DARWIN
|
||||
// mipmap generation on cubemap textures seems to be broken on the Mac for at least some cards.
|
||||
// Since the cubemap is small (64x64 per face) and doesn't have any fine detail, turning off mipmaps is a usable workaround.
|
||||
const BOOL use_cube_mipmaps = FALSE;
|
||||
#else
|
||||
const BOOL use_cube_mipmaps = FALSE; //current build works best without cube mipmaps
|
||||
#endif
|
||||
|
||||
bool LLCubeMap::sUseCubeMaps = true;
|
||||
|
||||
LLCubeMap::LLCubeMap()
|
||||
LLCubeMap::LLCubeMap(bool init_as_srgb)
|
||||
: mTextureStage(0),
|
||||
mTextureCoordStage(0),
|
||||
mMatrixStage(0)
|
||||
mMatrixStage(0),
|
||||
mIssRGB(init_as_srgb)
|
||||
{
|
||||
mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
|
||||
mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
|
||||
|
|
@ -82,12 +75,17 @@ void LLCubeMap::initGL()
|
|||
U32 texname = 0;
|
||||
|
||||
LLImageGL::generateTextures(1, &texname);
|
||||
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE));
|
||||
mImages[i] = new LLImageGL(RESOLUTION, RESOLUTION, 4, FALSE);
|
||||
#if USE_SRGB_DECODE
|
||||
if (mIssRGB) {
|
||||
mImages[i]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA);
|
||||
}
|
||||
#endif
|
||||
mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
|
||||
mRawImages[i] = new LLImageRaw(64, 64, 4);
|
||||
mRawImages[i] = new LLImageRaw(RESOLUTION, RESOLUTION, 4);
|
||||
mImages[i]->createGLTexture(0, mRawImages[i], texname);
|
||||
|
||||
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
|
||||
|
|
@ -154,7 +152,7 @@ void LLCubeMap::initGLData()
|
|||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
mImages[i]->setSubImage(mRawImages[i], 0, 0, 64, 64);
|
||||
mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -484,7 +482,7 @@ void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
|
|||
td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
|
||||
}
|
||||
}
|
||||
mImages[side]->setSubImage(mRawImages[side], 0, 0, 64, 64);
|
||||
mImages[side]->setSubImage(mRawImages[side], 0, 0, RESOLUTION, RESOLUTION);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,8 +36,9 @@ class LLVector3;
|
|||
// Environment map hack!
|
||||
class LLCubeMap : public LLRefCount
|
||||
{
|
||||
bool mIssRGB;
|
||||
public:
|
||||
LLCubeMap();
|
||||
LLCubeMap(bool init_as_srgb);
|
||||
void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
|
||||
void initGL();
|
||||
void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "llsys.h"
|
||||
|
||||
#include "llgl.h"
|
||||
#include "llglstates.h"
|
||||
#include "llrender.h"
|
||||
|
||||
#include "llerror.h"
|
||||
|
|
@ -1069,6 +1070,12 @@ void LLGLManager::initExtensions()
|
|||
mHassRGBFramebuffer = ExtensionExists("GL_EXT_framebuffer_sRGB", gGLHExts.mSysExts);
|
||||
#endif
|
||||
|
||||
#ifdef GL_EXT_texture_sRGB_decode
|
||||
mHasTexturesRGBDecode = ExtensionExists("GL_EXT_texture_sRGB_decode", gGLHExts.mSysExts);
|
||||
#else
|
||||
mHasTexturesRGBDecode = ExtensionExists("GL_ARB_texture_sRGB_decode", gGLHExts.mSysExts);
|
||||
#endif
|
||||
|
||||
mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
|
||||
|
||||
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
|
||||
|
|
@ -2115,7 +2122,8 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :
|
|||
if (mState)
|
||||
{
|
||||
mWasEnabled = sStateMap[state];
|
||||
llassert(mWasEnabled == glIsEnabled(state));
|
||||
// we can't actually assert on this as queued changes to state are not reflected by glIsEnabled
|
||||
//llassert(mWasEnabled == glIsEnabled(state));
|
||||
setEnabled(enabled);
|
||||
stop_glerror();
|
||||
}
|
||||
|
|
@ -2338,6 +2346,17 @@ LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& mode
|
|||
}
|
||||
}
|
||||
|
||||
void LLGLUserClipPlane::disable()
|
||||
{
|
||||
if (mApply)
|
||||
{
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
gGL.popMatrix();
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
}
|
||||
mApply = false;
|
||||
}
|
||||
|
||||
void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
|
||||
{
|
||||
glh::matrix4f& P = mProjection;
|
||||
|
|
@ -2366,12 +2385,7 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
|
|||
|
||||
LLGLUserClipPlane::~LLGLUserClipPlane()
|
||||
{
|
||||
if (mApply)
|
||||
{
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
gGL.popMatrix();
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
}
|
||||
disable();
|
||||
}
|
||||
|
||||
LLGLNamePool::LLGLNamePool()
|
||||
|
|
@ -2549,27 +2563,45 @@ void LLGLDepthTest::checkState()
|
|||
}
|
||||
}
|
||||
|
||||
LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P, U32 layer)
|
||||
LLGLSquashToFarClip::LLGLSquashToFarClip()
|
||||
{
|
||||
glh::matrix4f proj = get_current_projection();
|
||||
setProjectionMatrix(proj, 0);
|
||||
}
|
||||
|
||||
LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f& P, U32 layer)
|
||||
{
|
||||
setProjectionMatrix(P, layer);
|
||||
}
|
||||
|
||||
|
||||
void LLGLSquashToFarClip::setProjectionMatrix(glh::matrix4f& projection, U32 layer)
|
||||
{
|
||||
|
||||
F32 depth = 0.99999f - 0.0001f * layer;
|
||||
|
||||
for (U32 i = 0; i < 4; i++)
|
||||
{
|
||||
P.element(2, i) = P.element(3, i) * depth;
|
||||
projection.element(2, i) = projection.element(3, i) * depth;
|
||||
}
|
||||
|
||||
LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode();
|
||||
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadMatrix(P.m);
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
gGL.loadMatrix(projection.m);
|
||||
|
||||
gGL.matrixMode(last_matrix_mode);
|
||||
}
|
||||
|
||||
LLGLSquashToFarClip::~LLGLSquashToFarClip()
|
||||
{
|
||||
LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode();
|
||||
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
gGL.popMatrix();
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
|
||||
gGL.matrixMode(last_matrix_mode);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2632,6 +2664,43 @@ void LLGLSyncFence::wait()
|
|||
#endif
|
||||
}
|
||||
|
||||
LLGLSPipelineSkyBox::LLGLSPipelineSkyBox()
|
||||
: mAlphaTest(GL_ALPHA_TEST)
|
||||
, mCullFace(GL_CULL_FACE)
|
||||
, mSquashClip()
|
||||
{
|
||||
if (!LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_FOG);
|
||||
glDisable(GL_CLIP_PLANE0);
|
||||
}
|
||||
}
|
||||
|
||||
LLGLSPipelineSkyBox::~LLGLSPipelineSkyBox()
|
||||
{
|
||||
if (!LLGLSLShader::sNoFixedFunction)
|
||||
{
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_FOG);
|
||||
glEnable(GL_CLIP_PLANE0);
|
||||
}
|
||||
}
|
||||
|
||||
LLGLSPipelineDepthTestSkyBox::LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write)
|
||||
: LLGLSPipelineSkyBox()
|
||||
, mDepth(depth_test ? GL_TRUE : GL_FALSE, depth_write ? GL_TRUE : GL_FALSE, GL_LEQUAL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LLGLSPipelineBlendSkyBox::LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write)
|
||||
: LLGLSPipelineDepthTestSkyBox(depth_test, depth_write)
|
||||
, mBlend(GL_BLEND)
|
||||
{
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
// Expose desired use of high-performance graphics processor to Optimus driver
|
||||
extern "C"
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ public:
|
|||
BOOL mHasDebugOutput;
|
||||
BOOL mHassRGBTexture;
|
||||
BOOL mHassRGBFramebuffer;
|
||||
BOOL mHasTexturesRGBDecode;
|
||||
|
||||
// Vendor-specific extensions
|
||||
BOOL mIsATI;
|
||||
|
|
@ -349,6 +350,7 @@ public:
|
|||
~LLGLUserClipPlane();
|
||||
|
||||
void setPlane(F32 a, F32 b, F32 c, F32 d);
|
||||
void disable();
|
||||
|
||||
private:
|
||||
bool mApply;
|
||||
|
|
@ -361,14 +363,17 @@ private:
|
|||
Modify and load projection matrix to push depth values to far clip plane.
|
||||
|
||||
Restores projection matrix on destruction.
|
||||
GL_MODELVIEW_MATRIX is active whenever program execution
|
||||
leaves this class.
|
||||
Saves/restores matrix mode around projection manipulation.
|
||||
Does not stack.
|
||||
*/
|
||||
class LLGLSquashToFarClip
|
||||
{
|
||||
public:
|
||||
LLGLSquashToFarClip(glh::matrix4f projection, U32 layer = 0);
|
||||
LLGLSquashToFarClip();
|
||||
LLGLSquashToFarClip(glh::matrix4f& projection, U32 layer = 0);
|
||||
|
||||
void setProjectionMatrix(glh::matrix4f& projection, U32 layer);
|
||||
|
||||
~LLGLSquashToFarClip();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* @file llphoenixfunc.h
|
||||
* @file llglcommonfunc.h
|
||||
* @brief File include common opengl code snippets
|
||||
*
|
||||
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
|
||||
|
|
|
|||
|
|
@ -37,12 +37,6 @@
|
|||
#include "OpenGL/OpenGL.h"
|
||||
#endif
|
||||
|
||||
#ifdef LL_RELEASE_FOR_DOWNLOAD
|
||||
#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
|
||||
#else
|
||||
#define UNIFORM_ERRS LL_ERRS("Shader")
|
||||
#endif
|
||||
|
||||
// Lots of STL stuff in here, using namespace std to keep things more readable
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
|
@ -84,6 +78,12 @@ LLShaderFeatures::LLShaderFeatures()
|
|||
, hasObjectSkinning(false)
|
||||
, hasAtmospherics(false)
|
||||
, hasGamma(false)
|
||||
, hasSrgb(false)
|
||||
, encodesNormal(false)
|
||||
, isDeferred(false)
|
||||
, hasIndirect(false)
|
||||
, hasShadows(false)
|
||||
, hasAmbientOcclusion(false)
|
||||
, mIndexedTextureChannels(0)
|
||||
, disableTextureIndex(false)
|
||||
, hasAlphaMask(false)
|
||||
|
|
@ -344,13 +344,13 @@ void LLGLSLShader::unloadInternal()
|
|||
{
|
||||
GLhandleARB obj[1024];
|
||||
GLsizei count;
|
||||
glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj);
|
||||
|
||||
glGetAttachedObjectsARB(mProgramObject, sizeof(obj)/sizeof(obj[0]), &count, obj);
|
||||
for (GLsizei i = 0; i < count; i++)
|
||||
{
|
||||
glDetachObjectARB(mProgramObject, obj[i]);
|
||||
glDeleteObjectARB(obj[i]);
|
||||
}
|
||||
glDeleteObjectARB(obj[i]);
|
||||
}
|
||||
|
||||
glDeleteObjectARB(mProgramObject);
|
||||
|
||||
|
|
@ -448,12 +448,12 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
|
|||
}
|
||||
if( !success )
|
||||
{
|
||||
LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL;
|
||||
LL_SHADER_LOADING_WARNS() << "Failed to link shader: " << mName << LL_ENDL;
|
||||
|
||||
// Try again using a lower shader level;
|
||||
if (mShaderLevel > 0)
|
||||
{
|
||||
LL_WARNS("ShaderLoading") << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL;
|
||||
LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL;
|
||||
mShaderLevel--;
|
||||
return createShader(attributes,uniforms);
|
||||
}
|
||||
|
|
@ -485,18 +485,33 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
|
|||
return success;
|
||||
}
|
||||
|
||||
BOOL LLGLSLShader::attachObject(std::string object)
|
||||
{
|
||||
if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0)
|
||||
BOOL LLGLSLShader::attachVertexObject(std::string object_path) {
|
||||
if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0)
|
||||
{
|
||||
stop_glerror();
|
||||
glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]);
|
||||
glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]);
|
||||
stop_glerror();
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ShaderLoading") << "Attempting to attach shader object that hasn't been compiled: " << object << LL_ENDL;
|
||||
LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLGLSLShader::attachFragmentObject(std::string object_path)
|
||||
{
|
||||
if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0)
|
||||
{
|
||||
stop_glerror();
|
||||
glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]);
|
||||
stop_glerror();
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -511,7 +526,7 @@ void LLGLSLShader::attachObject(GLhandleARB object)
|
|||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("ShaderLoading") << "Attempting to attach non existing shader object. " << LL_ENDL;
|
||||
LL_SHADER_LOADING_WARNS() << "Attempting to attach non existing shader object. " << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -690,6 +705,11 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
|
|||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::clearPermutations()
|
||||
{
|
||||
mDefines.clear();
|
||||
}
|
||||
|
||||
void LLGLSLShader::addPermutation(std::string name, std::string value)
|
||||
{
|
||||
mDefines[name] = value;
|
||||
|
|
@ -759,18 +779,19 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
|
|||
S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap");
|
||||
S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap");
|
||||
S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
|
||||
S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap");
|
||||
S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
|
||||
|
||||
std::set<S32> skip_index;
|
||||
|
||||
if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap))
|
||||
if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap))
|
||||
{
|
||||
GLenum type;
|
||||
GLsizei length;
|
||||
GLint size = -1;
|
||||
char name[1024];
|
||||
|
||||
diffuseMap = specularMap = bumpMap = environmentMap = -1;
|
||||
diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1;
|
||||
|
||||
for (S32 i = 0; i < activeCount; i++)
|
||||
{
|
||||
|
|
@ -790,12 +811,6 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (-1 == specularMap && std::string(name) == "specularMap")
|
||||
{
|
||||
specularMap = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (-1 == bumpMap && std::string(name) == "bumpMap")
|
||||
{
|
||||
bumpMap = i;
|
||||
|
|
@ -807,6 +822,12 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
|
|||
environmentMap = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap")
|
||||
{
|
||||
altDiffuseMap = i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
|
||||
|
|
@ -858,7 +879,7 @@ BOOL LLGLSLShader::link(BOOL suppress_errors)
|
|||
{
|
||||
BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors);
|
||||
|
||||
if (!suppress_errors)
|
||||
if (!success && !suppress_errors)
|
||||
{
|
||||
LLShaderMgr::instance()->dumpObjectLog(mProgramObject, !success, mName);
|
||||
}
|
||||
|
|
@ -916,19 +937,19 @@ void LLGLSLShader::bindNoShader(void)
|
|||
}
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
|
||||
S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
|
||||
{
|
||||
S32 channel = 0;
|
||||
channel = getUniformLocation(uniform);
|
||||
|
||||
return bindTexture(channel, texture, mode);
|
||||
return bindTexture(channel, texture, mode, colorspace);
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
|
||||
S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
|
||||
{
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -937,6 +958,7 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu
|
|||
if (uniform > -1)
|
||||
{
|
||||
gGL.getTexUnit(uniform)->bind(texture, mode);
|
||||
gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace);
|
||||
}
|
||||
|
||||
return uniform;
|
||||
|
|
@ -954,7 +976,7 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
|||
{
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -968,11 +990,11 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
|||
return uniform;
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
||||
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
{
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
return -1;
|
||||
}
|
||||
S32 index = mTexture[uniform];
|
||||
|
|
@ -980,21 +1002,22 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
|||
{
|
||||
gGL.getTexUnit(index)->activate();
|
||||
gGL.getTexUnit(index)->enable(mode);
|
||||
gGL.getTexUnit(index)->setTextureColorSpace(space);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
||||
S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
{
|
||||
if (uniform < 0 || uniform >= (S32)mTexture.size())
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
|
||||
return -1;
|
||||
}
|
||||
S32 index = mTexture[uniform];
|
||||
if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE)
|
||||
{
|
||||
if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode)
|
||||
if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode && gGL.getTexUnit(index)->getCurrColorSpace() != space)
|
||||
{
|
||||
if (gDebugSession)
|
||||
{
|
||||
|
|
@ -1017,7 +1040,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1039,7 +1062,7 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1061,7 +1084,7 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1084,7 +1107,7 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1107,7 +1130,7 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1130,7 +1153,7 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1153,7 +1176,7 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1176,7 +1199,7 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1199,7 +1222,7 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1222,7 +1245,7 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1245,7 +1268,7 @@ void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, c
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1262,7 +1285,7 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1279,7 +1302,7 @@ void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose,
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1296,7 +1319,7 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c
|
|||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
|
||||
LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ public:
|
|||
bool hasObjectSkinning;
|
||||
bool hasAtmospherics;
|
||||
bool hasGamma;
|
||||
bool hasShadows;
|
||||
bool hasAmbientOcclusion;
|
||||
bool hasSrgb;
|
||||
bool encodesNormal;
|
||||
bool isDeferred;
|
||||
bool hasIndirect;
|
||||
S32 mIndexedTextureChannels;
|
||||
bool disableTextureIndex;
|
||||
bool hasAlphaMask;
|
||||
|
|
@ -96,7 +102,8 @@ public:
|
|||
std::vector<LLStaticHashedString> * uniforms,
|
||||
U32 varying_count = 0,
|
||||
const char** varyings = NULL);
|
||||
BOOL attachObject(std::string object);
|
||||
BOOL attachFragmentObject(std::string object);
|
||||
BOOL attachVertexObject(std::string object);
|
||||
void attachObject(GLhandleARB object);
|
||||
void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);
|
||||
BOOL mapAttributes(const std::vector<LLStaticHashedString> * attributes);
|
||||
|
|
@ -139,6 +146,7 @@ public:
|
|||
GLint getAttribLocation(U32 attrib);
|
||||
GLint mapUniformTextureChannel(GLint location, GLenum type);
|
||||
|
||||
void clearPermutations();
|
||||
void addPermutation(std::string name, std::string value);
|
||||
void removePermutation(std::string name);
|
||||
|
||||
|
|
@ -146,13 +154,13 @@ public:
|
|||
//if given texture uniform is active in the shader,
|
||||
//the corresponding channel will be active upon return
|
||||
//returns channel texture is enabled in from [0-MAX)
|
||||
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
|
||||
S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
|
||||
|
||||
// bindTexture returns the texture unit we've bound the texture to.
|
||||
// You can reuse the return value to unbind a texture when required.
|
||||
S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
|
||||
S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
|
||||
S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
|
||||
|
|
|
|||
|
|
@ -208,11 +208,27 @@ public:
|
|||
class LLGLSPipelineSkyBox
|
||||
{
|
||||
protected:
|
||||
LLGLDisable mAlphaTest, mCullFace, mFog;
|
||||
LLGLDisable mAlphaTest;
|
||||
LLGLDisable mCullFace;
|
||||
LLGLSquashToFarClip mSquashClip;
|
||||
public:
|
||||
LLGLSPipelineSkyBox()
|
||||
: mAlphaTest(GL_ALPHA_TEST), mCullFace(GL_CULL_FACE), mFog(GL_FOG)
|
||||
{ }
|
||||
LLGLSPipelineSkyBox();
|
||||
~LLGLSPipelineSkyBox();
|
||||
};
|
||||
|
||||
class LLGLSPipelineDepthTestSkyBox : public LLGLSPipelineSkyBox
|
||||
{
|
||||
public:
|
||||
LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write);
|
||||
|
||||
LLGLDepthTest mDepth;
|
||||
};
|
||||
|
||||
class LLGLSPipelineBlendSkyBox : public LLGLSPipelineDepthTestSkyBox
|
||||
{
|
||||
public:
|
||||
LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write);
|
||||
LLGLEnable mBlend;
|
||||
};
|
||||
|
||||
class LLGLSTracker
|
||||
|
|
|
|||
|
|
@ -288,6 +288,18 @@ void LLGLTexture::setCategory(S32 category)
|
|||
mGLTexturep->setCategory(category) ;
|
||||
}
|
||||
|
||||
void LLGLTexture::setTexName(LLGLuint texName)
|
||||
{
|
||||
llassert(mGLTexturep.notNull());
|
||||
return mGLTexturep->setTexName(texName);
|
||||
}
|
||||
|
||||
void LLGLTexture::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
|
||||
{
|
||||
llassert(mGLTexturep.notNull());
|
||||
return mGLTexturep->setTarget(target, bind_target);
|
||||
}
|
||||
|
||||
LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const
|
||||
{
|
||||
llassert(mGLTexturep.notNull()) ;
|
||||
|
|
@ -389,9 +401,11 @@ void LLGLTexture::destroyGLTexture()
|
|||
|
||||
void LLGLTexture::setTexelsPerImage()
|
||||
{
|
||||
S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
|
||||
S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
|
||||
mTexelsPerImage = (F32)fullwidth * fullheight;
|
||||
U32 fullwidth = llmin(mFullWidth,U32(MAX_IMAGE_SIZE_DEFAULT));
|
||||
U32 fullheight = llmin(mFullHeight,U32(MAX_IMAGE_SIZE_DEFAULT));
|
||||
mTexelsPerImage = (U32)fullwidth * fullheight;
|
||||
}
|
||||
|
||||
static LLUUID sStubUUID;
|
||||
|
||||
const LLUUID& LLGLTexture::getID() const { return sStubUUID; }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
* @file llglviewertexture.h
|
||||
* @file llgltexture.h
|
||||
* @brief Object for managing opengl textures
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
|
|
@ -104,7 +104,7 @@ public:
|
|||
|
||||
virtual void dump(); // debug info to LL_INFOS()
|
||||
|
||||
virtual const LLUUID& getID() const = 0;
|
||||
virtual const LLUUID& getID() const;
|
||||
|
||||
void setBoostLevel(S32 level);
|
||||
S32 getBoostLevel() { return mBoostLevel; }
|
||||
|
|
@ -133,6 +133,8 @@ public:
|
|||
BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height);
|
||||
void setGLTextureCreated (bool initialized);
|
||||
void setCategory(S32 category) ;
|
||||
void setTexName(LLGLuint); // for forcing w/ externally created textures only
|
||||
void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target);
|
||||
|
||||
LLTexUnit::eTextureAddressMode getAddressMode(void) const ;
|
||||
S32 getMaxDiscardLevel() const;
|
||||
|
|
@ -179,11 +181,11 @@ protected:
|
|||
|
||||
protected:
|
||||
S32 mBoostLevel; // enum describing priority level
|
||||
S32 mFullWidth;
|
||||
S32 mFullHeight;
|
||||
U32 mFullWidth;
|
||||
U32 mFullHeight;
|
||||
BOOL mUseMipMaps;
|
||||
S8 mComponents;
|
||||
F32 mTexelsPerImage; // Texels per image.
|
||||
U32 mTexelsPerImage; // Texels per image.
|
||||
mutable S8 mNeedsGLTexture;
|
||||
|
||||
//GL texture
|
||||
|
|
|
|||
|
|
@ -184,34 +184,47 @@ void LLImageGL::cleanupClass()
|
|||
//static
|
||||
S32 LLImageGL::dataFormatBits(S32 dataformat)
|
||||
{
|
||||
switch (dataformat)
|
||||
{
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8;
|
||||
case GL_LUMINANCE: return 8;
|
||||
case GL_ALPHA: return 8;
|
||||
case GL_COLOR_INDEX: return 8;
|
||||
case GL_LUMINANCE_ALPHA: return 16;
|
||||
case GL_RGB: return 24;
|
||||
case GL_RGB8: return 24;
|
||||
case GL_RGBA: return 32;
|
||||
case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac
|
||||
default:
|
||||
LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
switch (dataformat)
|
||||
{
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4;
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8;
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8;
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8;
|
||||
case GL_LUMINANCE: return 8;
|
||||
case GL_ALPHA: return 8;
|
||||
case GL_COLOR_INDEX: return 8;
|
||||
case GL_LUMINANCE_ALPHA: return 16;
|
||||
case GL_RGB: return 24;
|
||||
case GL_SRGB: return 24;
|
||||
case GL_RGB8: return 24;
|
||||
case GL_RGBA: return 32;
|
||||
case GL_SRGB_ALPHA: return 32;
|
||||
case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac
|
||||
default:
|
||||
LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
S32 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)
|
||||
{
|
||||
if (dataformat >= GL_COMPRESSED_RGB_S3TC_DXT1_EXT &&
|
||||
dataformat <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
|
||||
{
|
||||
if (width < 4) width = 4;
|
||||
if (height < 4) height = 4;
|
||||
}
|
||||
switch (dataformat)
|
||||
{
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
if (width < 4) width = 4;
|
||||
if (height < 4) height = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
S32 bytes ((width*height*dataFormatBits(dataformat)+7)>>3);
|
||||
S32 aligned = (bytes+3)&~3;
|
||||
return aligned;
|
||||
|
|
@ -223,14 +236,19 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
|
|||
switch (dataformat)
|
||||
{
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 3;
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 4;
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 4;
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4;
|
||||
case GL_LUMINANCE: return 1;
|
||||
case GL_ALPHA: return 1;
|
||||
case GL_COLOR_INDEX: return 1;
|
||||
case GL_LUMINANCE_ALPHA: return 2;
|
||||
case GL_RGB: return 3;
|
||||
case GL_SRGB: return 3;
|
||||
case GL_RGBA: return 4;
|
||||
case GL_SRGB_ALPHA: return 4;
|
||||
case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac
|
||||
default:
|
||||
LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
|
||||
|
|
@ -355,7 +373,7 @@ BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, B
|
|||
|
||||
LLImageGL::LLImageGL(BOOL usemipmaps)
|
||||
: LLTrace::MemTrackable<LLImageGL>("LLImageGL"),
|
||||
mSaveData(0)
|
||||
mSaveData(0), mExternalTexture(FALSE)
|
||||
{
|
||||
init(usemipmaps);
|
||||
setSize(0, 0, 0);
|
||||
|
|
@ -365,7 +383,7 @@ LLImageGL::LLImageGL(BOOL usemipmaps)
|
|||
|
||||
LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps)
|
||||
: LLTrace::MemTrackable<LLImageGL>("LLImageGL"),
|
||||
mSaveData(0)
|
||||
mSaveData(0), mExternalTexture(FALSE)
|
||||
{
|
||||
llassert( components <= 4 );
|
||||
init(usemipmaps);
|
||||
|
|
@ -376,7 +394,7 @@ LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps)
|
|||
|
||||
LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps)
|
||||
: LLTrace::MemTrackable<LLImageGL>("LLImageGL"),
|
||||
mSaveData(0)
|
||||
mSaveData(0), mExternalTexture(FALSE)
|
||||
{
|
||||
init(usemipmaps);
|
||||
setSize(0, 0, 0);
|
||||
|
|
@ -386,12 +404,36 @@ LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps)
|
|||
createGLTexture(0, imageraw);
|
||||
}
|
||||
|
||||
LLImageGL::LLImageGL(
|
||||
LLGLuint texName,
|
||||
U32 components,
|
||||
LLGLenum target,
|
||||
LLGLint formatInternal,
|
||||
LLGLenum formatPrimary,
|
||||
LLGLenum formatType,
|
||||
LLTexUnit::eTextureAddressMode addressMode)
|
||||
: LLTrace::MemTrackable<LLImageGL>("LLImageGL"), mSaveData(0), mExternalTexture(TRUE)
|
||||
{
|
||||
init(false);
|
||||
mTexName = texName;
|
||||
mTarget = target;
|
||||
mComponents = components;
|
||||
mAddressMode = addressMode;
|
||||
mFormatType = formatType;
|
||||
mFormatInternal = formatInternal;
|
||||
mFormatPrimary = formatPrimary;
|
||||
}
|
||||
|
||||
|
||||
LLImageGL::~LLImageGL()
|
||||
{
|
||||
LLImageGL::cleanup();
|
||||
sImageList.erase(this);
|
||||
freePickMask();
|
||||
sCount--;
|
||||
if (!mExternalTexture)
|
||||
{
|
||||
LLImageGL::cleanup();
|
||||
sImageList.erase(this);
|
||||
freePickMask();
|
||||
sCount--;
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageGL::init(BOOL usemipmaps)
|
||||
|
|
@ -626,10 +668,20 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
|
|||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_SET_IMAGE);
|
||||
bool is_compressed = false;
|
||||
if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
|
||||
{
|
||||
is_compressed = true;
|
||||
}
|
||||
|
||||
switch (mFormatPrimary)
|
||||
{
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
is_compressed = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1203,10 +1255,18 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
case GL_RGB8:
|
||||
intformat = GL_COMPRESSED_RGB;
|
||||
break;
|
||||
case GL_SRGB:
|
||||
case GL_SRGB8:
|
||||
intformat = GL_COMPRESSED_SRGB;
|
||||
break;
|
||||
case GL_RGBA:
|
||||
case GL_RGBA8:
|
||||
intformat = GL_COMPRESSED_RGBA;
|
||||
break;
|
||||
case GL_SRGB_ALPHA:
|
||||
case GL_SRGB8_ALPHA8:
|
||||
intformat = GL_COMPRESSED_SRGB_ALPHA;
|
||||
break;
|
||||
case GL_LUMINANCE:
|
||||
case GL_LUMINANCE8:
|
||||
intformat = GL_COMPRESSED_LUMINANCE;
|
||||
|
|
@ -1310,33 +1370,51 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
|
|||
|
||||
if( !mHasExplicitFormat )
|
||||
{
|
||||
switch (mComponents)
|
||||
{
|
||||
case 1:
|
||||
// Use luminance alpha (for fonts)
|
||||
mFormatInternal = GL_LUMINANCE8;
|
||||
mFormatPrimary = GL_LUMINANCE;
|
||||
mFormatType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case 2:
|
||||
// Use luminance alpha (for fonts)
|
||||
mFormatInternal = GL_LUMINANCE8_ALPHA8;
|
||||
mFormatPrimary = GL_LUMINANCE_ALPHA;
|
||||
mFormatType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case 3:
|
||||
mFormatInternal = GL_RGB8;
|
||||
mFormatPrimary = GL_RGB;
|
||||
mFormatType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case 4:
|
||||
mFormatInternal = GL_RGBA8;
|
||||
mFormatPrimary = GL_RGBA;
|
||||
mFormatType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
default:
|
||||
LL_ERRS() << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL;
|
||||
}
|
||||
switch (mComponents)
|
||||
{
|
||||
case 1:
|
||||
// Use luminance alpha (for fonts)
|
||||
mFormatInternal = GL_LUMINANCE8;
|
||||
mFormatPrimary = GL_LUMINANCE;
|
||||
mFormatType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case 2:
|
||||
// Use luminance alpha (for fonts)
|
||||
mFormatInternal = GL_LUMINANCE8_ALPHA8;
|
||||
mFormatPrimary = GL_LUMINANCE_ALPHA;
|
||||
mFormatType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case 3:
|
||||
#if USE_SRGB_DECODE
|
||||
if (gGLManager.mHasTexturesRGBDecode)
|
||||
{
|
||||
mFormatInternal = GL_SRGB8;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
mFormatInternal = GL_RGB8;
|
||||
}
|
||||
mFormatPrimary = GL_RGB;
|
||||
mFormatType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case 4:
|
||||
#if USE_SRGB_DECODE
|
||||
if (gGLManager.mHasTexturesRGBDecode)
|
||||
{
|
||||
mFormatInternal = GL_SRGB8_ALPHA8;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
mFormatInternal = GL_RGBA8;
|
||||
}
|
||||
mFormatPrimary = GL_RGBA;
|
||||
mFormatType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
default:
|
||||
LL_ERRS() << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL;
|
||||
}
|
||||
|
||||
calcAlphaChannelOffsetAndStride() ;
|
||||
}
|
||||
|
|
@ -1764,28 +1842,30 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
|
|||
}
|
||||
|
||||
mAlphaStride = -1 ;
|
||||
switch (mFormatPrimary)
|
||||
{
|
||||
case GL_LUMINANCE:
|
||||
case GL_ALPHA:
|
||||
mAlphaStride = 1;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
mAlphaStride = 2;
|
||||
break;
|
||||
case GL_RGB:
|
||||
mNeedsAlphaAndPickMask = FALSE ;
|
||||
mIsMask = FALSE;
|
||||
return ; //no alpha channel.
|
||||
case GL_RGBA:
|
||||
mAlphaStride = 4;
|
||||
break;
|
||||
case GL_BGRA_EXT:
|
||||
mAlphaStride = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (mFormatPrimary)
|
||||
{
|
||||
case GL_LUMINANCE:
|
||||
case GL_ALPHA:
|
||||
mAlphaStride = 1;
|
||||
break;
|
||||
case GL_LUMINANCE_ALPHA:
|
||||
mAlphaStride = 2;
|
||||
break;
|
||||
case GL_RGB:
|
||||
case GL_SRGB:
|
||||
mNeedsAlphaAndPickMask = FALSE;
|
||||
mIsMask = FALSE;
|
||||
return; //no alpha channel.
|
||||
case GL_RGBA:
|
||||
case GL_SRGB_ALPHA:
|
||||
mAlphaStride = 4;
|
||||
break;
|
||||
case GL_BGRA_EXT:
|
||||
mAlphaStride = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mAlphaOffset = -1 ;
|
||||
if (mFormatType == GL_UNSIGNED_BYTE)
|
||||
|
|
@ -1968,12 +2048,13 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
|
|||
|
||||
freePickMask();
|
||||
|
||||
if (mFormatType != GL_UNSIGNED_BYTE ||
|
||||
mFormatPrimary != GL_RGBA)
|
||||
{
|
||||
//cannot generate a pick mask for this texture
|
||||
return;
|
||||
}
|
||||
if (mFormatType != GL_UNSIGNED_BYTE ||
|
||||
((mFormatPrimary != GL_RGBA)
|
||||
&& (mFormatPrimary != GL_SRGB_ALPHA)))
|
||||
{
|
||||
//cannot generate a pick mask for this texture
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
const U32 pickSize = createPickMask(width, height);
|
||||
|
|
|
|||
|
|
@ -84,7 +84,10 @@ public:
|
|||
LLImageGL(BOOL usemipmaps = TRUE);
|
||||
LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
|
||||
LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps = TRUE);
|
||||
|
||||
|
||||
// For wrapping textures created via GL elsewhere with our API only. Use with caution.
|
||||
LLImageGL(LLGLuint mTexName, U32 components, LLGLenum target, LLGLint formatInternal, LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode);
|
||||
|
||||
protected:
|
||||
virtual ~LLImageGL();
|
||||
|
||||
|
|
@ -234,6 +237,8 @@ protected:
|
|||
LLGLenum mFormatType;
|
||||
BOOL mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1)
|
||||
|
||||
BOOL mExternalTexture;
|
||||
|
||||
// STATICS
|
||||
public:
|
||||
static std::set<LLImageGL*> sImageList;
|
||||
|
|
@ -279,6 +284,8 @@ public:
|
|||
void setCategory(S32 category) {mCategory = category;}
|
||||
S32 getCategory()const {return mCategory;}
|
||||
|
||||
void setTexName(GLuint texName) { mTexName = texName; }
|
||||
|
||||
//for debug use: show texture size distribution
|
||||
//----------------------------------------
|
||||
static S32 sCurTexSizeBar ;
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ static const GLenum sGLTextureType[] =
|
|||
GL_TEXTURE_2D,
|
||||
GL_TEXTURE_RECTANGLE_ARB,
|
||||
GL_TEXTURE_CUBE_MAP_ARB,
|
||||
GL_TEXTURE_2D_MULTISAMPLE
|
||||
GL_TEXTURE_2D_MULTISAMPLE,
|
||||
GL_TEXTURE_3D
|
||||
};
|
||||
|
||||
static const GLint sGLAddressMode[] =
|
||||
|
|
@ -104,7 +105,7 @@ LLTexUnit::LLTexUnit(S32 index)
|
|||
mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
|
||||
mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
|
||||
mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
|
||||
mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0),
|
||||
mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mTexColorSpace(TCS_LINEAR),
|
||||
mHasMipMaps(false),
|
||||
mIndex(index)
|
||||
{
|
||||
|
|
@ -161,6 +162,8 @@ void LLTexUnit::refreshState(void)
|
|||
setTextureCombiner(mCurrColorOp, mCurrColorSrc1, mCurrColorSrc2, false);
|
||||
setTextureCombiner(mCurrAlphaOp, mCurrAlphaSrc1, mCurrAlphaSrc2, true);
|
||||
}
|
||||
|
||||
setTextureColorSpace(mTexColorSpace);
|
||||
}
|
||||
|
||||
void LLTexUnit::activate(void)
|
||||
|
|
@ -218,6 +221,8 @@ void LLTexUnit::disable(void)
|
|||
{
|
||||
glDisable(sGLTextureType[mCurrTexType]);
|
||||
}
|
||||
|
||||
setTextureColorSpace(TCS_LINEAR);
|
||||
|
||||
mCurrTexType = TT_NONE;
|
||||
}
|
||||
|
|
@ -254,7 +259,8 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
|
|||
gl_tex->mTexOptionsDirty = false;
|
||||
setTextureAddressMode(gl_tex->mAddressMode);
|
||||
setTextureFilteringOption(gl_tex->mFilterOption);
|
||||
}
|
||||
}
|
||||
setTextureColorSpace(mTexColorSpace);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -329,6 +335,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
|
|||
setTextureFilteringOption(texture->mFilterOption);
|
||||
stop_glerror();
|
||||
}
|
||||
setTextureColorSpace(mTexColorSpace);
|
||||
}
|
||||
|
||||
stop_glerror();
|
||||
|
|
@ -354,7 +361,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
|
|||
{
|
||||
activate();
|
||||
enable(LLTexUnit::TT_CUBE_MAP);
|
||||
mCurrTexture = cubeMap->mImages[0]->getTexName();
|
||||
mCurrTexture = cubeMap->mImages[0]->getTexName();
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);
|
||||
mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;
|
||||
cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory);
|
||||
|
|
@ -363,7 +370,8 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
|
|||
cubeMap->mImages[0]->mTexOptionsDirty = false;
|
||||
setTextureAddressMode(cubeMap->mImages[0]->mAddressMode);
|
||||
setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption);
|
||||
}
|
||||
}
|
||||
setTextureColorSpace(mTexColorSpace);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
@ -414,7 +422,8 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
|
|||
enable(type);
|
||||
mCurrTexture = texture;
|
||||
glBindTexture(sGLTextureType[type], texture);
|
||||
mHasMipMaps = hasMips;
|
||||
mHasMipMaps = hasMips;
|
||||
setTextureColorSpace(mTexColorSpace);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -434,6 +443,9 @@ void LLTexUnit::unbind(eTextureType type)
|
|||
if (mCurrTexType == type)
|
||||
{
|
||||
mCurrTexture = 0;
|
||||
|
||||
// Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping".
|
||||
mTexColorSpace = TCS_LINEAR;
|
||||
if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)
|
||||
{
|
||||
glBindTexture(sGLTextureType[type], sWhiteTexture);
|
||||
|
|
@ -837,6 +849,28 @@ void LLTexUnit::debugTextureUnit(void)
|
|||
}
|
||||
}
|
||||
|
||||
void LLTexUnit::setTextureColorSpace(eTextureColorSpace space) {
|
||||
mTexColorSpace = space;
|
||||
|
||||
#if USE_SRGB_DECODE
|
||||
if (gGLManager.mHasTexturesRGBDecode) {
|
||||
|
||||
if (space == TCS_SRGB) {
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
|
||||
}
|
||||
else {
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
|
||||
}
|
||||
|
||||
if (gDebugGL) {
|
||||
assert_glerror();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
|
||||
|
||||
}
|
||||
|
||||
LLLightState::LLLightState(S32 index)
|
||||
: mIndex(index),
|
||||
mEnabled(false),
|
||||
|
|
@ -849,9 +883,12 @@ LLLightState::LLLightState(S32 index)
|
|||
if (mIndex == 0)
|
||||
{
|
||||
mDiffuse.set(1,1,1,1);
|
||||
mDiffuseB.set(0,0,0,0);
|
||||
mSpecular.set(1,1,1,1);
|
||||
}
|
||||
|
||||
mSunIsPrimary = true;
|
||||
|
||||
mAmbient.set(0,0,0,1);
|
||||
mPosition.set(0,0,1,0);
|
||||
mSpotDirection.set(0,0,-1);
|
||||
|
|
@ -894,6 +931,24 @@ void LLLightState::setDiffuse(const LLColor4& diffuse)
|
|||
}
|
||||
}
|
||||
|
||||
void LLLightState::setDiffuseB(const LLColor4& diffuse)
|
||||
{
|
||||
if (mDiffuseB != diffuse)
|
||||
{
|
||||
++gGL.mLightHash;
|
||||
mDiffuseB = diffuse;
|
||||
}
|
||||
}
|
||||
|
||||
void LLLightState::setSunPrimary(bool v)
|
||||
{
|
||||
if (mSunIsPrimary != v)
|
||||
{
|
||||
++gGL.mLightHash;
|
||||
mSunIsPrimary = v;
|
||||
}
|
||||
}
|
||||
|
||||
void LLLightState::setAmbient(const LLColor4& ambient)
|
||||
{
|
||||
if (mAmbient != ambient)
|
||||
|
|
@ -1150,8 +1205,10 @@ void LLRender::syncLightState()
|
|||
|
||||
LLVector4 position[8];
|
||||
LLVector3 direction[8];
|
||||
LLVector3 attenuation[8];
|
||||
LLVector4 attenuation[8];
|
||||
LLVector3 diffuse[8];
|
||||
LLVector3 diffuse_b[8];
|
||||
bool sun_primary[8];
|
||||
|
||||
for (U32 i = 0; i < 8; i++)
|
||||
{
|
||||
|
|
@ -1159,17 +1216,21 @@ void LLRender::syncLightState()
|
|||
|
||||
position[i] = light->mPosition;
|
||||
direction[i] = light->mSpotDirection;
|
||||
attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[3]);
|
||||
attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[2], light->mSpecular.mV[3]);
|
||||
diffuse[i].set(light->mDiffuse.mV);
|
||||
diffuse_b[i].set(light->mDiffuseB.mV);
|
||||
sun_primary[i] = light->mSunIsPrimary;
|
||||
}
|
||||
|
||||
shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, 8, position[0].mV);
|
||||
shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, 8, direction[0].mV);
|
||||
shader->uniform3fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV);
|
||||
shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV);
|
||||
shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, 8, diffuse[0].mV);
|
||||
shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
|
||||
//HACK -- duplicate sunlight color for compatibility with drivers that can't deal with multiple shader objects referencing the same uniform
|
||||
shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
|
||||
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0);
|
||||
shader->uniform4fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV);
|
||||
shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
|
||||
shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1190,6 +1251,7 @@ void LLRender::syncMatrices()
|
|||
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
|
||||
|
||||
static glh::matrix4f cached_mvp;
|
||||
static glh::matrix4f cached_inv_mdv;
|
||||
static U32 cached_mvp_mdv_hash = 0xFFFFFFFF;
|
||||
static U32 cached_mvp_proj_hash = 0xFFFFFFFF;
|
||||
|
||||
|
|
@ -1203,12 +1265,18 @@ void LLRender::syncMatrices()
|
|||
bool mvp_done = false;
|
||||
|
||||
U32 i = MM_MODELVIEW;
|
||||
if (mMatHash[i] != shader->mMatHash[i])
|
||||
if (mMatHash[MM_MODELVIEW] != shader->mMatHash[MM_MODELVIEW])
|
||||
{ //update modelview, normal, and MVP
|
||||
glh::matrix4f& mat = mMatrix[i][mMatIdx[i]];
|
||||
glh::matrix4f& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]];
|
||||
|
||||
shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m);
|
||||
shader->mMatHash[i] = mMatHash[i];
|
||||
// if MDV has changed, update the cached inverse as well
|
||||
if (cached_mvp_mdv_hash != mMatHash[MM_MODELVIEW])
|
||||
{
|
||||
cached_inv_mdv = mat.inverse();
|
||||
}
|
||||
|
||||
shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, mat.m);
|
||||
shader->mMatHash[MM_MODELVIEW] = mMatHash[MM_MODELVIEW];
|
||||
|
||||
//update normal matrix
|
||||
S32 loc = shader->getUniformLocation(LLShaderMgr::NORMAL_MATRIX);
|
||||
|
|
@ -1216,7 +1284,7 @@ void LLRender::syncMatrices()
|
|||
{
|
||||
if (cached_normal_hash != mMatHash[i])
|
||||
{
|
||||
cached_normal = mat.inverse().transpose();
|
||||
cached_normal = cached_inv_mdv.transpose();
|
||||
cached_normal_hash = mMatHash[i];
|
||||
}
|
||||
|
||||
|
|
@ -1232,6 +1300,11 @@ void LLRender::syncMatrices()
|
|||
shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat);
|
||||
}
|
||||
|
||||
if (shader->getUniformLocation(LLShaderMgr::INVERSE_MODELVIEW_MATRIX))
|
||||
{
|
||||
shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, cached_inv_mdv.m);
|
||||
}
|
||||
|
||||
//update MVP matrix
|
||||
mvp_done = true;
|
||||
loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
|
||||
|
|
@ -1251,14 +1324,21 @@ void LLRender::syncMatrices()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
i = MM_PROJECTION;
|
||||
if (mMatHash[i] != shader->mMatHash[i])
|
||||
if (mMatHash[MM_PROJECTION] != shader->mMatHash[MM_PROJECTION])
|
||||
{ //update projection matrix, normal, and MVP
|
||||
glh::matrix4f& mat = mMatrix[i][mMatIdx[i]];
|
||||
glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
|
||||
|
||||
shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m);
|
||||
shader->mMatHash[i] = mMatHash[i];
|
||||
// it would be nice to have this automatically track the state of the proj matrix
|
||||
// but certain render paths (deferred lighting) require it to be mismatched *sigh*
|
||||
//if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX))
|
||||
//{
|
||||
// glh::matrix4f inv_proj = mat.inverse();
|
||||
// shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
|
||||
//}
|
||||
|
||||
shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m);
|
||||
shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION];
|
||||
|
||||
if (!mvp_done)
|
||||
{
|
||||
|
|
@ -1266,7 +1346,7 @@ void LLRender::syncMatrices()
|
|||
S32 loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
|
||||
if (loc > -1)
|
||||
{
|
||||
if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
|
||||
if (cached_mvp_mdv_hash != mMatHash[MM_PROJECTION] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
|
||||
{
|
||||
U32 mdv = MM_MODELVIEW;
|
||||
cached_mvp = mat;
|
||||
|
|
@ -1290,7 +1370,7 @@ void LLRender::syncMatrices()
|
|||
}
|
||||
|
||||
|
||||
if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting)
|
||||
if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting || shader->mFeatures.calculatesAtmospherics)
|
||||
{ //also sync light state
|
||||
syncLightState();
|
||||
}
|
||||
|
|
@ -1307,7 +1387,7 @@ void LLRender::syncMatrices()
|
|||
GL_TEXTURE,
|
||||
};
|
||||
|
||||
for (U32 i = 0; i < 2; ++i)
|
||||
for (U32 i = 0; i < MM_TEXTURE0; ++i)
|
||||
{
|
||||
if (mMatHash[i] != mCurMatHash[i])
|
||||
{
|
||||
|
|
@ -1317,11 +1397,11 @@ void LLRender::syncMatrices()
|
|||
}
|
||||
}
|
||||
|
||||
for (U32 i = 2; i < NUM_MATRIX_MODES; ++i)
|
||||
for (U32 i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i)
|
||||
{
|
||||
if (mMatHash[i] != mCurMatHash[i])
|
||||
{
|
||||
gGL.getTexUnit(i-2)->activate();
|
||||
gGL.getTexUnit(i-MM_TEXTURE0)->activate();
|
||||
glMatrixMode(mode[i]);
|
||||
glLoadMatrixf(mMatrix[i][mMatIdx[i]].m);
|
||||
mCurMatHash[i] = mMatHash[i];
|
||||
|
|
@ -1453,18 +1533,21 @@ void LLRender::multMatrix(const GLfloat* m)
|
|||
}
|
||||
}
|
||||
|
||||
void LLRender::matrixMode(U32 mode)
|
||||
void LLRender::matrixMode(eMatrixMode mode)
|
||||
{
|
||||
if (mode == MM_TEXTURE)
|
||||
{
|
||||
mode = MM_TEXTURE0 + gGL.getCurrentTexUnitIndex();
|
||||
U32 tex_index = gGL.getCurrentTexUnitIndex();
|
||||
// the shaders don't actually reference anything beyond texture_matrix0/1 outside of terrain rendering
|
||||
llassert_always(tex_index <= 3);
|
||||
mode = eMatrixMode(MM_TEXTURE0 + gGL.getCurrentTexUnitIndex());
|
||||
}
|
||||
|
||||
llassert(mode < NUM_MATRIX_MODES);
|
||||
mMatrixMode = mode;
|
||||
}
|
||||
|
||||
U32 LLRender::getMatrixMode()
|
||||
LLRender::eMatrixMode LLRender::getMatrixMode()
|
||||
{
|
||||
if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3)
|
||||
{ //always return MM_TEXTURE if current matrix mode points at any texture matrix
|
||||
|
|
@ -2331,3 +2414,85 @@ void LLRender::debugTexUnits(void)
|
|||
LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
glh::matrix4f copy_matrix(F32* src)
|
||||
{
|
||||
glh::matrix4f ret;
|
||||
ret.set_value(src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
glh::matrix4f get_current_modelview()
|
||||
{
|
||||
return copy_matrix(gGLModelView);
|
||||
}
|
||||
|
||||
glh::matrix4f get_current_projection()
|
||||
{
|
||||
return copy_matrix(gGLProjection);
|
||||
}
|
||||
|
||||
glh::matrix4f get_last_modelview()
|
||||
{
|
||||
return copy_matrix(gGLLastModelView);
|
||||
}
|
||||
|
||||
glh::matrix4f get_last_projection()
|
||||
{
|
||||
return copy_matrix(gGLLastProjection);
|
||||
}
|
||||
|
||||
void copy_matrix(const glh::matrix4f& src, F32* dst)
|
||||
{
|
||||
for (U32 i = 0; i < 16; i++)
|
||||
{
|
||||
dst[i] = src.m[i];
|
||||
}
|
||||
}
|
||||
|
||||
void set_current_modelview(const glh::matrix4f& mat)
|
||||
{
|
||||
copy_matrix(mat, gGLModelView);
|
||||
}
|
||||
|
||||
void set_current_projection(glh::matrix4f& mat)
|
||||
{
|
||||
copy_matrix(mat, gGLProjection);
|
||||
}
|
||||
|
||||
glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
|
||||
{
|
||||
glh::matrix4f ret(
|
||||
2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
|
||||
0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
|
||||
0.f, 0.f, -2.f/(zfar-znear), -(zfar+znear)/(zfar-znear),
|
||||
0.f, 0.f, 0.f, 1.f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
|
||||
{
|
||||
GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f);
|
||||
|
||||
return glh::matrix4f(f/aspect, 0, 0, 0,
|
||||
0, f, 0, 0,
|
||||
0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar),
|
||||
0, 0, -1.f, 0);
|
||||
}
|
||||
|
||||
glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up)
|
||||
{
|
||||
LLVector3 f = center-eye;
|
||||
f.normVec();
|
||||
up.normVec();
|
||||
LLVector3 s = f % up;
|
||||
LLVector3 u = s % f;
|
||||
|
||||
return glh::matrix4f(s[0], s[1], s[2], 0,
|
||||
u[0], u[1], u[2], 0,
|
||||
-f[0], -f[1], -f[2], 0,
|
||||
0, 0, 0, 1);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,10 +61,11 @@ public:
|
|||
typedef enum
|
||||
{
|
||||
TT_TEXTURE = 0, // Standard 2D Texture
|
||||
TT_RECT_TEXTURE, // Non power of 2 texture
|
||||
TT_CUBE_MAP, // 6-sided cube map texture
|
||||
TT_RECT_TEXTURE, // Non power of 2 texture
|
||||
TT_CUBE_MAP, // 6-sided cube map texture
|
||||
TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
|
||||
TT_NONE // No texture type is currently enabled
|
||||
TT_TEXTURE_3D, // standard 3D Texture
|
||||
TT_NONE, // No texture type is currently enabled
|
||||
} eTextureType;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -130,6 +131,12 @@ public:
|
|||
TBS_ONE_MINUS_CONST_ALPHA
|
||||
} eTextureBlendSrc;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TCS_LINEAR = 0,
|
||||
TCS_SRGB
|
||||
} eTextureColorSpace;
|
||||
|
||||
LLTexUnit(S32 index);
|
||||
|
||||
// Refreshes renderer state of the texture unit to the cached values
|
||||
|
|
@ -152,7 +159,7 @@ public:
|
|||
// Binds the LLImageGL to this texture unit
|
||||
// (automatically enables the unit for the LLImageGL's texture type)
|
||||
bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false);
|
||||
bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
|
||||
bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
|
||||
|
||||
// Binds a cubemap to this texture unit
|
||||
// (automatically enables the texture unit for cubemaps)
|
||||
|
|
@ -197,6 +204,10 @@ public:
|
|||
|
||||
void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; }
|
||||
|
||||
void setTextureColorSpace(eTextureColorSpace space);
|
||||
|
||||
eTextureColorSpace getCurrColorSpace() { return mTexColorSpace; }
|
||||
|
||||
protected:
|
||||
const S32 mIndex;
|
||||
U32 mCurrTexture;
|
||||
|
|
@ -208,6 +219,7 @@ protected:
|
|||
eTextureBlendOp mCurrAlphaOp;
|
||||
eTextureBlendSrc mCurrAlphaSrc1;
|
||||
eTextureBlendSrc mCurrAlphaSrc2;
|
||||
eTextureColorSpace mTexColorSpace;
|
||||
S32 mCurrColorScale;
|
||||
S32 mCurrAlphaScale;
|
||||
bool mHasMipMaps;
|
||||
|
|
@ -228,6 +240,7 @@ public:
|
|||
void enable();
|
||||
void disable();
|
||||
void setDiffuse(const LLColor4& diffuse);
|
||||
void setDiffuseB(const LLColor4& diffuse);
|
||||
void setAmbient(const LLColor4& ambient);
|
||||
void setSpecular(const LLColor4& specular);
|
||||
void setPosition(const LLVector4& position);
|
||||
|
|
@ -237,6 +250,7 @@ public:
|
|||
void setSpotExponent(const F32& exponent);
|
||||
void setSpotCutoff(const F32& cutoff);
|
||||
void setSpotDirection(const LLVector3& direction);
|
||||
void setSunPrimary(bool v);
|
||||
|
||||
protected:
|
||||
friend class LLRender;
|
||||
|
|
@ -244,6 +258,8 @@ protected:
|
|||
S32 mIndex;
|
||||
bool mEnabled;
|
||||
LLColor4 mDiffuse;
|
||||
LLColor4 mDiffuseB;
|
||||
bool mSunIsPrimary;
|
||||
LLColor4 mAmbient;
|
||||
LLColor4 mSpecular;
|
||||
LLVector4 mPosition;
|
||||
|
|
@ -264,10 +280,11 @@ public:
|
|||
|
||||
enum eTexIndex
|
||||
{
|
||||
DIFFUSE_MAP = 0,
|
||||
NORMAL_MAP,
|
||||
SPECULAR_MAP,
|
||||
NUM_TEXTURE_CHANNELS,
|
||||
DIFFUSE_MAP = 0,
|
||||
ALTERNATE_DIFFUSE_MAP = 1,
|
||||
NORMAL_MAP = 1,
|
||||
SPECULAR_MAP = 2,
|
||||
NUM_TEXTURE_CHANNELS = 3,
|
||||
};
|
||||
|
||||
enum eVolumeTexIndex
|
||||
|
|
@ -360,8 +377,8 @@ public:
|
|||
void loadMatrix(const GLfloat* m);
|
||||
void loadIdentity();
|
||||
void multMatrix(const GLfloat* m);
|
||||
void matrixMode(U32 mode);
|
||||
U32 getMatrixMode();
|
||||
void matrixMode(eMatrixMode mode);
|
||||
eMatrixMode getMatrixMode();
|
||||
|
||||
const glh::matrix4f& getModelviewMatrix();
|
||||
const glh::matrix4f& getProjectionMatrix();
|
||||
|
|
@ -450,7 +467,7 @@ public:
|
|||
private:
|
||||
friend class LLLightState;
|
||||
|
||||
U32 mMatrixMode;
|
||||
eMatrixMode mMatrixMode;
|
||||
U32 mMatIdx[NUM_MATRIX_MODES];
|
||||
U32 mMatHash[NUM_MATRIX_MODES];
|
||||
glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH];
|
||||
|
|
@ -495,4 +512,33 @@ extern S32 gGLViewport[4];
|
|||
|
||||
extern LLRender gGL;
|
||||
|
||||
// This rotation matrix moves the default OpenGL reference frame
|
||||
// (-Z at, Y up) to Cory's favorite reference frame (X at, Z up)
|
||||
const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X
|
||||
-1.f, 0.f, 0.f, 0.f, // -X becomes Y
|
||||
0.f, 1.f, 0.f, 0.f, // Y becomes Z
|
||||
0.f, 0.f, 0.f, 1.f };
|
||||
|
||||
glh::matrix4f copy_matrix(F32* src);
|
||||
glh::matrix4f get_current_modelview();
|
||||
glh::matrix4f get_current_projection();
|
||||
glh::matrix4f get_last_modelview();
|
||||
glh::matrix4f get_last_projection();
|
||||
|
||||
void copy_matrix(const glh::matrix4f& src, F32* dst);
|
||||
void set_current_modelview(const glh::matrix4f& mat);
|
||||
void set_current_projection(glh::matrix4f& mat);
|
||||
|
||||
glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar);
|
||||
glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
|
||||
glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up);
|
||||
|
||||
#if LL_RELEASE_FOR_DOWNLOAD
|
||||
#define LL_SHADER_LOADING_WARNS(...) LL_WARNS_ONCE("ShaderLoading")
|
||||
#define LL_SHADER_UNIFORM_ERRS(...) LL_WARNS_ONCE("Shader")
|
||||
#else
|
||||
#define LL_SHADER_LOADING_WARNS(...) LL_WARNS()
|
||||
#define LL_SHADER_UNIFORM_ERRS(...) LL_ERRS("Shader")
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -502,9 +502,26 @@ U32 LLRenderTarget::getNumTextures() const
|
|||
}
|
||||
|
||||
|
||||
void LLRenderTarget::bindTexture(U32 index, S32 channel)
|
||||
void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)
|
||||
{
|
||||
gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));
|
||||
|
||||
bool isSRGB = false;
|
||||
llassert(mInternalFormat.size() > index);
|
||||
switch (mInternalFormat[index])
|
||||
{
|
||||
case GL_SRGB_ALPHA:
|
||||
case GL_SRGB:
|
||||
case GL_SRGB8_ALPHA8:
|
||||
isSRGB = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options);
|
||||
gGL.getTexUnit(channel)->setTextureColorSpace(isSRGB ? LLTexUnit::TCS_SRGB : LLTexUnit::TCS_LINEAR);
|
||||
}
|
||||
|
||||
void LLRenderTarget::flush(bool fetch_depth)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue