summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2010-04-06 17:42:03 -0500
committerDave Parks <davep@lindenlab.com>2010-04-06 17:42:03 -0500
commit8a8269cca90df5bb7d53086ed7a3c14cb8cd941e (patch)
tree4dc827342d59773a4dcb808863ef71b96825aa71 /indra
parentecec1641ffe295c3bccbd0b4cb1bd2056b8a83e7 (diff)
parentde663d15df69aa6961f984f9f1c440f1fe2b3efb (diff)
merge
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llsdserialize.cpp139
-rw-r--r--indra/llcommon/llsdserialize.h4
-rw-r--r--indra/llmath/llvolume.cpp141
-rw-r--r--indra/llmath/llvolume.h6
-rw-r--r--indra/llrender/llglslshader.cpp14
-rw-r--r--indra/llrender/llglslshader.h3
-rw-r--r--indra/llrender/llshadermgr.cpp8
-rw-r--r--indra/llrender/llvertexbuffer.cpp14
-rw-r--r--indra/llrender/llvertexbuffer.h5
-rw-r--r--indra/newview/lldrawpoolavatar.cpp26
-rw-r--r--indra/newview/lldrawpoolavatar.h2
-rw-r--r--indra/newview/llface.cpp18
-rw-r--r--indra/newview/llface.h4
-rw-r--r--indra/newview/llspatialpartition.h7
-rw-r--r--indra/newview/llviewershadermgr.cpp25
-rw-r--r--indra/newview/llviewershadermgr.h3
-rw-r--r--indra/newview/llvoavatar.cpp109
-rw-r--r--indra/newview/llvoavatar.h1
-rw-r--r--indra/newview/llvovolume.cpp20
19 files changed, 452 insertions, 97 deletions
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index cf337be161..fdeb93e27f 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -39,6 +39,7 @@
#include <iostream>
#include "apr_base64.h"
+#include "zlib/zlib.h" // for davep's dirty little zip functions
#if !LL_WINDOWS
#include <netinet/in.h> // htonl & ntohl
@@ -1989,3 +1990,141 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
return s;
}
+
+//dirty little zippers -- yell at davep if these are horrid
+
+//return a string containing gzipped bytes of binary serialized LLSD
+// VERY inefficient -- creates several copies of LLSD block in memory
+std::string zip_llsd(LLSD& data)
+{
+ std::stringstream llsd_strm;
+
+ LLSDSerialize::serialize(data, llsd_strm, LLSDSerialize::LLSD_BINARY);
+
+ z_stream strm;
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
+ if (ret != Z_OK)
+ {
+ llwarns << "Failed to compress LLSD block." << llendl;
+ return std::string();
+ }
+
+ std::string source = llsd_strm.str();
+
+ strm.avail_in = source.size();
+ strm.next_in = (U8*) source.data();
+ U8* output = new U8[strm.avail_in];
+ strm.avail_out = strm.avail_in;
+ strm.next_out = output;
+ ret = deflate(&strm, Z_FINISH);
+ if (ret != Z_STREAM_END)
+ {
+ delete [] output;
+ llwarns << "Failed to compress LLSD block." << llendl;
+ return std::string();
+ }
+
+ std::string::size_type size = source.size()-strm.avail_out;
+
+ std::string result((char*) output, size);
+ deflateEnd(&strm);
+ delete [] output;
+
+ return result;
+}
+
+//decompress a block of LLSD from provided istream
+// not very efficient -- creats a copy of decompressed LLSD block in memory
+// and deserializes from that copy using LLSDSerialize
+bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
+{
+ U8* result = NULL;
+ U32 cur_size = 0;
+ z_stream strm;
+
+ const U32 CHUNK = 65536;
+
+ U8 *in = new U8[size];
+ is.read((char*) in, size);
+
+ U8 out[CHUNK];
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.avail_in = size;
+ strm.next_in = in;
+
+ S32 ret = inflateInit(&strm);
+
+ if (ret != Z_OK)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ do
+ {
+ strm.avail_out = CHUNK;
+ strm.next_out = out;
+ ret = inflate(&strm, Z_NO_FLUSH);
+ if (ret == Z_STREAM_ERROR)
+ {
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ return false;
+ }
+
+ switch (ret)
+ {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR;
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ inflateEnd(&strm);
+ free(result);
+ delete [] in;
+ return false;
+ break;
+ }
+
+ U32 have = CHUNK-strm.avail_out;
+
+ result = (U8*) realloc(result, cur_size + have);
+ memcpy(result+cur_size, out, have);
+ cur_size += have;
+
+ } while (strm.avail_out == 0);
+
+ inflateEnd(&strm);
+ delete [] in;
+
+ if (ret != Z_STREAM_END)
+ {
+ free(result);
+ return false;
+ }
+
+ //result now points to the decompressed LLSD block
+ {
+ std::string res_str((char*) result, cur_size);
+ std::istringstream istr(res_str);
+
+ if (!LLSDSerialize::deserialize(data, istr, cur_size))
+ {
+ llwarns << "Failed to unzip LLSD block" << llendl;
+ free(result);
+ return false;
+ }
+ }
+
+ free(result);
+ return true;
+}
+
+
+
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 2f2b292189..390eaca783 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -796,4 +796,8 @@ public:
}
};
+//dirty little zip functions -- yell at davep
+LL_COMMON_API std::string zip_llsd(LLSD& data);
+LL_COMMON_API bool unzip_llsd(LLSD& data, std::istream& is, S32 size);
+
#endif // LL_LLSDSERIALIZE_H
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 52a3fb2195..fdd48b9e9e 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -47,8 +47,6 @@
#include "llvolume.h"
#include "llstl.h"
#include "llsdserialize.h"
-#include "zlib/zlib.h"
-
#define DEBUG_SILHOUETTE_BINORMALS 0
#define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette
@@ -1964,97 +1962,15 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is)
bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
{
- U8* result = NULL;
- U32 cur_size = 0;
-
- {
- //input stream is now pointing at a zlib compressed block of LLSD
- //decompress block
- z_stream strm;
-
- const U32 CHUNK = 65536;
-
- U8 *in = new U8[size];
- is.read((char*) in, size);
-
- U8 out[CHUNK];
-
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.avail_in = size;
- strm.next_in = in;
-
- S32 ret = inflateInit(&strm);
-
- if (ret != Z_OK)
- {
- llerrs << "WTF?" << llendl;
- }
-
- do
- {
- strm.avail_out = CHUNK;
- strm.next_out = out;
- ret = inflate(&strm, Z_NO_FLUSH);
- if (ret == Z_STREAM_ERROR)
- {
- inflateEnd(&strm);
- free(result);
- delete [] in;
- return false;
- }
-
- switch (ret)
- {
- case Z_NEED_DICT:
- ret = Z_DATA_ERROR;
- case Z_DATA_ERROR:
- case Z_MEM_ERROR:
- inflateEnd(&strm);
- free(result);
- delete [] in;
- return false;
- break;
- }
-
- U32 have = CHUNK-strm.avail_out;
-
- result = (U8*) realloc(result, cur_size + have);
- memcpy(result+cur_size, out, have);
- cur_size += have;
-
- } while (strm.avail_out == 0);
-
- inflateEnd(&strm);
- delete [] in;
-
- if (ret != Z_STREAM_END)
- {
- free(result);
- return false;
- }
- }
-
- //result now points to the decompressed LLSD block
-
+ //input stream is now pointing at a zlib compressed block of LLSD
+ //decompress block
LLSD mdl;
-
+ if (!unzip_llsd(mdl, is, size))
{
- std::string res_str((char*) result, cur_size);
- std::istringstream istr(res_str);
-
- if (!LLSDSerialize::deserialize(mdl, istr, cur_size))
- {
- llwarns << "not a valid mesh asset!" << llendl;
- return false;
- }
+ llwarns << "not a valid mesh asset!" << llendl;
+ return false;
}
-
-
- free(result);
-
-
+
{
U32 face_count = mdl.size();
@@ -2094,11 +2010,56 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
U32 num_verts = pos.size()/(3*2);
face.mVertices.resize(num_verts);
+ if (mdl[i].has("Weights"))
+ {
+ face.mWeights.resize(num_verts);
+
+ LLSD::Binary weights = mdl[i]["Weights"];
+
+ U32 idx = 0;
+
+ U32 cur_vertex = 0;
+ while (idx < weights.size() && cur_vertex < num_verts)
+ {
+ const U8 END_INFLUENCES = 0xFF;
+ U8 joint = weights[idx++];
+
+ U32 cur_influence = 0;
+ while (joint != END_INFLUENCES)
+ {
+ U16 influence = weights[idx++];
+ influence = influence << 8;
+ influence |= weights[idx++];
+
+ F32 w = llmin((F32) influence / 65535.f, 0.99999f);
+ face.mWeights[cur_vertex].mV[cur_influence++] = (F32) joint + w;
+
+ if (cur_influence >= 4)
+ {
+ joint = END_INFLUENCES;
+ }
+ else
+ {
+ joint = weights[idx++];
+ }
+ }
+
+ cur_vertex++;
+ }
+
+ if (cur_vertex != num_verts || idx != weights.size())
+ {
+ llwarns << "Vertex weight count does not match vertex count!" << llendl;
+ }
+
+ }
+
LLVector3 min_pos;
LLVector3 max_pos;
LLVector2 min_tc;
LLVector2 max_tc;
+
min_pos.setValue(mdl[i]["PositionDomain"]["Min"]);
max_pos.setValue(mdl[i]["PositionDomain"]["Max"]);
min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]);
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 60c1569e55..c6a156ae37 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -49,6 +49,7 @@ class LLVolume;
//#include "vmath.h"
#include "v2math.h"
#include "v3math.h"
+#include "v4math.h"
#include "llquaternion.h"
#include "llstrider.h"
#include "v4coloru.h"
@@ -887,6 +888,11 @@ public:
std::vector<U16> mTriStrip;
std::vector<S32> mEdge;
+ //list of skin weights for rigged volumes
+ // format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight>
+ // mWeights.size() should be empty or match mVertices.size()
+ std::vector<LLVector4> mWeights;
+
private:
BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index ca92cb6580..949057df04 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -61,7 +61,7 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
LLShaderFeatures::LLShaderFeatures()
: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
-hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false),
+hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false),
hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
{
}
@@ -717,6 +717,18 @@ GLint LLGLSLShader::getUniformLocation(const string& uniform)
return -1;
}
+GLint LLGLSLShader::getAttribLocation(U32 attrib)
+{
+ if (attrib < mAttribute.size())
+ {
+ return mAttribute[attrib];
+ }
+ else
+ {
+ return -1;
+ }
+}
+
void LLGLSLShader::uniform1i(const string& uniform, GLint v)
{
GLint location = getUniformLocation(uniform);
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 166d4af04c..dc493ba162 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -48,6 +48,7 @@ public:
bool hasWaterFog; // implies no gamma
bool hasTransport; // implies no lighting (it's possible to have neither though)
bool hasSkinning;
+ bool hasObjectSkinning;
bool hasAtmospherics;
bool hasGamma;
@@ -109,7 +110,7 @@ public:
void vertexAttrib4fv(U32 index, GLfloat* v);
GLint getUniformLocation(const std::string& uniform);
-
+ GLint getAttribLocation(U32 attrib);
GLint mapUniformTextureChannel(GLint location, GLenum type);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 1286e91e49..23b76351eb 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -152,6 +152,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
}
+
+ if (features->hasObjectSkinning)
+ {
+ if (!shader->attachObject("avatar/objectSkinV.glsl"))
+ {
+ return FALSE;
+ }
+ }
///////////////////////////////////////
// Attach Fragment Shader Features Next
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 4064e688e8..d5b00f27a7 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -62,6 +62,7 @@ BOOL LLVertexBuffer::sIBOActive = FALSE;
U32 LLVertexBuffer::sAllocatedBytes = 0;
BOOL LLVertexBuffer::sMapped = FALSE;
BOOL LLVertexBuffer::sUseStreamDraw = TRUE;
+S32 LLVertexBuffer::sWeight4Loc = -1;
std::vector<U32> LLVertexBuffer::sDeleteList;
@@ -76,6 +77,7 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
sizeof(LLColor4U), // TYPE_COLOR,
sizeof(LLVector3), // TYPE_BINORMAL,
sizeof(F32), // TYPE_WEIGHT,
+ sizeof(LLVector4), // TYPE_WEIGHT4,
sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
};
@@ -1015,6 +1017,12 @@ bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index)
{
return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index);
}
+
+bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index)
+{
+ return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index);
+}
+
bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index)
{
return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index);
@@ -1284,6 +1292,12 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const
{
glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT]));
}
+
+ if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1)
+ {
+ glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, stride, (void*)(base+mOffsets[TYPE_WEIGHT4]));
+ }
+
if (data_mask & MAP_CLOTHWEIGHT)
{
glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index e2fecdffef..225237215c 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -84,6 +84,8 @@ public:
static LLVBOPool sStreamIBOPool;
static LLVBOPool sDynamicIBOPool;
+ static S32 sWeight4Loc;
+
static BOOL sUseStreamDraw;
static void initClass(bool use_vbo);
@@ -109,6 +111,7 @@ public:
// These use VertexAttribPointer and should possibly be made generic
TYPE_BINORMAL,
TYPE_WEIGHT,
+ TYPE_WEIGHT4,
TYPE_CLOTHWEIGHT,
TYPE_MAX,
TYPE_INDEX,
@@ -124,6 +127,7 @@ public:
// These use VertexAttribPointer and should possibly be made generic
MAP_BINORMAL = (1<<TYPE_BINORMAL),
MAP_WEIGHT = (1<<TYPE_WEIGHT),
+ MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
};
@@ -173,6 +177,7 @@ public:
bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0);
bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0);
bool getWeightStrider(LLStrider<F32>& strider, S32 index=0);
+ bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0);
bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0);
BOOL isEmpty() const { return mEmpty; }
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 012e41383f..9311a5f60e 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -320,7 +320,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
S32 LLDrawPoolAvatar::getNumPasses()
{
- return LLPipeline::sImpostorRender ? 1 : 3;
+ return LLPipeline::sImpostorRender ? 1 : 4;
}
void LLDrawPoolAvatar::render(S32 pass)
@@ -357,6 +357,8 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)
break;
case 2:
beginSkinned();
+ case 3:
+ beginRigged();
break;
}
}
@@ -381,6 +383,10 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass)
break;
case 2:
endSkinned();
+ break;
+ case 3:
+ endRigged();
+ break;
}
}
@@ -566,6 +572,18 @@ void LLDrawPoolAvatar::endSkinned()
gGL.getTexUnit(0)->activate();
}
+void LLDrawPoolAvatar::beginRigged()
+{
+ gSkinnedObjectSimpleProgram.bind();
+ LLVertexBuffer::sWeight4Loc = gSkinnedObjectSimpleProgram.getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+}
+
+void LLDrawPoolAvatar::endRigged()
+{
+ gSkinnedObjectSimpleProgram.unbind();
+ LLVertexBuffer::sWeight4Loc = -1;
+}
+
void LLDrawPoolAvatar::beginDeferredSkinned()
{
sShaderLevel = mVertexShaderLevel;
@@ -711,6 +729,12 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
avatarp->renderRigid();
return;
}
+
+ if (pass == 3)
+ {
+ avatarp->renderSkinnedAttachments();
+ return;
+ }
if (sShaderLevel > 0)
{
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index b947943619..c43aa9b1e3 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -90,10 +90,12 @@ public:
void beginRigid();
void beginFootShadow();
void beginSkinned();
+ void beginRigged();
void endRigid();
void endFootShadow();
void endSkinned();
+ void endRigged();
void beginDeferredImpostor();
void beginDeferredRigid();
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 53330e4d98..bc3e04db18 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -888,7 +888,8 @@ static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom");
BOOL LLFace::getGeometryVolume(const LLVolume& volume,
const S32 &f,
const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
- const U16 &index_offset)
+ const U16 &index_offset,
+ bool force_rebuild)
{
LLFastTimer t(FTM_FACE_GET_GEOM);
const LLVolumeFace &vf = volume.getVolumeFace(f);
@@ -925,8 +926,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLStrider<LLColor4U> colors;
LLStrider<LLVector3> binormals;
LLStrider<U16> indicesp;
+ LLStrider<LLVector4> weights;
- BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
+ BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal();
LLVector3 scale;
@@ -944,6 +946,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
BOOL rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD);
BOOL rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL);
BOOL rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL);
+ bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4);
const LLTextureEntry *tep = mVObjp->getTE(f);
U8 bump_code = tep ? tep->getBumpmap() : 0;
@@ -960,7 +963,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
mVertexBuffer->getBinormalStrider(binormals, mGeomIndex);
}
-
+ if (rebuild_weights)
+ {
+ mVertexBuffer->getWeight4Strider(weights, mGeomIndex);
+ }
+
F32 tcoord_xoffset = 0.f ;
F32 tcoord_yoffset = 0.f ;
F32 tcoord_xscale = 1.f ;
@@ -1338,6 +1345,11 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
*binormals++ = binormal;
}
+ if (rebuild_weights)
+ {
+ *weights++ = vf.mWeights[i];
+ }
+
if (rebuild_color)
{
*colors++ = color;
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 67dd97e6f7..06ec043c76 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -73,6 +73,7 @@ public:
HUD_RENDER = 0x0008,
USE_FACE_COLOR = 0x0010,
TEXTURE_ANIM = 0x0020,
+ RIGGED = 0x0040,
};
static void initClass();
@@ -145,7 +146,8 @@ public:
BOOL getGeometryVolume(const LLVolume& volume,
const S32 &f,
const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
- const U16 &index_offset);
+ const U16 &index_offset,
+ bool force_rebuild = false);
// For avatar
U16 getGeometryAvatar(
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index d74216de2d..b5e5967374 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -615,6 +615,13 @@ public:
class LLVolumeGeometryManager: public LLGeometryManager
{
public:
+ typedef enum
+ {
+ NONE = 0,
+ BATCH_SORT,
+ DISTANCE_SORT
+ } eSortType;
+
virtual ~LLVolumeGeometryManager() { }
virtual void rebuildGeom(LLSpatialGroup* group);
virtual void rebuildMesh(LLSpatialGroup* group);
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index a0d0b9d490..8a68dd6ea7 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -77,6 +77,9 @@ LLGLSLShader gObjectFullbrightShinyProgram;
LLGLSLShader gObjectShinyProgram;
LLGLSLShader gObjectShinyWaterProgram;
+//object hardware skinning shaders
+LLGLSLShader gSkinnedObjectSimpleProgram;
+
//environment shaders
LLGLSLShader gTerrainProgram;
LLGLSLShader gTerrainWaterProgram;
@@ -148,6 +151,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gObjectSimpleProgram);
mShaderList.push_back(&gObjectFullbrightProgram);
mShaderList.push_back(&gObjectFullbrightShinyProgram);
+ mShaderList.push_back(&gSkinnedObjectSimpleProgram);
mShaderList.push_back(&gTerrainProgram);
mShaderList.push_back(&gTerrainWaterProgram);
mShaderList.push_back(&gObjectSimpleWaterProgram);
@@ -195,6 +199,7 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void)
mReservedAttribs.push_back("materialColor");
mReservedAttribs.push_back("specularColor");
mReservedAttribs.push_back("binormal");
+ mReservedAttribs.push_back("object_weight");
mAvatarAttribs.reserve(5);
mAvatarAttribs.push_back("weight");
@@ -548,6 +553,9 @@ void LLViewerShaderMgr::unloadShaders()
gObjectShinyProgram.unload();
gObjectFullbrightShinyProgram.unload();
gObjectShinyWaterProgram.unload();
+
+ gSkinnedObjectSimpleProgram.unload();
+
gWaterProgram.unload();
gUnderWaterProgram.unload();
gTerrainProgram.unload();
@@ -625,6 +633,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) );
+ shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) );
// We no longer have to bind the shaders to global glhandles, they are automatically added to a map now.
for (U32 i = 0; i < shaders.size(); i++)
@@ -1214,6 +1223,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleWaterProgram.unload();
gObjectFullbrightProgram.unload();
gObjectFullbrightWaterProgram.unload();
+ gSkinnedObjectSimpleProgram.unload();
return FALSE;
}
@@ -1323,6 +1333,21 @@ BOOL LLViewerShaderMgr::loadShadersObject()
success = gObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms);
}
+ if (success)
+ {
+ gSkinnedObjectSimpleProgram.mName = "Skinned Simple Shader";
+ gSkinnedObjectSimpleProgram.mFeatures.calculatesLighting = true;
+ gSkinnedObjectSimpleProgram.mFeatures.calculatesAtmospherics = true;
+ gSkinnedObjectSimpleProgram.mFeatures.hasGamma = true;
+ gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true;
+ gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true;
+ gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true;
+ gSkinnedObjectSimpleProgram.mShaderFiles.clear();
+ gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+ gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gSkinnedObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL);
+ }
if( !success )
{
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index ac2b4624e0..83a650cdbc 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -82,6 +82,7 @@ public:
MATERIAL_COLOR = 0,
SPECULAR_COLOR,
BINORMAL,
+ OBJECT_WEIGHT,
END_RESERVED_ATTRIBS
} eGLSLReservedAttribs;
@@ -313,6 +314,8 @@ extern LLGLSLShader gObjectFullbrightShinyProgram;
extern LLGLSLShader gObjectShinyProgram;
extern LLGLSLShader gObjectShinyWaterProgram;
+extern LLGLSLShader gSkinnedObjectSimpleProgram;
+
//environment shaders
extern LLGLSLShader gTerrainProgram;
extern LLGLSLShader gTerrainWaterProgram;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 540cb47710..0e75da4677 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -64,6 +64,7 @@
#include "llkeyframefallmotion.h"
#include "llkeyframestandmotion.h"
#include "llkeyframewalkmotion.h"
+#include "llmeshrepository.h"
#include "llmutelist.h"
#include "llmoveview.h"
#include "llquantize.h"
@@ -79,6 +80,7 @@
#include "llviewermenu.h"
#include "llviewerobjectlist.h"
#include "llviewerparcelmgr.h"
+#include "llviewershadermgr.h"
#include "llviewerstats.h"
#include "llvoavatarself.h"
#include "llvovolume.h"
@@ -3637,6 +3639,113 @@ bool LLVOAvatar::shouldAlphaMask()
}
+U32 LLVOAvatar::renderSkinnedAttachments()
+{
+ U32 num_indices = 0;
+
+ const U32 data_mask = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_NORMAL |
+ LLVertexBuffer::MAP_TEXCOORD0 |
+ LLVertexBuffer::MAP_WEIGHT4;
+
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ LLViewerJointAttachment* attachment = iter->second;
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
+ {
+ const LLViewerObject* attached_object = (*attachment_iter);
+ if (attached_object && !attached_object->isHUDAttachment())
+ {
+ const LLDrawable* drawable = attached_object->mDrawable;
+ if (drawable)
+ {
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ LLFace* face = drawable->getFace(i);
+ if (face->isState(LLFace::RIGGED))
+ {
+ LLVolume* volume = attached_object->getVolume();
+ const LLVolumeFace& vol_face = volume->getVolumeFace(i);
+
+ const LLMeshSkinInfo* skin = NULL;
+ LLVertexBuffer* buff = face->mVertexBuffer;
+
+ if (!buff ||
+ !buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) ||
+ buff->getRequestedVerts() != vol_face.mVertices.size())
+ {
+ face->mVertexBuffer = NULL;
+ face->mLastVertexBuffer = NULL;
+ buff = NULL;
+
+ LLUUID mesh_id = volume->getParams().getSculptID();
+ if (mesh_id.notNull())
+ {
+ skin = gMeshRepo.getSkinInfo(mesh_id);
+ if (skin)
+ {
+ face->mVertexBuffer = new LLVertexBuffer(data_mask, 0);
+ face->mVertexBuffer->allocateBuffer(vol_face.mVertices.size(), vol_face.mIndices.size(), true);
+
+ face->setGeomIndex(0);
+ face->setIndicesIndex(0);
+
+ U16 offset = 0;
+
+ LLMatrix4 mat_vert = skin->mBindShapeMatrix;
+ LLMatrix3 mat_normal;
+
+ face->getGeometryVolume(*volume, i, mat_vert, mat_normal, offset, true);
+ buff = face->mVertexBuffer;
+ }
+ }
+ }
+
+ if (buff)
+ {
+ if (skin)
+ {
+ LLMatrix4 mat[64];
+
+ for (U32 i = 0; i < skin->mJointNames.size(); ++i)
+ {
+ LLJoint* joint = getJoint(skin->mJointNames[i]);
+ if (joint)
+ {
+ mat[i] = skin->mInvBindMatrix[i];
+ mat[i] *= joint->getWorldMatrix();
+ }
+ }
+
+ gSkinnedObjectSimpleProgram.uniformMatrix4fv("matrixPalette",
+ skin->mJointNames.size(),
+ FALSE,
+ (GLfloat*) mat[0].mMatrix);
+
+ buff->setBuffer(data_mask);
+
+ U16 start = face->getGeomStart();
+ U16 end = start + face->getGeomCount();
+ S32 offset = face->getIndicesStart();
+ U32 count = face->getIndicesCount();
+
+ buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return num_indices;
+}
+
//-----------------------------------------------------------------------------
// renderSkinned()
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index d5485413f4..b0535a4a26 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -339,6 +339,7 @@ public:
U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
U32 renderRigid();
U32 renderSkinned(EAvatarRenderPass pass);
+ U32 renderSkinnedAttachments();
U32 renderTransparent(BOOL first_pass);
void renderCollisionVolumes();
static void deleteCachedImages(bool clearAll=true);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index bc83e11fd2..56fb42bb89 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3496,6 +3496,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
drawablep->clearState(LLDrawable::HAS_ALPHA);
+ bool rigged = vobj->isAttachment() &&
+ vobj->isMesh() &&
+ gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID());
+
//for each face
for (S32 i = 0; i < drawablep->getNumFaces(); i++)
{
@@ -3503,6 +3507,22 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
drawablep->updateFaceSize(i);
LLFace* facep = drawablep->getFace(i);
+ if (rigged)
+ {
+ if (!facep->isState(LLFace::RIGGED))
+ {
+ facep->mVertexBuffer = NULL;
+ facep->mLastVertexBuffer = NULL;
+ facep->setState(LLFace::RIGGED);
+ }
+
+ continue;
+ }
+ else
+ {
+ facep->clearState(LLFace::RIGGED);
+ }
+
if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0)
{
facep->mVertexBuffer = NULL;