summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llmath/llvolume.cpp17
-rw-r--r--indra/llmath/llvolume.h4
-rw-r--r--indra/llmath/llvolumeoctree.cpp8
-rw-r--r--indra/newview/lldrawable.cpp14
-rw-r--r--indra/newview/lldrawable.h56
-rw-r--r--indra/newview/llface.cpp2
-rw-r--r--indra/newview/llspatialpartition.cpp80
-rw-r--r--indra/newview/llviewerobject.cpp14
-rw-r--r--indra/newview/llvovolume.cpp230
-rw-r--r--indra/newview/llvovolume.h22
10 files changed, 372 insertions, 75 deletions
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 4798197921..07339f7526 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2569,14 +2569,13 @@ void LLVolume::makeTetrahedron()
mIsTetrahedron = TRUE;
}
-void LLVolume::copyVolumeFaces(LLVolume* volume)
+void LLVolume::copyVolumeFaces(const LLVolume* volume)
{
mVolumeFaces = volume->mVolumeFaces;
mSculptLevel = 0;
mIsTetrahedron = FALSE;
}
-
S32 LLVolume::getNumFaces() const
{
#if LL_MESH_ENABLED
@@ -5462,12 +5461,17 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
}
-void LLVolumeFace::createOctree()
+void LLVolumeFace::createOctree(F32 scaler)
{
+ if (mOctree)
+ {
+ return;
+ }
+
LLVector4a center;
LLVector4a size;
center.splat(0.f);
- size.splat(1.f);
+ size.splat(0.5f);
mOctree = new LLOctreeRoot<LLVolumeTriangle>(center, size, NULL);
new LLVolumeOctreeListener(mOctree);
@@ -5511,12 +5515,15 @@ void LLVolumeFace::createOctree()
LLVector4a size;
size.setSub(max,min);
- tri->mRadius = size.getLength3().getF32() * 0.5f;
+ tri->mRadius = size.getLength3().getF32() * scaler;
//insert
mOctree->insert(tri);
}
+ //remove unneeded octree layers
+ while (!mOctree->balance()) { }
+
//calculate AABB for each node
LLVolumeOctreeRebound rebound(this);
rebound.traverse(mOctree);
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index af28337f57..ff5e3d9dfa 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();
+ void createOctree(F32 scaler = 0.25f);
enum
{
@@ -1044,7 +1044,7 @@ public:
LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
- void copyVolumeFaces(LLVolume* volume);
+ void copyVolumeFaces(const LLVolume* volume);
private:
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp
index 12fe90f35d..cb6211f63c 100644
--- a/indra/llmath/llvolumeoctree.cpp
+++ b/indra/llmath/llvolumeoctree.cpp
@@ -223,14 +223,14 @@ void LLVolumeOctreeValidate::visit(const LLOctreeNode<LLVolumeTriangle>* branch)
test_min.setSub(center, size);
test_max.setAdd(center, size);
- if (!test_min.equals3(min) ||
- !test_max.equals3(max))
+ if (!test_min.equals3(min, 0.001f) ||
+ !test_max.equals3(max, 0.001f))
{
llerrs << "Bad bounding box data found." << llendl;
}
- test_min.sub(LLVector4a::getEpsilon());
- test_max.add(LLVector4a::getEpsilon());
+ test_min.sub(LLVector4a(0.001f));
+ test_max.add(LLVector4a(0.001f));
for (U32 i = 0; i < branch->getChildCount(); ++i)
{
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 68f52e04bc..5949a373ae 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -189,6 +189,20 @@ 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();
+}
+
BOOL LLDrawable::isLight() const
{
LLViewerObject* objectp = mVObjp;
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index fc90bc57c4..a17e2172aa 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -101,7 +101,7 @@ public:
LLVOVolume* getVOVolume() const; // cast mVObjp tp LLVOVolume if OK
const LLMatrix4& getWorldMatrix() const { return mXform.getWorldMatrix(); }
- const LLMatrix4& getRenderMatrix() const { return isRoot() ? getWorldMatrix() : getParent()->getWorldMatrix(); }
+ const LLMatrix4& getRenderMatrix() const;
void setPosition(LLVector3 v) const { }
const LLVector3& getPosition() const { return mXform.getPosition(); }
const LLVector3& getWorldPosition() const { return mXform.getPositionW(); }
@@ -250,35 +250,37 @@ public:
typedef enum e_drawable_flags
{
- IN_REBUILD_Q1 = 0x00000002,
- IN_REBUILD_Q2 = 0x00000004,
- IN_LIGHT_Q = 0x00000008,
- EARLY_MOVE = 0x00000010,
- MOVE_UNDAMPED = 0x00000020,
- ON_MOVE_LIST = 0x00000040,
- USE_BACKLIGHT = 0x00000080,
- UV = 0x00000100,
- UNLIT = 0x00000200,
- LIGHT = 0x00000400,
- LIGHTING_BUILT = 0x00000800,
- REBUILD_VOLUME = 0x00001000, //volume changed LOD or parameters, or vertex buffer changed
- REBUILD_TCOORD = 0x00002000, //texture coordinates changed
- REBUILD_COLOR = 0x00004000, //color changed
- REBUILD_POSITION= 0x00010000, //vertex positions/normals changed
+ IN_REBUILD_Q1 = 0x00000001,
+ IN_REBUILD_Q2 = 0x00000002,
+ IN_LIGHT_Q = 0x00000004,
+ EARLY_MOVE = 0x00000008,
+ MOVE_UNDAMPED = 0x00000010,
+ ON_MOVE_LIST = 0x00000020,
+ USE_BACKLIGHT = 0x00000040,
+ UV = 0x00000080,
+ UNLIT = 0x00000100,
+ LIGHT = 0x00000200,
+ LIGHTING_BUILT = 0x00000400,
+ REBUILD_VOLUME = 0x00000800, //volume changed LOD or parameters, or vertex buffer changed
+ REBUILD_TCOORD = 0x00001000, //texture coordinates changed
+ REBUILD_COLOR = 0x00002000, //color changed
+ REBUILD_POSITION= 0x00004000, //vertex positions/normals changed
REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR,
REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR,
REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_VOLUME,
- ON_SHIFT_LIST = 0x00100000,
- BLOCKER = 0x00400000,
- ACTIVE = 0x00800000,
- DEAD = 0x01000000,
- INVISIBLE = 0x02000000, // stay invisible until flag is cleared
- NEARBY_LIGHT = 0x04000000, // In gPipeline.mNearbyLightSet
- BUILT = 0x08000000,
- FORCE_INVISIBLE = 0x10000000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned)
- CLEAR_INVISIBLE = 0x20000000, // clear FORCE_INVISIBLE next draw frame
- REBUILD_SHADOW = 0x40000000,
- HAS_ALPHA = 0x80000000,
+ REBUILD_RIGGED = 0x00008000,
+ ON_SHIFT_LIST = 0x00010000,
+ BLOCKER = 0x00020000,
+ ACTIVE = 0x00040000,
+ DEAD = 0x00080000,
+ INVISIBLE = 0x00100000, // stay invisible until flag is cleared
+ NEARBY_LIGHT = 0x00200000, // In gPipeline.mNearbyLightSet
+ BUILT = 0x00400000,
+ FORCE_INVISIBLE = 0x00800000, // stay invis until CLEAR_INVISIBLE is set (set of orphaned)
+ CLEAR_INVISIBLE = 0x01000000, // clear FORCE_INVISIBLE next draw frame
+ REBUILD_SHADOW = 0x02000000,
+ HAS_ALPHA = 0x04000000,
+ RIGGED = 0x08000000,
} EDrawableFlags;
LLXformMatrix mXform;
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 7c24eb77cd..9a178985cf 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -720,7 +720,7 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
LLMemType mt1(LLMemType::MTYPE_DRAWABLE);
//get bounding box
- if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
+ if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION | LLDrawable::REBUILD_RIGGED))
{
//VECTORIZE THIS
LLMatrix4a mat_vert;
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 2f0641489d..191cdac981 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -3047,19 +3047,21 @@ public:
LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) branch->getListener(0);
LLVector3 center, size;
- center.set(vl->mBounds[0].getF32ptr());
- size.set(vl->mBounds[1].getF32ptr());
-
+
if (branch->getData().empty())
{
gGL.color3f(1.f,0.2f,0.f);
+ center.set(branch->getCenter().getF32ptr());
+ size.set(branch->getSize().getF32ptr());
}
else
{
gGL.color3f(0.75f, 1.f, 0.f);
+ center.set(vl->mBounds[0].getF32ptr());
+ size.set(vl->mBounds[1].getF32ptr());
}
-
- drawBoxOutline(center, size);
+
+ drawBoxOutline(center, size);
for (U32 i = 0; i < 2; i++)
{
@@ -3072,10 +3074,7 @@ public:
else
{
gGL.color4f(0,0.5f,0.5f, 0.25f);
- if (!branch->getData().empty())
- {
- drawBoxOutline(center, size);
- }
+ drawBoxOutline(center, size);
}
if (i == 1)
@@ -3121,34 +3120,53 @@ void renderRaycast(LLDrawable* drawablep)
LLVOVolume* vobj = drawablep->getVOVolume();
LLVolume* volume = vobj->getVolume();
- for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
+
+ if (drawablep->isState(LLDrawable::RIGGED))
+ {
+ volume = NULL;
+ }
+
+ if (volume)
{
- const LLVolumeFace& face = volume->getVolumeFace(i);
- if (!face.mOctree)
+ for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
{
- ((LLVolumeFace*) &face)->createOctree();
- }
+ const LLVolumeFace& face = volume->getVolumeFace(i);
+ if (!face.mOctree)
+ {
+ ((LLVolumeFace*) &face)->createOctree();
+ }
- gGL.pushMatrix();
- glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix);
- LLVector3 start, end;
- start = vobj->agentPositionToVolume(gDebugRaycastStart);
- end = vobj->agentPositionToVolume(gDebugRaycastEnd);
+ gGL.pushMatrix();
+ glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix);
- LLVector4a starta, enda;
- starta.load3(start.mV);
- enda.load3(end.mV);
- LLVector4a dir;
- dir.setSub(enda, starta);
+ LLVector3 start, end;
+ start = vobj->agentPositionToVolume(gDebugRaycastStart);
+ end = vobj->agentPositionToVolume(gDebugRaycastEnd);
- F32 t = 1.f;
+ LLVector4a starta, enda;
+ starta.load3(start.mV);
+ enda.load3(end.mV);
+ LLVector4a dir;
+ dir.setSub(enda, starta);
- LLRenderOctreeRaycast render(starta, dir, &t);
- gGL.flush();
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- render.traverse(face.mOctree);
- gGL.popMatrix();
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ F32 t = 1.f;
+
+ LLRenderOctreeRaycast render(starta, dir, &t);
+ gGL.flush();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ {
+ //render face positions
+ LLVertexBuffer::unbind();
+ glColor4f(0,1,1,0.5f);
+ glVertexPointer(3, GL_FLOAT, sizeof(LLVector4a), face.mPositions);
+ glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices);
+ }
+
+ render.traverse(face.mOctree);
+ gGL.popMatrix();
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
}
}
else if (drawablep->isAvatar())
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index fd2212f25d..4c1a1958e8 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -3279,6 +3279,15 @@ const LLVector3 LLViewerObject::getPositionEdit() const
const LLVector3 LLViewerObject::getRenderPosition() const
{
+ if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED))
+ {
+ LLVOAvatar* avatar = getAvatar();
+ if (avatar)
+ {
+ return avatar->getPositionAgent();
+ }
+ }
+
if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
{
return getPositionAgent();
@@ -3297,6 +3306,11 @@ const LLVector3 LLViewerObject::getPivotPositionAgent() const
const LLQuaternion LLViewerObject::getRenderRotation() const
{
LLQuaternion ret;
+ if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED))
+ {
+ return ret;
+ }
+
if (mDrawable.isNull() || mDrawable->isStatic())
{
ret = getRotationEdit();
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 5448e7dcd9..60bdfc24b9 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -41,9 +41,11 @@
#include "llviewercontrol.h"
#include "lldir.h"
#include "llflexibleobject.h"
+#include "llfloatertools.h"
#include "llmaterialtable.h"
#include "llprimitive.h"
#include "llvolume.h"
+#include "llvolumeoctree.h"
#include "llvolumemgr.h"
#include "llvolumemessage.h"
#include "material_codes.h"
@@ -70,6 +72,7 @@
#include "llselectmgr.h"
#include "pipeline.h"
#include "llsdutil.h"
+#include "llmatrix4a.h"
#include "llmediaentry.h"
#include "llmediadataclient.h"
#include "llmeshrepository.h"
@@ -1355,7 +1358,13 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
LLVector4a min,max;
- BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION);
+ BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION) || mRiggedVolume.notNull();
+
+ LLVolume* volume = mRiggedVolume;
+ if (!volume)
+ {
+ volume = getVolume();
+ }
for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++)
{
@@ -1364,7 +1373,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
{
continue;
}
- res &= face->genVolumeBBoxes(*getVolume(), i,
+ res &= face->genVolumeBBoxes(*volume, i,
mRelativeXform, mRelativeXformInvTrans,
(mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global);
@@ -1415,7 +1424,12 @@ void LLVOVolume::updateRelativeXform()
LLDrawable* drawable = mDrawable;
- if (drawable->isActive())
+ if (drawable->isState(LLDrawable::RIGGED))
+ {
+ mRelativeXform.setIdentity();
+ mRelativeXformInvTrans.setIdentity();
+ }
+ else if (drawable->isActive())
{
// setup relative transforms
LLQuaternion delta_rot;
@@ -1497,11 +1511,22 @@ void LLVOVolume::updateRelativeXform()
static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies");
static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives");
+static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged");
BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
{
LLFastTimer t(FTM_UPDATE_PRIMITIVES);
+ if (mDrawable->isState(LLDrawable::REBUILD_RIGGED))
+ {
+ {
+ LLFastTimer t(FTM_UPDATE_RIGGED_VOLUME);
+ updateRiggedVolume();
+ }
+ genBBoxes(FALSE);
+ mDrawable->clearState(LLDrawable::REBUILD_RIGGED);
+ }
+
if (mVolumeImpl != NULL)
{
BOOL res;
@@ -1597,7 +1622,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
{
LLPipeline::sCompiles++;
}
-
+
mVolumeChanged = FALSE;
mLODChanged = FALSE;
mSculptChanged = FALSE;
@@ -2724,6 +2749,11 @@ BOOL LLVOVolume::isVolumeGlobal() const
{
return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE;
}
+ else if (mRiggedVolume.notNull())
+ {
+ return TRUE;
+ }
+
return FALSE;
}
@@ -3390,6 +3420,20 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
BOOL ret = FALSE;
LLVolume* volume = getVolume();
+
+ if (mDrawable->isState(LLDrawable::RIGGED))
+ {
+ if (LLFloater::isVisible(gFloaterTools) && getAvatar()->isSelf())
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
+ volume = mRiggedVolume;
+ }
+ else
+ { //cannot pick rigged attachments on other avatars or when not in build mode
+ return FALSE;
+ }
+ }
+
if (volume)
{
LLVector3 v_start, v_end, v_dir;
@@ -3484,6 +3528,170 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
return ret;
}
+void LLVOVolume::updateRiggedVolume()
+{
+ //Update mRiggedVolume to match current animation frame of avatar.
+ //Also update position/size in octree.
+
+ LLVolume* volume = getVolume();
+
+ const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID());
+
+ if (!skin)
+ {
+ mRiggedVolume = NULL;
+ return;
+ }
+
+ LLVOAvatar* avatar = getAvatar();
+
+ if (!avatar)
+ {
+ mRiggedVolume = NULL;
+ return;
+ }
+
+ if (!mRiggedVolume)
+ {
+ LLVolumeParams p;
+ mRiggedVolume = new LLRiggedVolume(p);
+ }
+
+ mRiggedVolume->update(skin, avatar, volume);
+
+}
+
+static LLFastTimer::DeclareTimer FTM_SKIN_RIGGED("Skin");
+static LLFastTimer::DeclareTimer FTM_RIGGED_OCTREE("Octree");
+
+void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume)
+{
+ bool copy = false;
+ if (volume->getNumVolumeFaces() != getNumVolumeFaces())
+ {
+ copy = true;
+ }
+
+ for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i)
+ {
+ const LLVolumeFace& src_face = volume->getVolumeFace(i);
+ const LLVolumeFace& dst_face = getVolumeFace(i);
+
+ if (src_face.mNumIndices != dst_face.mNumIndices ||
+ src_face.mNumVertices != dst_face.mNumVertices)
+ {
+ copy = true;
+ }
+ }
+
+ if (copy)
+ {
+ copyVolumeFaces(volume);
+ }
+
+ //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]);
+ if (joint)
+ {
+ mat[j] = skin->mInvBindMatrix[j];
+ mat[j] *= joint->getWorldMatrix();
+ }
+ }
+
+ for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
+ {
+ const LLVolumeFace& vol_face = volume->getVolumeFace(i);
+
+ LLVolumeFace& dst_face = mVolumeFaces[i];
+
+ LLVector4a* weight = vol_face.mWeights;
+
+ LLMatrix4a bind_shape_matrix;
+ bind_shape_matrix.loadu(skin->mBindShapeMatrix);
+
+ LLVector4a* pos = dst_face.mPositions;
+
+ {
+ LLFastTimer t(FTM_SKIN_RIGGED);
+
+ for (U32 j = 0; j < dst_face.mNumVertices; ++j)
+ {
+ LLMatrix4a final_mat;
+ final_mat.clear();
+
+ S32 idx[4];
+
+ LLVector4 wght;
+
+ F32 scale = 0.f;
+ for (U32 k = 0; k < 4; k++)
+ {
+ F32 w = weight[j][k];
+
+ idx[k] = (S32) floorf(w);
+ wght[k] = w - floorf(w);
+ scale += wght[k];
+ }
+
+ wght *= 1.f/scale;
+
+ for (U32 k = 0; k < 4; k++)
+ {
+ F32 w = wght[k];
+
+ LLMatrix4a src;
+ src.setMul(mp[idx[k]], w);
+
+ final_mat.add(src);
+ }
+
+
+ LLVector4a& v = vol_face.mPositions[j];
+ LLVector4a t;
+ LLVector4a dst;
+ bind_shape_matrix.affineTransform(v, t);
+ final_mat.affineTransform(t, dst);
+ dst.sub(origin);
+ pos[j] = dst;
+ }
+
+ //update bounding box
+ LLVector4a& min = dst_face.mExtents[0];
+ LLVector4a& max = dst_face.mExtents[1];
+
+ min = pos[0];
+ max = pos[1];
+
+ for (U32 j = 1; j < dst_face.mNumVertices; ++j)
+ {
+ min.setMin(min, pos[j]);
+ max.setMax(max, pos[j]);
+ }
+
+ dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]);
+ dst_face.mCenter->mul(0.5f);
+
+ }
+
+ {
+ LLFastTimer t(FTM_RIGGED_OCTREE);
+ delete dst_face.mOctree;
+ dst_face.mOctree = NULL;
+ dst_face.createOctree(2.f);
+ }
+ }
+}
+
U32 LLVOVolume::getPartitionType() const
{
if (isHUDAttachment())
@@ -3732,6 +3940,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic();
+ bool is_rigged = false;
+
//for each face
for (S32 i = 0; i < drawablep->getNumFaces(); i++)
{
@@ -3747,8 +3957,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
facep->mVertexBuffer = NULL;
facep->mLastVertexBuffer = NULL;
}
-
+
facep->setState(LLFace::RIGGED);
+ is_rigged = true;
//get drawpool of avatar with rigged face
LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);
@@ -3958,6 +4169,15 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
facep->mLastVertexBuffer = NULL;
}
}
+
+ if (is_rigged)
+ {
+ drawablep->setState(LLDrawable::RIGGED);
+ }
+ else
+ {
+ drawablep->clearState(LLDrawable::RIGGED);
+ }
}
group->mBufferUsage = useage;
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index eeb98726c9..d868099eeb 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -46,6 +46,8 @@ class LLDrawPool;
class LLSelectNode;
class LLObjectMediaDataClient;
class LLObjectMediaNavigateClient;
+class LLVOAvatar;
+class LLMeshSkinInfo;
typedef std::vector<viewer_media_t> media_list_t;
@@ -54,6 +56,18 @@ enum LLVolumeInterfaceType
INTERFACE_FLEXIBLE = 1,
};
+
+class LLRiggedVolume : public LLVolume
+{
+public:
+ LLRiggedVolume(const LLVolumeParams& params)
+ : LLVolume(params, 0.f)
+ {
+ }
+
+ void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume);
+};
+
// Base class for implementations of the volume - Primitive, Flexible Object, etc.
class LLVolumeInterface
{
@@ -289,6 +303,11 @@ public:
void removeMDCImpl() { --mMDCImplCount; }
S32 getMDCImplCount() { return mMDCImplCount; }
+
+ //rigged volume update (for raycasting)
+ void updateRiggedVolume();
+ LLRiggedVolume* getRiggedVolume() { return mRiggedVolume; }
+
protected:
S32 computeLODDetail(F32 distance, F32 radius);
BOOL calcLOD();
@@ -322,6 +341,9 @@ private:
S32 mLastFetchedMediaVersion; // as fetched from the server, starts as -1
S32 mIndexInTex;
S32 mMDCImplCount;
+
+ LLPointer<LLRiggedVolume> mRiggedVolume;
+
// statics
public:
static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop