summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2010-09-20 18:45:56 -0500
committerDave Parks <davep@lindenlab.com>2010-09-20 18:45:56 -0500
commitc42ed54b0a532cb4e0ad30a1b0b5038cef9938f2 (patch)
tree39eb08c897f9e59fe448a1f63b354f83b7309f0b /indra
parent2c4c1c47bce3db7420f0eb27bdaa7598fbbbb65a (diff)
Stop using ll_aligned_malloc/free in llvolume.
Fix for garbage data in vertex weight array crashing software skinning. Proper integration of picking for rigged attachhments. Optimization in LLDrawable::updateDistance (don't call updateRelativeXform, just use spatial group position).
Diffstat (limited to 'indra')
-rw-r--r--indra/llmath/llvolume.cpp108
-rw-r--r--indra/llmath/llvolume.h2
-rw-r--r--indra/newview/lldrawable.cpp12
-rw-r--r--indra/newview/lldrawpoolavatar.cpp10
-rw-r--r--indra/newview/llface.cpp32
-rw-r--r--indra/newview/llselectmgr.cpp50
-rw-r--r--indra/newview/llspatialpartition.cpp16
-rw-r--r--indra/newview/llvovolume.cpp114
-rw-r--r--indra/newview/llvovolume.h12
9 files changed, 247 insertions, 109 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 07339f7526..24528a8ce9 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1990,7 +1990,7 @@ void LLVolumeFace::VertexData::init()
{
if (!mData)
{
- mData = (LLVector4a*) ll_aligned_malloc_16(32);
+ mData = new LLVector4a[2];
}
}
@@ -2019,7 +2019,7 @@ const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolu
LLVolumeFace::VertexData::~VertexData()
{
- ll_aligned_free_16(mData);
+ delete [] mData;
}
LLVector4a& LLVolumeFace::VertexData::getPosition()
@@ -2257,12 +2257,12 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
U32 cur_influence = 0;
LLVector4 wght(0,0,0,0);
- while (joint != END_INFLUENCES)
+ while (joint != END_INFLUENCES && idx < weights.size())
{
U16 influence = weights[idx++];
influence |= ((U16) weights[idx++] << 8);
- F32 w = llmin((F32) influence / 65535.f, 0.99999f);
+ F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f);
wght.mV[cur_influence++] = (F32) joint + w;
if (cur_influence >= 4)
@@ -5230,7 +5230,7 @@ LLVolumeFace::LLVolumeFace() :
mWeights(NULL),
mOctree(NULL)
{
- mExtents = (LLVector4a*) ll_aligned_malloc_16(48);
+ mExtents = new LLVector4a[3];
mCenter = mExtents+2;
}
@@ -5251,7 +5251,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
mWeights(NULL),
mOctree(NULL)
{
- mExtents = (LLVector4a*) ll_aligned_malloc_16(48);
+ mExtents = new LLVector4a[3];
mCenter = mExtents+2;
*this = src;
}
@@ -5286,7 +5286,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
if (mNumVertices)
{
- S32 vert_size = mNumVertices*4*sizeof(F32);
+ S32 vert_size = mNumVertices*sizeof(LLVector4a);
S32 tc_size = (mNumVertices*8+0xF) & ~0xF;
LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);
@@ -5301,7 +5301,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
}
else
{
- ll_aligned_free_16(mBinormals);
+ delete [] mBinormals;
mBinormals = NULL;
}
@@ -5312,7 +5312,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
}
else
{
- ll_aligned_free_16(mWeights);
+ delete [] mWeights;
mWeights = NULL;
}
}
@@ -5330,7 +5330,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
LLVolumeFace::~LLVolumeFace()
{
- ll_aligned_free_16(mExtents);
+ delete [] mExtents;
mExtents = NULL;
freeData();
@@ -5338,17 +5338,17 @@ LLVolumeFace::~LLVolumeFace()
void LLVolumeFace::freeData()
{
- ll_aligned_free_16(mPositions);
+ delete [] mPositions;
mPositions = NULL;
- ll_aligned_free_16(mNormals);
+ delete [] mNormals;
mNormals = NULL;
- ll_aligned_free_16(mTexCoords);
+ delete [] mTexCoords;
mTexCoords = NULL;
- ll_aligned_free_16(mIndices);
+ delete [] mIndices;
mIndices = NULL;
- ll_aligned_free_16(mBinormals);
+ delete [] mBinormals;
mBinormals = NULL;
- ll_aligned_free_16(mWeights);
+ delete [] mWeights;
mWeights = NULL;
delete mOctree;
@@ -5461,18 +5461,13 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
}
-void LLVolumeFace::createOctree(F32 scaler)
+void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size)
{
if (mOctree)
{
return;
}
- LLVector4a center;
- LLVector4a size;
- center.splat(0.f);
- size.splat(0.5f);
-
mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL);
new LLVolumeOctreeListener(mOctree);
@@ -6166,21 +6161,21 @@ void LLVolumeFace::createBinormals()
void LLVolumeFace::resizeVertices(S32 num_verts)
{
- ll_aligned_free_16(mPositions);
- ll_aligned_free_16(mNormals);
- ll_aligned_free_16(mBinormals);
- ll_aligned_free_16(mTexCoords);
+ delete [] mPositions;
+ delete [] mNormals;
+ delete [] mBinormals;
+ delete [] mTexCoords;
mBinormals = NULL;
if (num_verts)
{
- mPositions = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
- mNormals = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
+ mPositions = new LLVector4a[num_verts];
+ mNormals = new LLVector4a[num_verts];
//pad texture coordinate block end to allow for QWORD reads
S32 size = ((num_verts*8) + 0xF) & ~0xF;
- mTexCoords = (LLVector2*) ll_aligned_malloc_16(size);
+ mTexCoords = new LLVector2[size/8];
}
else
{
@@ -6204,20 +6199,20 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
S32 old_size = mNumVertices*16;
//positions
- LLVector4a* dst = (LLVector4a*) ll_aligned_malloc_16(new_size);
+ LLVector4a* dst = new LLVector4a[new_verts];
if (mPositions)
{
LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mPositions, old_size);
- ll_aligned_free_16(mPositions);
+ delete [] mPositions;
}
mPositions = dst;
//normals
- dst = (LLVector4a*) ll_aligned_malloc_16(new_size);
+ dst = new LLVector4a[new_verts];
if (mNormals)
{
LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mNormals, old_size);
- ll_aligned_free_16(mNormals);
+ delete [] mNormals;
}
mNormals = dst;
@@ -6225,19 +6220,18 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
new_size = ((new_verts*8)+0xF) & ~0xF;
old_size = ((mNumVertices*8)+0xF) & ~0xF;
- dst = (LLVector4a*) ll_aligned_malloc_16(new_size);
{
- LLVector2* dst = (LLVector2*) ll_aligned_malloc_16(new_size);
+ LLVector2* dst = new LLVector2[new_size/8];
if (mTexCoords)
{
LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mTexCoords, old_size);
- ll_aligned_free_16(mTexCoords);
+ delete [] mTexCoords;
}
+ mTexCoords = dst;
}
- mTexCoords = (LLVector2*) dst;
//just clear binormals
- ll_aligned_free_16(mBinormals);
+ delete [] mBinormals;
mBinormals = NULL;
mPositions[mNumVertices] = pos;
@@ -6249,26 +6243,26 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
void LLVolumeFace::allocateBinormals(S32 num_verts)
{
- ll_aligned_free_16(mBinormals);
- mBinormals = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
+ delete [] mBinormals;
+ mBinormals = new LLVector4a[num_verts];
}
void LLVolumeFace::allocateWeights(S32 num_verts)
{
- ll_aligned_free_16(mWeights);
- mWeights = (LLVector4a*) ll_aligned_malloc_16(num_verts*16);
+ delete [] mWeights;
+ mWeights = new LLVector4a[num_verts];
}
void LLVolumeFace::resizeIndices(S32 num_indices)
{
- ll_aligned_free_16(mIndices);
-
+ delete [] mIndices;
+
if (num_indices)
{
//pad index block end to allow for QWORD reads
S32 size = ((num_indices*2) + 0xF) & ~0xF;
- mIndices = (U16*) ll_aligned_malloc_16(size);
+ mIndices = new U16[size/2];
}
else
{
@@ -6286,11 +6280,11 @@ void LLVolumeFace::pushIndex(const U16& idx)
S32 old_size = ((mNumIndices*2)+0xF) & ~0xF;
if (new_size != old_size)
{
- U16* dst = (U16*) ll_aligned_malloc_16(new_size);
+ U16* dst = new U16[new_size/2];
if (mIndices)
{
LLVector4a::memcpyNonAliased16((F32*) dst, (F32*) mIndices, old_size);
- ll_aligned_free_16(mIndices);
+ delete [] mIndices;
}
mIndices = dst;
}
@@ -6333,9 +6327,9 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
}
//allocate new buffer space
- LLVector4a* new_pos = (LLVector4a*) ll_aligned_malloc_16(new_count*16);
- LLVector4a* new_norm = (LLVector4a*) ll_aligned_malloc_16(new_count*16);
- LLVector2* new_tc = (LLVector2*) ll_aligned_malloc_16((new_count*8+0xF) & ~0xF);
+ LLVector4a* new_pos = new LLVector4a[new_count];
+ LLVector4a* new_norm = new LLVector4a[new_count];
+ LLVector2* new_tc = new LLVector2[((new_count*8+0xF) & ~0xF)/8];
if (mNumVertices > 0)
@@ -6346,10 +6340,10 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
}
//free old buffer space
- ll_aligned_free_16(mPositions);
- ll_aligned_free_16(mNormals);
- ll_aligned_free_16(mTexCoords);
-
+ delete [] mPositions;
+ delete [] mNormals;
+ delete [] mTexCoords;
+
//point to new buffers
mPositions = new_pos;
mNormals = new_norm;
@@ -6399,7 +6393,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
new_count = mNumIndices + face.mNumIndices;
//allocate new index buffer
- U16* new_indices = (U16*) ll_aligned_malloc_16((new_count*2+0xF) & ~0xF);
+ U16* new_indices = new U16[((new_count*2+0xF) & ~0xF)/2];
if (mNumIndices > 0)
{ //copy old index buffer
S32 old_size = (mNumIndices*2+0xF) & ~0xF;
@@ -6407,8 +6401,8 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
}
//free old index buffer
- ll_aligned_free_16(mIndices);
-
+ delete [] mIndices;
+
//point to new index buffer
mIndices = new_indices;
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index ff5e3d9dfa..32364bd4b8 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -882,7 +882,7 @@ public:
};
void optimize(F32 angle_cutoff = 2.f);
- void createOctree(F32 scaler = 0.25f);
+ void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
enum
{
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 5949a373ae..efbb62011c 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -191,15 +191,6 @@ LLVOVolume* LLDrawable::getVOVolume() const
const LLMatrix4& LLDrawable::getRenderMatrix() const
{
- if (LLDrawable::isState(LLDrawable::RIGGED))
- {
- LLVOAvatar* avatar = mVObjp->getAvatar();
- if (avatar)
- {
- return avatar->mDrawable->getWorldMatrix();
- }
- }
-
return isRoot() ? getWorldMatrix() : getParent()->getWorldMatrix();
}
@@ -727,8 +718,7 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
LLVOVolume* volume = getVOVolume();
if (volume)
{
- volume->updateRelativeXform();
- pos = volume->getRelativeXform().getTranslation();
+ pos.set(getPositionGroup().getF32ptr());
if (isStatic())
{
pos += volume->getRegion()->getOriginAgent();
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index ccc060f3fa..5cf6082f12 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -1325,6 +1325,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
#if LL_MESH_ENABLED
void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
{
+ LLVector4a* weight = vol_face.mWeights;
+ if (!weight)
+ {
+ return;
+ }
+
LLVertexBuffer* buffer = face->mVertexBuffer;
U32 data_mask = 0;
@@ -1403,8 +1409,6 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
}
}
- LLVector4a* weight = vol_face.mWeights;
-
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
@@ -1422,7 +1426,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
{
F32 w = weight[j][k];
- idx[k] = (S32) floorf(w);
+ idx[k] = llclamp((S32) floorf(w), 0, 63);
wght[k] = w - floorf(w);
scale += wght[k];
}
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 9a178985cf..3fa60e9f1e 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -556,8 +556,36 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
}
glColor4fv(color.mV);
- mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
- mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
+
+ if (mDrawablep->isState(LLDrawable::RIGGED))
+ {
+ LLVOVolume* volume = mDrawablep->getVOVolume();
+ if (volume)
+ {
+ LLRiggedVolume* rigged = volume->getRiggedVolume();
+ if (rigged)
+ {
+ LLGLEnable offset(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-1.f, -1.f);
+ glMultMatrixf((F32*) volume->getRelativeXform().mMatrix);
+ const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset());
+ LLVertexBuffer::unbind();
+ glVertexPointer(3, GL_FLOAT, 16, vol_face.mPositions);
+ if (vol_face.mTexCoords)
+ {
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords);
+ }
+ glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ }
+ }
+ else
+ {
+ mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex);
+ mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0);
+ }
gGL.popMatrix();
}
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index ff2929695d..21f7e780e2 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -5395,6 +5395,42 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power)
return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id));
}
+
+//helper function for pushing relevant vertices from drawable to GL
+void pushWireframe(LLDrawable* drawable)
+{
+ if (drawable->isState(LLDrawable::RIGGED))
+ { //render straight from rigged volume if this is a rigged attachment
+ LLVOVolume* vobj = drawable->getVOVolume();
+ if (vobj)
+ {
+ vobj->updateRiggedVolume();
+ LLRiggedVolume* rigged_volume = vobj->getRiggedVolume();
+ if (rigged_volume)
+ {
+ LLVertexBuffer::unbind();
+ gGL.pushMatrix();
+ glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix);
+ for (S32 i = 0; i < rigged_volume->getNumVolumeFaces(); ++i)
+ {
+ const LLVolumeFace& face = rigged_volume->getVolumeFace(i);
+ glVertexPointer(3, GL_FLOAT, 16, face.mPositions);
+ glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
+ }
+ gGL.popMatrix();
+ }
+ }
+ }
+ else
+ {
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ LLFace* face = drawable->getFace(i);
+ pushVerts(face, LLVertexBuffer::MAP_VERTEX);
+ }
+ }
+}
+
void LLSelectNode::renderOneWireframe(const LLColor4& color)
{
LLViewerObject* objectp = getObject();
@@ -5442,11 +5478,7 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color)
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
{
glColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
- for (S32 i = 0; i < drawable->getNumFaces(); ++i)
- {
- LLFace* face = drawable->getFace(i);
- pushVerts(face, LLVertexBuffer::MAP_VERTEX);
- }
+ pushWireframe(drawable);
}
}
@@ -5455,13 +5487,9 @@ void LLSelectNode::renderOneWireframe(const LLColor4& color)
glColor4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2);
LLGLEnable offset(GL_POLYGON_OFFSET_LINE);
- glPolygonOffset(3.f, 2.f);
+ glPolygonOffset(3.f, 3.f);
glLineWidth(3.f);
- for (S32 i = 0; i < drawable->getNumFaces(); ++i)
- {
- LLFace* face = drawable->getFace(i);
- pushVerts(face, LLVertexBuffer::MAP_VERTEX);
- }
+ pushWireframe(drawable);
glLineWidth(1.f);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
gGL.popMatrix();
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 191cdac981..0f9f35dc57 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -3121,9 +3121,11 @@ void renderRaycast(LLDrawable* drawablep)
LLVOVolume* vobj = drawablep->getVOVolume();
LLVolume* volume = vobj->getVolume();
+ bool transform = true;
if (drawablep->isState(LLDrawable::RIGGED))
{
- volume = NULL;
+ volume = vobj->getRiggedVolume();
+ transform = false;
}
if (volume)
@@ -3140,8 +3142,16 @@ void renderRaycast(LLDrawable* drawablep)
glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix);
LLVector3 start, end;
- start = vobj->agentPositionToVolume(gDebugRaycastStart);
- end = vobj->agentPositionToVolume(gDebugRaycastEnd);
+ if (transform)
+ {
+ start = vobj->agentPositionToVolume(gDebugRaycastStart);
+ end = vobj->agentPositionToVolume(gDebugRaycastEnd);
+ }
+ else
+ {
+ start = gDebugRaycastStart;
+ end = gDebugRaycastEnd;
+ }
LLVector4a starta, enda;
starta.load3(start.mV);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 60bdfc24b9..f09ce5b363 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1358,8 +1358,9 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
LLVector4a min,max;
- BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION) || mRiggedVolume.notNull();
+ BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED);
+ bool rigged = false;
LLVolume* volume = mRiggedVolume;
if (!volume)
{
@@ -1424,10 +1425,19 @@ void LLVOVolume::updateRelativeXform()
LLDrawable* drawable = mDrawable;
- if (drawable->isState(LLDrawable::RIGGED))
- {
- mRelativeXform.setIdentity();
- mRelativeXformInvTrans.setIdentity();
+ if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull())
+ { //rigged volume (which is in agent space) is used for generating bounding boxes etc
+ //inverse of render matrix should go to partition space
+ mRelativeXform = getRenderMatrix();
+
+ F32* dst = (F32*) mRelativeXformInvTrans.mMatrix;
+ F32* src = (F32*) mRelativeXform.mMatrix;
+ dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];
+ dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6];
+ dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10];
+
+ mRelativeXform.invert();
+ mRelativeXformInvTrans.transpose();
}
else if (drawable->isActive())
{
@@ -3421,12 +3431,15 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
LLVolume* volume = getVolume();
+ bool transform = true;
+
if (mDrawable->isState(LLDrawable::RIGGED))
{
if (LLFloater::isVisible(gFloaterTools) && getAvatar()->isSelf())
{
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
volume = mRiggedVolume;
+ transform = false;
}
else
{ //cannot pick rigged attachments on other avatars or when not in build mode
@@ -3438,8 +3451,16 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
{
LLVector3 v_start, v_end, v_dir;
- v_start = agentPositionToVolume(start);
- v_end = agentPositionToVolume(end);
+ if (transform)
+ {
+ v_start = agentPositionToVolume(start);
+ v_end = agentPositionToVolume(end);
+ }
+ else
+ {
+ v_start = start;
+ v_end = end;
+ }
LLVector3 p;
LLVector3 n;
@@ -3499,18 +3520,40 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
if (intersection != NULL)
{
- *intersection = volumePositionToAgent(p); // must map back to agent space
+ if (transform)
+ {
+ *intersection = volumePositionToAgent(p); // must map back to agent space
+ }
+ else
+ {
+ *intersection = p;
+ }
}
if (normal != NULL)
{
- *normal = volumeDirectionToAgent(n);
+ if (transform)
+ {
+ *normal = volumeDirectionToAgent(n);
+ }
+ else
+ {
+ *normal = n;
+ }
+
(*normal).normVec();
}
if (bi_normal != NULL)
{
- *bi_normal = volumeDirectionToAgent(bn);
+ if (transform)
+ {
+ *bi_normal = volumeDirectionToAgent(bn);
+ }
+ else
+ {
+ *bi_normal = bn;
+ }
(*bi_normal).normVec();
}
@@ -3528,18 +3571,49 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
return ret;
}
+bool LLVOVolume::treatAsRigged()
+{
+ return LLFloater::isVisible(gFloaterTools) &&
+ isAttachment() &&
+ getAvatar() &&
+ getAvatar()->isSelf() &&
+ mDrawable.notNull() &&
+ mDrawable->isState(LLDrawable::RIGGED);
+}
+
+LLRiggedVolume* LLVOVolume::getRiggedVolume()
+{
+ return mRiggedVolume;
+}
+
+void LLVOVolume::clearRiggedVolume()
+{
+ if (mRiggedVolume.notNull())
+ {
+ mRiggedVolume = NULL;
+ updateRelativeXform();
+ }
+}
+
void LLVOVolume::updateRiggedVolume()
{
//Update mRiggedVolume to match current animation frame of avatar.
//Also update position/size in octree.
+ if (!treatAsRigged())
+ {
+ clearRiggedVolume();
+
+ return;
+ }
+
LLVolume* volume = getVolume();
const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID());
if (!skin)
{
- mRiggedVolume = NULL;
+ clearRiggedVolume();
return;
}
@@ -3547,7 +3621,7 @@ void LLVOVolume::updateRiggedVolume()
if (!avatar)
{
- mRiggedVolume = NULL;
+ clearRiggedVolume();
return;
}
@@ -3555,6 +3629,7 @@ void LLVOVolume::updateRiggedVolume()
{
LLVolumeParams p;
mRiggedVolume = new LLRiggedVolume(p);
+ updateRelativeXform();
}
mRiggedVolume->update(skin, avatar, volume);
@@ -3592,12 +3667,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
//build matrix palette
LLMatrix4a mp[64];
LLMatrix4* mat = (LLMatrix4*) mp;
-
- LLMatrix4 agent_to_root;
-
- LLVector4a origin;
- origin.load3(avatar->getPositionAgent().mV);
-
+
for (U32 j = 0; j < skin->mJointNames.size(); ++j)
{
LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);
@@ -3661,7 +3731,6 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
LLVector4a dst;
bind_shape_matrix.affineTransform(v, t);
final_mat.affineTransform(t, dst);
- dst.sub(origin);
pos[j] = dst;
}
@@ -3687,7 +3756,12 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
LLFastTimer t(FTM_RIGGED_OCTREE);
delete dst_face.mOctree;
dst_face.mOctree = NULL;
- dst_face.createOctree(2.f);
+
+ LLVector4a size;
+ size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]);
+ size.splat(size.getLength3().getF32()*0.5f);
+
+ dst_face.createOctree(1.f);
}
}
}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index d868099eeb..f058710a27 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -306,7 +306,17 @@ public:
//rigged volume update (for raycasting)
void updateRiggedVolume();
- LLRiggedVolume* getRiggedVolume() { return mRiggedVolume; }
+ LLRiggedVolume* getRiggedVolume();
+
+ //returns true if volume should be treated as a rigged volume
+ // - Build tools are open
+ // - object is an attachment
+ // - object is attached to self
+ // - object is rendered as rigged
+ bool treatAsRigged();
+
+ //clear out rigged volume and revert back to non-rigged state for picking/LOD/distance updates
+ void clearRiggedVolume();
protected:
S32 computeLODDetail(F32 distance, F32 radius);