summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2010-04-02 14:43:05 -0500
committerDave Parks <davep@lindenlab.com>2010-04-02 14:43:05 -0500
commit807d835c2bfc5d794a74f9690d1fafbe55ff88cc (patch)
tree08887317bbddf493dc4142505abfd1c727a67578
parent532e63e91fb40b5d4c4b0eb2f855cce442b8539d (diff)
First draft of skin weights in .mesh asset
-rw-r--r--indra/llcommon/llsdserialize.cpp137
-rw-r--r--indra/llcommon/llsdserialize.h4
-rw-r--r--indra/llmath/llvolume.cpp135
-rw-r--r--indra/llmath/llvolume.h6
4 files changed, 192 insertions, 90 deletions
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index cf337be161..c341b15539 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,139 @@ 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;
+ }
+
+ 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;
+ 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..c563af592f 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,50 @@ 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"];
+
+ LLSD::Binary::iterator iter = weights.begin();
+
+ U32 cur_vertex = 0;
+ while (iter != weights.end())
+ {
+ const S32 END_INFLUENCES = 0xFF;
+ U8 joint = *(iter++);
+
+ U32 cur_influence = 0;
+ while (joint != END_INFLUENCES)
+ {
+ U16 influence = *(iter++);
+ influence = influence << 8;
+ influence |= *(iter++);
+
+ 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 = *(iter++);
+ }
+ }
+
+ cur_vertex++;
+ iter++;
+ }
+ }
+
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);