From 3e80fa3dbc943de9b784fedc202ba38cf238f46d Mon Sep 17 00:00:00 2001 From: David Parks Date: Mon, 2 Nov 2009 19:55:37 +0000 Subject: Sync up with render-pipeline-7 ignore-dead-branch --- indra/llmath/llvolume.cpp | 350 ++++++++++++++++++++++++++++++++++++++++++- indra/llmath/llvolume.h | 22 ++- indra/llmath/llvolumemgr.cpp | 2 +- indra/llmath/m4math.cpp | 11 ++ indra/llmath/m4math.h | 1 + indra/llmath/v2math.cpp | 15 ++ indra/llmath/v2math.h | 3 + 7 files changed, 392 insertions(+), 12 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index b8ef92f9a9..afa82ed399 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -46,6 +46,9 @@ #include "lldarray.h" #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 @@ -1688,7 +1691,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; generate(); - if (mParams.getSculptID().isNull()) + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { createVolumeFaces(); } @@ -1839,6 +1842,295 @@ BOOL LLVolume::generate() return FALSE; } +bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const +{ + const U8* l = (const U8*) this; + const U8* r = (const U8*) &rhs; + + for (U32 i = 0; i < sizeof(VertexData); ++i) + { + if (l[i] != r[i]) + { + return r[i] < l[i]; + } + } + + return false; +} + +bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const +{ + const U8* l = (const U8*) this; + const U8* r = (const U8*) &rhs; + + for (U32 i = 0; i < sizeof(VertexData); ++i) + { + if (l[i] != r[i]) + { + return false; + } + } + + return true; +} + + +BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name) +{ + std::ifstream is; + + is.open(file_name.c_str(), std::ifstream::in | std::ifstream::binary); + + BOOL success = createVolumeFacesFromStream(is); + + is.close(); + + return success; +} + +BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) +{ + mSculptLevel = -1; // default is an error occured + + LLSD header; + { + if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024)) + { + llwarns << "not a valid mesh asset!" << llendl; + return FALSE; + } + } + + std::string nm[] = + { + "impostor", + "low_lod", + "medium_lod", + "high_lod" + }; + + S32 lod = llclamp((S32) mDetail, 0, 3); + + while (lod < 4 && header[nm[lod]]["offset"].asInteger() == -1) + { + ++lod; + } + + if (lod >= 4) + { + llwarns << "Couldn't load model for given lod" << llendl; + return FALSE; + } + + is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); + + + 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; + + S32 size = header[nm[lod]]["size"].asInteger(); + 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 + + LLSD mdl; + + { + 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; + } + } + + + free(result); + + + { + U32 face_count = mdl.size(); + + mVolumeFaces.resize(face_count); + + for (U32 i = 0; i < face_count; ++i) + { + LLSD::Binary pos = mdl[i]["Position"]; + LLSD::Binary norm = mdl[i]["Normal"]; + LLSD::Binary tc = mdl[i]["TexCoord0"]; + LLSD::Binary idx = mdl[i]["TriangleList"]; + + LLVolumeFace& face = mVolumeFaces[i]; + + face.mHasBinormals = FALSE; + + //copy out indices + face.mIndices.resize(idx.size()/2); + if (idx.empty()) + { //why is there an empty index list? + continue; + } + + U16* indices = (U16*) &(idx[0]); + for (U32 j = 0; j < idx.size()/2; ++j) + { + face.mIndices[j] = indices[j]; + } + + //copy out vertices + U32 num_verts = pos.size()/(3*2); + face.mVertices.resize(num_verts); + + 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"]); + max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); + + F32 scale = llclamp((F32) mdl[i]["Scale"].asReal(), 1.f, 10.f); + + LLVector3 pos_range = max_pos - min_pos; + LLVector2 tc_range = max_tc - min_tc; + + LLVector3& min = face.mExtents[0]; + LLVector3& max = face.mExtents[1]; + + min = max = LLVector3(0,0,0); + + for (U32 j = 0; j < num_verts; ++j) + { + U16* v = (U16*) &(pos[j*3*2]); + + face.mVertices[j].mPosition.setVec( + (F32) v[0] / 65535.f * pos_range.mV[0] + min_pos.mV[0], + (F32) v[1] / 65535.f * pos_range.mV[1] + min_pos.mV[1], + (F32) v[2] / 65535.f * pos_range.mV[2] + min_pos.mV[2]); + + face.mVertices[j].mPosition *= scale; + + if (j == 0) + { + min = max = face.mVertices[j].mPosition; + } + else + { + update_min_max(min,max,face.mVertices[j].mPosition); + } + + U16* n = (U16*) &(norm[j*3*2]); + + face.mVertices[j].mNormal.setVec( + (F32) n[0] / 65535.f * 2.f - 1.f, + (F32) n[1] / 65535.f * 2.f - 1.f, + (F32) n[2] / 65535.f * 2.f - 1.f); + + U16* t = (U16*) &(tc[j*2*2]); + + face.mVertices[j].mTexCoord.setVec( + (F32) t[0] / 65535.f * tc_range.mV[0] + min_tc.mV[0], + (F32) t[1] / 65535.f * tc_range.mV[1] + min_tc.mV[1]); + } + + } + } + + mSculptLevel = 0; // success! + return TRUE; +} + +void LLVolume::copyVolumeFaces(LLVolume* volume) +{ + mVolumeFaces = volume->mVolumeFaces; + mSculptLevel = 0; +} + +S32 const LL_SCULPT_MESH_MAX_FACES = 8; + +S32 LLVolume::getNumFaces() const +{ + U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK); + + if (sculpt_type == LL_SCULPT_TYPE_MESH) + { + return LL_SCULPT_MESH_MAX_FACES; + } + + return (S32)mProfilep->mFaces.size(); +} + void LLVolume::createVolumeFaces() { @@ -1864,6 +2156,11 @@ void LLVolume::createVolumeFaces() LLProfile::Face& face = mProfilep->mFaces[i]; vf.mBeginS = face.mIndex; vf.mNumS = face.mCount; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } + vf.mBeginT = 0; vf.mNumT= getPath().mPath.size(); vf.mID = i; @@ -1907,6 +2204,10 @@ void LLVolume::createVolumeFaces() if (face.mFlat && vf.mNumS > 2) { //flat inner faces have to copy vert normals vf.mNumS = vf.mNumS*2; + if (vf.mNumS < 0) + { + llerrs << "Volume face corruption detected." << llendl; + } } } else @@ -2309,7 +2610,6 @@ bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const return mSculptID < params.mSculptID; } - return mSculptType < params.mSculptType; @@ -3379,22 +3679,29 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, S32 face_mask) { LLMemType m1(LLMemType::MTYPE_VOLUME); - + vertices.clear(); normals.clear(); segments.clear(); + if (mParams.getSculptType() == LL_SCULPT_TYPE_MESH) + { + return; + } + S32 cur_index = 0; //for each face for (face_list_t::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); ++iter) { - const LLVolumeFace& face = *iter; + LLVolumeFace& face = *iter; - if (!(face_mask & (0x1 << cur_index++))) + if (!(face_mask & (0x1 << cur_index++)) || + face.mIndices.empty() || face.mEdge.empty()) { continue; } + if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { } @@ -3594,6 +3901,8 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, F32 closest_t = 2.f; // must be larger than 1 + end_face = llmin(end_face, getNumVolumeFaces()-1); + for (S32 i = start_face; i <= end_face; i++) { const LLVolumeFace &face = getVolumeFace((U32)i); @@ -4103,11 +4412,28 @@ BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const return TRUE; } +LLSD LLVolumeParams::sculptAsLLSD() const +{ + LLSD sd = LLSD(); + sd["id"] = getSculptID(); + sd["type"] = getSculptType(); + + return sd; +} + +bool LLVolumeParams::sculptFromLLSD(LLSD& sd) +{ + setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); + return true; +} + LLSD LLVolumeParams::asLLSD() const { LLSD sd = LLSD(); sd["path"] = mPathParams; sd["profile"] = mProfileParams; + sd["sculpt"] = sculptAsLLSD(); + return sd; } @@ -4115,6 +4441,8 @@ bool LLVolumeParams::fromLLSD(LLSD& sd) { mPathParams.fromLLSD(sd["path"]); mProfileParams.fromLLSD(sd["profile"]); + sculptFromLLSD(sd["sculpt"]); + return true; } @@ -4157,6 +4485,12 @@ const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity // for collison purposes BOOL LLVolumeParams::isConvex() const { + if (!getSculptID().isNull()) + { + // can't determine, be safe and say no: + return FALSE; + } + F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); F32 hollow = mProfileParams.getHollow(); @@ -5011,7 +5345,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) if (!partial_build) { mIndices.resize(num_indices); - mEdge.resize(num_indices); + + if (volume->getParams().getSculptType() != LL_SCULPT_TYPE_MESH) + { + mEdge.resize(num_indices); + } } else { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 871b334452..9f595ccbc4 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -186,6 +186,9 @@ const U8 LL_SCULPT_TYPE_CYLINDER = 4; const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER; +// need to change this (these) names +const U8 LL_SCULPT_TYPE_MESH = 5; + const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; @@ -575,6 +578,9 @@ public: BOOL importLegacyStream(std::istream& input_stream); BOOL exportLegacyStream(std::ostream& output_stream) const; + LLSD sculptAsLLSD() const; + bool sculptFromLLSD(LLSD& sd); + LLSD asLLSD() const; operator LLSD() const { return asLLSD(); } bool fromLLSD(LLSD& sd); @@ -634,7 +640,6 @@ public: const F32& getSkew() const { return mPathParams.getSkew(); } const LLUUID& getSculptID() const { return mSculptID; } const U8& getSculptType() const { return mSculptType; } - BOOL isConvex() const; // 'begin' and 'end' should be in range [0, 1] (they will be clamped) @@ -798,7 +803,7 @@ public: BOOL create(LLVolume* volume, BOOL partial_build = FALSE); void createBinormals(); - + class VertexData { public: @@ -806,6 +811,9 @@ public: LLVector3 mNormal; LLVector3 mBinormal; LLVector2 mTexCoord; + + bool operator<(const VertexData& rhs) const; + bool operator==(const VertexData& rhs) const; }; enum @@ -851,8 +859,7 @@ class LLVolume : public LLRefCount { friend class LLVolumeLODGroup; -private: - LLVolume(const LLVolume&); // Don't implement +protected: ~LLVolume(); // use unref public: @@ -874,7 +881,7 @@ public: U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); } U8 getPathType() const { return mParams.getPathParams().getCurveType(); } - S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); } + S32 getNumFaces() const; S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } F32 getDetail() const { return mDetail; } const LLVolumeParams& getParams() const { return mParams; } @@ -946,6 +953,8 @@ 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); + private: void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); F32 sculptGetSurfaceArea(); @@ -956,6 +965,9 @@ private: protected: BOOL generate(); void createVolumeFaces(); +public: + virtual BOOL createVolumeFacesFromFile(const std::string& file_name); + virtual BOOL createVolumeFacesFromStream(std::istream& is); protected: BOOL mUnique; diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 53641fceab..61c5a0adc9 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -320,7 +320,7 @@ BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) { llassert_always(mLODRefs[i] > 0); mLODRefs[i]--; -#if 1 // SJB: Possible opt: keep other lods around +#if 0 // SJB: Possible opt: keep other lods around if (!mLODRefs[i]) { mVolumeLODs[i] = NULL; diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index d8e7b4aaf9..7c7f60154d 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -428,6 +428,17 @@ const LLMatrix4& LLMatrix4::initRotTrans(const LLQuaternion &q, const LLVector return (*this); } +const LLMatrix4& LLMatrix4::initScale(const LLVector3 &scale) +{ + setIdentity(); + + mMatrix[VX][VX] = scale.mV[VX]; + mMatrix[VY][VY] = scale.mV[VY]; + mMatrix[VZ][VZ] = scale.mV[VZ]; + + return (*this); +} + const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos) { F32 sx, sy, sz; diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index e74b7afe9b..de981b7646 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -159,6 +159,7 @@ public: 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 + const LLMatrix4& initScale(const LLVector3 &scale); // Set all const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos); diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 555e1f92bb..220336e0c2 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -115,3 +115,18 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u) a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u ); } + +LLSD LLVector2::getValue() const +{ + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + return ret; +} + +void LLVector2::setValue(LLSD& sd) +{ + mV[0] = (F32) sd[0].asReal(); + mV[1] = (F32) sd[1].asReal(); +} + diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index 9fef8851cc..f9f1c024f2 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -66,6 +66,9 @@ class LLVector2 void set(const LLVector2 &vec); // Sets LLVector2 to vec void set(const F32 *vec); // Sets LLVector2 to vec + LLSD getValue() const; + void setValue(LLSD& sd); + void setVec(F32 x, F32 y); // deprecated void setVec(const LLVector2 &vec); // deprecated void setVec(const F32 *vec); // deprecated -- cgit v1.3 From 88292104d9a2332e6169f2add8f0b590bb22dbff Mon Sep 17 00:00:00 2001 From: David Parks Date: Wed, 4 Nov 2009 14:19:05 +0000 Subject: Fix for crash when loading some meshes. Added button to auto-fill LODs. --- indra/llmath/llvolume.cpp | 4 +++- indra/newview/pipeline.cpp | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index afa82ed399..ddd1b4b3db 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1690,9 +1690,11 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; - generate(); + mLODScaleBias.setVec(1,1,1); + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { + generate(); createVolumeFaces(); } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7cf5cf75ad..4fc94c08bc 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8988,6 +8988,7 @@ void LLPipeline::LLMeshThread::run() { LLVolumeParams volume_params; volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + volume_params.setSculptID(mMeshID, LL_SCULPT_TYPE_MESH); mVolume = new LLVolume(volume_params, mDetail); mVolume->createVolumeFacesFromStream(buffer_stream); } -- cgit v1.3 From 10069e0e13e3214ba9320fdce915440b2e12f938 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 5 Nov 2009 19:58:10 -0600 Subject: Fix for prims all being 0 lod. Fix for dangling prim references. --- indra/llmath/llvolume.cpp | 3 ++- indra/llprimitive/llprimitive.cpp | 8 +++++++- indra/newview/llvovolume.cpp | 2 +- indra/newview/pipeline.cpp | 2 ++ 4 files changed, 12 insertions(+), 3 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index ddd1b4b3db..33a8d33ce1 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1692,9 +1692,10 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mLODScaleBias.setVec(1,1,1); + generate(); + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { - generate(); createVolumeFaces(); } } diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 52265e7ad5..340f60ed1a 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -744,7 +744,10 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai return TRUE; } -#if 0 +#if 0 + // #if 0'd out by davep + // this is a lot of cruft to set texture entry values that just stay the same for LOD switch + // or immediately get overridden by an object update message, also crashes occasionally U32 old_face_mask = mVolumep->mFaceMask; S32 face_bit = 0; @@ -943,6 +946,9 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai } } #else + // build the new object + sVolumeManager->unrefVolume(mVolumep); + mVolumep = volumep; setNumTEs(mVolumep->getNumFaces()); #endif return TRUE; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 78fd371087..7666009a62 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -919,7 +919,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool { //mesh is not loaded, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); - gPipeline.loadMesh(this, asset_id); + gPipeline.loadMesh(this, asset_id, detail); } else { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 4ac95fa939..3554ceb7f0 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8949,6 +8949,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } //no lower LOD is a available, is a higher lod available? @@ -8961,6 +8962,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } } } -- cgit v1.3 From 4e420a36c67e611cd7d85652b43d9cd65315e563 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 7 Nov 2009 08:22:39 -0600 Subject: Fix for missing LOD spam. --- indra/llmath/llvolume.cpp | 21 +++++++++++++++------ indra/llprimitive/llprimitive.cpp | 3 ++- indra/newview/pipeline.cpp | 2 ++ 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 33a8d33ce1..c8ef911cc1 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1676,7 +1676,8 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mFaceMask = 0x0; mDetail = detail; mSculptLevel = -2; - + mLODScaleBias.setVec(1,1,1); + // set defaults if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) { @@ -1690,8 +1691,6 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; - mLODScaleBias.setVec(1,1,1); - generate(); if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) @@ -1899,7 +1898,7 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) { if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024)) { - llwarns << "not a valid mesh asset!" << llendl; + llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl; return FALSE; } } @@ -1921,8 +1920,18 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) if (lod >= 4) { - llwarns << "Couldn't load model for given lod" << llendl; - return FALSE; + lod = llclamp((S32) mDetail, 0, 3); + + while (lod >= 0 && header[nm[lod]]["offset"].asInteger() == -1) + { + --lod; + } + + if (lod < 0) + { + llwarns << "Mesh header missing LOD offsets. Not a valid mesh asset!" << llendl; + return FALSE; + } } is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 340f60ed1a..4c6d244f3c 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -948,7 +948,8 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai #else // build the new object sVolumeManager->unrefVolume(mVolumep); - mVolumep = volumep; + mVolumep = volumep; + setNumTEs(mVolumep->getNumFaces()); #endif return TRUE; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3554ceb7f0..f13bb73acf 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8949,6 +8949,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } @@ -8962,6 +8963,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); return; } + group->derefLOD(lod); } } -- cgit v1.3 From c02702f3871979cb7745b49aa502ac3c71f77681 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 13 Nov 2009 17:01:56 -0600 Subject: CTS-7 Add hard edge threshold capability to normal generation. --- indra/llmath/llvolume.cpp | 12 ++++++++++++ indra/llmath/llvolume.h | 1 + 2 files changed, 13 insertions(+) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 6286d1bcea..f252b2a232 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1876,6 +1876,18 @@ bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)co return true; } +bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const +{ + bool retval = false; + if (rhs.mPosition == mPosition && rhs.mTexCoord == mTexCoord) + { + F32 cur_angle = rhs.mNormal*mNormal; + + retval = cur_angle > angle_cutoff; + } + + return retval; +} BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name) { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 9f595ccbc4..d2727d8f21 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -814,6 +814,7 @@ public: bool operator<(const VertexData& rhs) const; bool operator==(const VertexData& rhs) const; + bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; }; enum -- cgit v1.3 From 81bfdcbfae4f203e60f00794966383b01475995b Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 18 Nov 2009 18:10:48 -0600 Subject: Tetrahedron displays in place of unloaded mesh. Still has some LOD issues. --- indra/llmath/llvolume.cpp | 96 +++++++++++++++++++++++++++++++++++++++++++++- indra/llmath/llvolume.h | 1 + indra/newview/pipeline.cpp | 9 ++++- 3 files changed, 103 insertions(+), 3 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index f252b2a232..84da1b3c62 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1925,7 +1925,9 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) S32 lod = llclamp((S32) mDetail, 0, 3); - while (lod < 4 && header[nm[lod]]["offset"].asInteger() == -1) + while (lod < 4 && + (header[nm[lod]]["offset"].asInteger() == -1 || + header[nm[lod]]["size"].asInteger() == 0 )) { ++lod; } @@ -1934,7 +1936,9 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) { lod = llclamp((S32) mDetail, 0, 3); - while (lod >= 0 && header[nm[lod]]["offset"].asInteger() == -1) + while (lod >= 0 && + (header[nm[lod]]["offset"].asInteger() == -1 || + header[nm[lod]]["size"].asInteger() == 0) ) { --lod; } @@ -2135,6 +2139,94 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) return TRUE; } +void tetrahedron_set_normal(LLVolumeFace::VertexData* cv) +{ + LLVector3 nrm = (cv[1].mPosition-cv[0].mPosition)%(cv[2].mPosition-cv[0].mPosition); + + nrm.normVec(); + + cv[0].mNormal = nrm; + cv[1].mNormal = nrm; + cv[2].mNormal = nrm; +} + +void LLVolume::makeTetrahedron() +{ + mVolumeFaces.clear(); + + LLVolumeFace face; + + F32 x = 0.5f; + LLVector3 p[] = + { //unit tetrahedron corners + LLVector3(x,x,x), + LLVector3(-x,-x,x), + LLVector3(-x,x,-x), + LLVector3(x,-x,-x) + }; + + LLVolumeFace::VertexData cv[3]; + + //set texture coordinates + cv[0].mTexCoord = LLVector2(0,0); + cv[1].mTexCoord = LLVector2(1,0); + cv[2].mTexCoord = LLVector2(0.5f, 0.5f*F_SQRT3); + + + //side 1 + cv[0].mPosition = p[1]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[2]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 2 + cv[0].mPosition = p[3]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[1]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 3 + cv[0].mPosition = p[3]; + cv[1].mPosition = p[1]; + cv[2].mPosition = p[2]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //side 4 + cv[0].mPosition = p[2]; + cv[1].mPosition = p[0]; + cv[2].mPosition = p[3]; + + tetrahedron_set_normal(cv); + + face.mVertices.push_back(cv[0]); + face.mVertices.push_back(cv[1]); + face.mVertices.push_back(cv[2]); + + //set index buffer + for (U32 i = 0; i < 12; i++) + { + face.mIndices.push_back(i); + } + + mVolumeFaces.push_back(face); + mSculptLevel = 0; +} + void LLVolume::copyVolumeFaces(LLVolume* volume) { mVolumeFaces = volume->mVolumeFaces; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index d2727d8f21..bf2854ede9 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -969,6 +969,7 @@ protected: public: virtual BOOL createVolumeFacesFromFile(const std::string& file_name); virtual BOOL createVolumeFacesFromStream(std::istream& is); + virtual void makeTetrahedron(); protected: BOOL mUnique; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index c262e94ff4..3410ad6559 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8976,6 +8976,9 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); } } + + //nothing found, so make a tetrahedron + volume->makeTetrahedron(); } } @@ -9102,7 +9105,11 @@ void LLPipeline::notifyLoadedMeshes() if (valid) { - mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); + if (mesh->mVolume->getNumVolumeFaces() > 0) + { + mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); + } + for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); -- cgit v1.3 From 62233f22469cdc66042fc7bbbbd367dbb7212fde Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 24 Nov 2009 07:38:04 -0600 Subject: Fix for copying of tetrahedrons in place of mesh LODs. Fix for bad tetrahedron bounding box. Bad fix for simultaneous loading of multiple LODs. --- indra/llmath/llvolume.cpp | 31 +++++++++++++++++++++++++-- indra/llmath/llvolume.h | 5 ++++- indra/llmath/llvolumemgr.cpp | 13 ++++++++++++ indra/llmath/llvolumemgr.h | 1 + indra/newview/llvovolume.cpp | 31 ++++----------------------- indra/newview/llvovolume.h | 1 - indra/newview/pipeline.cpp | 50 +++++++++++++++++++++++++++++++++++--------- indra/newview/pipeline.h | 6 ++++-- 8 files changed, 95 insertions(+), 43 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 84da1b3c62..515b1061f9 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1676,6 +1676,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mFaceMask = 0x0; mDetail = detail; mSculptLevel = -2; + mIsTetrahedron = FALSE; mLODScaleBias.setVec(1,1,1); // set defaults @@ -1905,7 +1906,7 @@ BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name) BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) { mSculptLevel = -1; // default is an error occured - + LLSD header; { if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024)) @@ -2048,6 +2049,11 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) { U32 face_count = mdl.size(); + if (face_count == 0) + { + llerrs << "WTF?" << llendl; + } + mVolumeFaces.resize(face_count); for (U32 i = 0; i < face_count; ++i) @@ -2063,8 +2069,9 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) //copy out indices face.mIndices.resize(idx.size()/2); - if (idx.empty()) + if (idx.empty() || face.mIndices.size() < 3) { //why is there an empty index list? + llerrs <<"WTF?" << llendl; continue; } @@ -2150,6 +2157,11 @@ void tetrahedron_set_normal(LLVolumeFace::VertexData* cv) cv[2].mNormal = nrm; } +BOOL LLVolume::isTetrahedron() +{ + return mIsTetrahedron; +} + void LLVolume::makeTetrahedron() { mVolumeFaces.clear(); @@ -2165,6 +2177,9 @@ void LLVolume::makeTetrahedron() LLVector3(x,-x,-x) }; + face.mExtents[0].setVec(-x,-x,-x); + face.mExtents[1].setVec(x,x,x); + LLVolumeFace::VertexData cv[3]; //set texture coordinates @@ -2225,12 +2240,19 @@ void LLVolume::makeTetrahedron() mVolumeFaces.push_back(face); mSculptLevel = 0; + mIsTetrahedron = TRUE; } void LLVolume::copyVolumeFaces(LLVolume* volume) { + if (volume->isTetrahedron()) + { + llerrs << "WTF?" << llendl; + } + mVolumeFaces = volume->mVolumeFaces; mSculptLevel = 0; + mIsTetrahedron = FALSE; } S32 const LL_SCULPT_MESH_MAX_FACES = 8; @@ -2615,6 +2637,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, LLMemType m1(LLMemType::MTYPE_VOLUME); U8 sculpt_type = mParams.getSculptType(); + if (sculpt_type & LL_SCULPT_TYPE_MASK == LL_SCULPT_TYPE_MESH) + { + llerrs << "WTF?" << llendl; + } + BOOL data_is_empty = FALSE; if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index bf2854ede9..8e57f2e280 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -904,7 +904,8 @@ public: BOOL isUnique() const { return mUnique; } S32 getSculptLevel() const { return mSculptLevel; } - + void setSculptLevel(S32 level) { mSculptLevel = level; } + S32 *getTriangleIndices(U32 &num_indices) const; // returns number of triangle indeces required for path/profile mesh @@ -970,11 +971,13 @@ public: virtual BOOL createVolumeFacesFromFile(const std::string& file_name); virtual BOOL createVolumeFacesFromStream(std::istream& is); virtual void makeTetrahedron(); + virtual BOOL isTetrahedron(); protected: BOOL mUnique; F32 mDetail; S32 mSculptLevel; + BOOL mIsTetrahedron; LLVolumeParams mParams; LLPath *mPathp; diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 61c5a0adc9..419e0015ba 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -375,6 +375,19 @@ F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail) return mDetailScales[detail]; } +S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail) +{ + for (S32 i = 1; i < 4; i++) + { + if (mDetailScales[i] > detail) + { + return i-1; + } + } + + return 3; +} + F32 LLVolumeLODGroup::dump() { F32 usage = 0.f; diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index a78ea76a1a..f5dc4cd748 100644 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h @@ -59,6 +59,7 @@ public: static S32 getDetailFromTan(const F32 tan_angle); static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher); static F32 getVolumeScaleFromDetail(const S32 detail); + static S32 getVolumeDetailFromScale(F32 scale); LLVolume* refLOD(const S32 detail); BOOL derefLOD(LLVolume *volumep); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4c126d8fd9..64c2e9e8ec 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -163,7 +163,6 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mRelativeXformInvTrans.setIdentity(); mLOD = MIN_LOD; - mMeshSculptLevel = -2; mTextureAnimp = NULL; mVObjRadius = LLVector3(1,1,0.5f).length(); mNumFaces = 0; @@ -682,25 +681,7 @@ void LLVOVolume::updateTextureVirtualSize() LLUUID id = sculpt_params->getSculptTexture(); U8 sculpt_type = sculpt_params->getSculptType(); - if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - // mesh is a mesh - { - if (mMeshSculptLevel == -2) - { - // get the asset please - gPipeline.loadMesh(this, id); - /*gAssetStorage->getAssetData(id, LLAssetType::AT_MESH, (LLGetAssetCallback)NULL, NULL, TRUE); - - if (gAssetStorage->hasLocalAsset(id, LLAssetType::AT_MESH)) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); - mSculptChanged = TRUE; - }*/ - } - } - - else - // mesh is a sculptie + if ((sculpt_type & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) { mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); @@ -902,14 +883,10 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { if (getVolume()->getNumVolumeFaces() == 0) - { - //mesh is not loaded, request pipeline load this mesh + { + //load request not yet issued, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); - gPipeline.loadMesh(this, asset_id, detail); - } - else - { - mMeshSculptLevel = 1; + gPipeline.loadMesh(this, asset_id, LLVolumeLODGroup::getVolumeDetailFromScale(getVolume()->getDetail())); } } else // otherwise is sculptie diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 4b247f3778..f14a71130b 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -298,7 +298,6 @@ private: LLFrameTimer mTextureUpdateTimer; S32 mLOD; BOOL mLODChanged; - S32 mMeshSculptLevel; BOOL mSculptChanged; F32 mSpotLightPriority; LLMatrix4 mRelativeXform; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3410ad6559..0ee619244b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -8913,23 +8913,29 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) { + + if (detail < 0 || detail > 4) + { + return; + } + { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - mesh_load_map::iterator iter = mLoadingMeshes.find(mesh_id); - if (iter != mLoadingMeshes.end()) + mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id); + if (iter != mLoadingMeshes[detail].end()) { //request pending for this mesh, append volume id to list iter->second.insert(vobj->getID()); return; } //first request for this mesh - mLoadingMeshes[mesh_id].insert(vobj->getID()); + mLoadingMeshes[detail][mesh_id].insert(vobj->getID()); } if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) { //already have asset, load desired LOD in background - mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume())); + mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume(), detail)); } else { //fetch asset and load when done @@ -8952,7 +8958,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) for (S32 i = detail-1; i >= 0; --i) { LLVolume* lod = group->refLOD(i); - if (lod && lod->getNumVolumeFaces() > 0) + if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) { volume->copyVolumeFaces(lod); group->derefLOD(lod); @@ -8966,7 +8972,7 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) for (S32 i = detail+1; i < 4; ++i) { LLVolume* lod = group->refLOD(i); - if (lod && lod->getNumVolumeFaces() > 0) + if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) { volume->copyVolumeFaces(lod); group->derefLOD(lod); @@ -8976,6 +8982,10 @@ void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) group->derefLOD(lod); } } + else + { + llerrs << "WTF?" << llendl; + } //nothing found, so make a tetrahedron volume->makeTetrahedron(); @@ -8992,12 +9002,22 @@ void LLPipeline::getMeshAssetCallback(LLVFS *vfs, } -LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target) +LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail) : LLThread("mesh_loading_thread") { mMeshID = mesh_id; mVolume = NULL; mDetail = target->getDetail(); + + if (detail == -1) + { + mDetailIndex = LLVolumeLODGroup::getVolumeDetailFromScale(target->getDetail()); + } + else + { + mDetailIndex = detail; + } + mTargetVolume = target; } @@ -9073,6 +9093,10 @@ void LLPipeline::notifyLoadedMeshes() for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) { //for each mesh done loading + + + + LLMeshThread* mesh = *iter; if (!mesh->isStopped()) @@ -9081,10 +9105,12 @@ void LLPipeline::notifyLoadedMeshes() continue; } + S32 detail = mesh->mDetailIndex; + //get list of objects waiting to be notified this mesh is loaded - mesh_load_map::iterator obj_iter = mLoadingMeshes.find(mesh->mMeshID); + mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh->mMeshID); - if (mesh->mVolume && obj_iter != mLoadingMeshes.end()) + if (mesh->mVolume && obj_iter != mLoadingMeshes[detail].end()) { //make sure target volume is still valid BOOL valid = FALSE; @@ -9109,6 +9135,10 @@ void LLPipeline::notifyLoadedMeshes() { mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); } + else + { + llwarns << "Mesh loading returned empty volume." << llendl; + } for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { @@ -9120,7 +9150,7 @@ void LLPipeline::notifyLoadedMeshes() } } - mLoadingMeshes.erase(mesh->mMeshID); + mLoadingMeshes[detail].erase(mesh->mMeshID); } delete mesh; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 23e98aa0d6..a31379a209 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -676,8 +676,9 @@ public: protected: std::vector mSelectedFaces; + typedef std::map > mesh_load_map; - mesh_load_map mLoadingMeshes; + mesh_load_map mLoadingMeshes[4]; LLMutex* mMeshMutex; @@ -688,7 +689,8 @@ protected: LLVolume* mTargetVolume; LLUUID mMeshID; F32 mDetail; - LLMeshThread(LLUUID mesh_id, LLVolume* target); + S32 mDetailIndex; + LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail = -1); ~LLMeshThread(); void run(); }; -- cgit v1.3 From 6d66910c6e2fbb25bf8b5c7b90e795f350342104 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 25 Nov 2009 11:35:41 -0600 Subject: Fix for spam on invalid mesh asset. Fix for index buffer overflow spam and crash in llvertexbuffer. --- indra/llmath/llvolume.cpp | 5 ----- indra/newview/llvovolume.cpp | 5 +++-- indra/newview/pipeline.cpp | 18 ++++++------------ 3 files changed, 9 insertions(+), 19 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 515b1061f9..3e547aec6f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2245,11 +2245,6 @@ void LLVolume::makeTetrahedron() void LLVolume::copyVolumeFaces(LLVolume* volume) { - if (volume->isTetrahedron()) - { - llerrs << "WTF?" << llendl; - } - mVolumeFaces = volume->mVolumeFaces; mSculptLevel = 0; mIsTetrahedron = FALSE; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 64c2e9e8ec..3e9db86cfa 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -882,7 +882,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { - if (getVolume()->getNumVolumeFaces() == 0) + if (getVolume()->getNumVolumeFaces() == 0 || getVolume()->isTetrahedron()) { //load request not yet issued, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); @@ -924,7 +924,8 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool void LLVOVolume::notifyMeshLoaded() { mSculptChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + dirtySpatialGroup(TRUE); } // sculpt replaces generate() for sculpted surfaces diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 0ee619244b..af3a35615c 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1807,8 +1807,6 @@ void LLPipeline::rebuildPriorityGroups() assertInitialized(); - notifyLoadedMeshes(); - // Iterate through all drawables on the priority build queue, for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); iter != mGroupQ1.end(); ++iter) @@ -1888,6 +1886,8 @@ void LLPipeline::updateGeom(F32 max_dtime) // for now, only LLVOVolume does this to throttle LOD changes LLVOVolume::preUpdateGeom(); + notifyLoadedMeshes(); + // Iterate through all drawables on the priority build queue, for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); iter != mBuildQ1.end();) @@ -8913,7 +8913,6 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) { - if (detail < 0 || detail > 4) { return; @@ -9093,10 +9092,6 @@ void LLPipeline::notifyLoadedMeshes() for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) { //for each mesh done loading - - - - LLMeshThread* mesh = *iter; if (!mesh->isStopped()) @@ -9131,14 +9126,13 @@ void LLPipeline::notifyLoadedMeshes() if (valid) { - if (mesh->mVolume->getNumVolumeFaces() > 0) - { - mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); - } - else + if (mesh->mVolume->getNumVolumeFaces() <= 0) { llwarns << "Mesh loading returned empty volume." << llendl; + mesh->mVolume->makeTetrahedron(); } + + mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) { -- cgit v1.3 From 062a2dd309ca5521d4045eb721496476f43d24dc Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 30 Nov 2009 15:32:10 -0600 Subject: Remove zero area triangles from meshes post-import. --- indra/llmath/llvolume.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 3e547aec6f..1d36da7f52 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1692,10 +1692,9 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; - generate(); - if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { + generate(); createVolumeFaces(); } } -- cgit v1.3 From f039fa98efedc91965338ef53624279f99914205 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 30 Nov 2009 17:02:38 -0600 Subject: Fix for silly crash due to LLPrimitive having 0 texture entries. --- indra/llmath/llvolume.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 1d36da7f52..858bd9edea 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1692,9 +1692,10 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; + generate(); + if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) { - generate(); createVolumeFaces(); } } -- cgit v1.3 From bb2631180a85df343e6d816fc37d881af31d49fb Mon Sep 17 00:00:00 2001 From: "Karl Stiefvater (qarl)" Date: Tue, 1 Dec 2009 17:40:52 -0600 Subject: CTS-4 Only part of an uploaded mesh renders. --- indra/llmath/llvolume.cpp | 1 - indra/llmath/llvolume.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 858bd9edea..fb2de92e35 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2250,7 +2250,6 @@ void LLVolume::copyVolumeFaces(LLVolume* volume) mIsTetrahedron = FALSE; } -S32 const LL_SCULPT_MESH_MAX_FACES = 8; S32 LLVolume::getNumFaces() const { diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 8e57f2e280..59c60ccd92 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -192,6 +192,7 @@ const U8 LL_SCULPT_TYPE_MESH = 5; const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; +const S32 LL_SCULPT_MESH_MAX_FACES = 8; class LLProfileParams { -- cgit v1.3 From 695969c77066de5032bdc9caefecf9b32b076b2f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 11 Dec 2009 14:47:11 -0600 Subject: HTTP Mesh fetch FTW.. still busted --- indra/llcommon/llthread.cpp | 31 +++- indra/llcommon/llthread.h | 22 +++ indra/llmath/llvolume.cpp | 7 +- indra/llmath/llvolume.h | 2 + indra/newview/CMakeLists.txt | 2 + indra/newview/app_settings/settings.xml | 2 +- indra/newview/llappviewer.cpp | 8 + indra/newview/llviewerregion.cpp | 1 + indra/newview/llvovolume.cpp | 15 +- indra/newview/pipeline.cpp | 255 +------------------------------- indra/newview/pipeline.h | 34 +---- 11 files changed, 93 insertions(+), 286 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index b1175836b7..df7ea214cc 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -62,6 +62,9 @@ // //---------------------------------------------------------------------------- +U32 ll_thread_local sThreadID = 0; +U32 LLThread::sIDIter = 0; + // // Handed to the APR thread creation function // @@ -72,6 +75,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // Set thread state to running threadp->mStatus = RUNNING; + sThreadID = threadp->mID; + // Run the user supplied function threadp->run(); @@ -90,6 +95,8 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : mAPRThreadp(NULL), mStatus(STOPPED) { + mID = ++sIDIter; + // Thread creation probably CAN be paranoid about APR being initialized, if necessary if (poolp) { @@ -273,7 +280,7 @@ void LLThread::wakeLocked() //============================================================================ LLMutex::LLMutex(apr_pool_t *poolp) : - mAPRMutexp(NULL) + mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD) { //if (poolp) //{ @@ -305,7 +312,14 @@ LLMutex::~LLMutex() void LLMutex::lock() { + if (mLockingThread == sThreadID) + { //redundant lock + mCount++; + return; + } + apr_thread_mutex_lock(mAPRMutexp); + #if MUTEX_DEBUG // Have to have the lock before we can access the debug info U32 id = LLThread::currentID(); @@ -313,10 +327,18 @@ void LLMutex::lock() llerrs << "Already locked in Thread: " << id << llendl; mIsLocked[id] = TRUE; #endif + + mLockingThread = sThreadID; } void LLMutex::unlock() { + if (mCount > 0) + { //not the root unlock + mCount--; + return; + } + #if MUTEX_DEBUG // Access the debug info while we have the lock U32 id = LLThread::currentID(); @@ -324,6 +346,8 @@ void LLMutex::unlock() llerrs << "Not locked in Thread: " << id << llendl; mIsLocked[id] = FALSE; #endif + + mLockingThread = NO_THREAD; apr_thread_mutex_unlock(mAPRMutexp); } @@ -341,6 +365,11 @@ bool LLMutex::isLocked() } } +U32 LLMutex::lockingThread() const +{ + return mLockingThread; +} + //============================================================================ LLCondition::LLCondition(apr_pool_t *poolp) : diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index d8aa90de2e..2d553b5258 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -40,8 +40,17 @@ class LLThread; class LLMutex; class LLCondition; +#if LL_WINDOWS +#define ll_thread_local __declspec(thread) +#else +#define ll_thread_local __thread +#endif + class LL_COMMON_API LLThread { +private: + static U32 sIDIter; + public: typedef enum e_thread_status { @@ -82,6 +91,8 @@ public: apr_pool_t *getAPRPool() { return mAPRPoolp; } LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; } + U32 getID() const { return mID; } + private: BOOL mPaused; @@ -96,6 +107,7 @@ protected: apr_pool_t *mAPRPoolp; BOOL mIsLocalPool; EThreadStatus mStatus; + U32 mID; //a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used. //Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes. @@ -133,17 +145,27 @@ protected: class LL_COMMON_API LLMutex { public: + typedef enum + { + NO_THREAD = 0xFFFFFFFF + } e_locking_thread; + LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex ~LLMutex(); void lock(); // blocks void unlock(); bool isLocked(); // non-blocking, but does do a lock/unlock so not free + U32 lockingThread() const; //get ID of locking thread protected: apr_thread_mutex_t *mAPRMutexp; + mutable U32 mCount; + mutable U32 mLockingThread; + apr_pool_t *mAPRPoolp; BOOL mIsLocalPool; + S32 mLockCount; #if MUTEX_DEBUG std::map mIsLocked; #endif diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index fb2de92e35..44ff173502 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1952,8 +1952,12 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) } is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); - + return unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger()); +} + +BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) +{ U8* result = NULL; U32 cur_size = 0; @@ -1964,7 +1968,6 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) const U32 CHUNK = 65536; - S32 size = header[nm[lod]]["size"].asInteger(); U8 *in = new U8[size]; is.read((char*) in, size); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 59c60ccd92..9970b24a94 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -971,6 +971,8 @@ protected: public: virtual BOOL createVolumeFacesFromFile(const std::string& file_name); virtual BOOL createVolumeFacesFromStream(std::istream& is); + virtual BOOL unpackVolumeFaces(std::istream& is, S32 size); + virtual void makeTetrahedron(); virtual BOOL isTetrahedron(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 23f8b4b9ca..52adc740e3 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -284,6 +284,7 @@ set(viewer_SOURCE_FILES llmediaremotectrl.cpp llmemoryview.cpp llmenucommands.cpp + llmeshrepository.cpp llmetricperformancetester.cpp llmimetypes.cpp llmorphview.cpp @@ -789,6 +790,7 @@ set(viewer_HEADER_FILES llmediaremotectrl.h llmemoryview.h llmenucommands.h + llmeshrepository.h llmetricperformancetester.h llmimetypes.h llmorphview.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 4ed2927ce6..087472661f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9998,7 +9998,7 @@ Type Boolean Value - 1 + 0 UseStartScreen diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ddc818172d..a56e86c979 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -48,6 +48,7 @@ #include "llwindow.h" #include "llviewerstats.h" #include "llmd5.h" +#include "llmeshrepository.h" #include "llpumpio.h" #include "llmimetypes.h" #include "llslurl.h" @@ -1266,6 +1267,9 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning Up" << llendflush; + // shut down mesh streamer + gMeshRepo.shutdown(); + // Must clean up texture references before viewer window is destroyed. LLHUDManager::getInstance()->updateEffects(); LLHUDObject::updateAll(); @@ -1678,6 +1682,9 @@ bool LLAppViewer::initThreads() mFastTimerLogThread->start(); } + // Mesh streaming and caching + gMeshRepo.init(); + // *FIX: no error handling here! return true; } @@ -2394,6 +2401,7 @@ bool LLAppViewer::initWindow() gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); gPipeline.init(); + stop_glerror(); gViewerWindow->initGLDefaults(); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 8317837520..f173149bf4 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1432,6 +1432,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("FetchLib"); capabilityNames.append("FetchLibDescendents"); capabilityNames.append("GetTexture"); + capabilityNames.append("GetMesh"); capabilityNames.append("GroupProposalBallot"); capabilityNames.append("HomeLocation"); capabilityNames.append("MapLayer"); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7debfb9186..f66f0c2d72 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -70,6 +70,7 @@ #include "llsdutil.h" #include "llmediaentry.h" #include "llmediadataclient.h" +#include "llmeshrepository.h" #include "llagent.h" const S32 MIN_QUIET_FRAMES_COALESCE = 30; @@ -861,6 +862,16 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool { LLVolumeParams volume_params = params; + if (isSculpted()) + { + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { //meshes might not have all LODs, get the force detail to best existing LOD + LLUUID mesh_id = params.getSculptID(); + mLOD = gMeshRepo.getActualMeshLOD(mesh_id, mLOD); + } + } + // Check if we need to change implementations bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); if (is_flexible) @@ -888,6 +899,8 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool } } + + if ((LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) { mFaceMappingChanged = TRUE; @@ -906,7 +919,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool { //load request not yet issued, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); - gPipeline.loadMesh(this, asset_id, LLVolumeLODGroup::getVolumeDetailFromScale(getVolume()->getDetail())); + gMeshRepo.loadMesh(this, asset_id, LLVolumeLODGroup::getVolumeDetailFromScale(getVolume()->getDetail())); } } else // otherwise is sculptie diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 610804c5eb..b37645d2de 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -70,6 +70,7 @@ #include "llgldbg.h" #include "llhudmanager.h" #include "lllightconstants.h" +#include "llmeshrepository.h" #include "llresmgr.h" #include "llselectmgr.h" #include "llsky.h" @@ -103,6 +104,7 @@ #include "llspatialpartition.h" #include "llmutelist.h" #include "lltoolpie.h" +#include "llcurl.h" #ifdef _DEBUG @@ -342,8 +344,6 @@ LLPipeline::LLPipeline() : mGlowPool(NULL), mBumpPool(NULL), mWLSkyPool(NULL), - mMeshMutex(NULL), - mMeshThreadCount(0), mLightMask(0), mLightMovingMask(0), mLightingDetail(0), @@ -403,7 +403,6 @@ void LLPipeline::init() stop_glerror(); - mMeshMutex = new LLMutex(NULL); for (U32 i = 0; i < 2; ++i) { mSpotLightFade[i] = 1.f; @@ -478,9 +477,6 @@ void LLPipeline::cleanup() //delete mWLSkyPool; mWLSkyPool = NULL; - delete mMeshMutex; - mMeshMutex = NULL; - releaseGLBuffers(); mBloomImagep = NULL; @@ -1802,6 +1798,8 @@ void LLPipeline::rebuildPriorityGroups() assertInitialized(); + gMeshRepo.notifyLoadedMeshes(); + // Iterate through all drawables on the priority build queue, for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin(); iter != mGroupQ1.end(); ++iter) @@ -1881,8 +1879,6 @@ void LLPipeline::updateGeom(F32 max_dtime) // for now, only LLVOVolume does this to throttle LOD changes LLVOVolume::preUpdateGeom(); - notifyLoadedMeshes(); - // Iterate through all drawables on the priority build queue, for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); iter != mBuildQ1.end();) @@ -8912,246 +8908,3 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups() } -void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) -{ - if (detail < 0 || detail > 4) - { - return; - } - - { - LLMutexLock lock(mMeshMutex); - //add volume to list of loading meshes - mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id); - if (iter != mLoadingMeshes[detail].end()) - { //request pending for this mesh, append volume id to list - iter->second.insert(vobj->getID()); - return; - } - - //first request for this mesh - mLoadingMeshes[detail][mesh_id].insert(vobj->getID()); - } - - if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) - { //already have asset, load desired LOD in background - mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume(), detail)); - } - else - { //fetch asset and load when done - gAssetStorage->getAssetData(mesh_id, LLAssetType::AT_MESH, - getMeshAssetCallback, vobj->getVolume(), TRUE); - } - - //do a quick search to see if we can't display something while we wait for this mesh to load - LLVolume* volume = vobj->getVolume(); - - if (volume) - { - LLVolumeParams params = volume->getParams(); - - LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params); - - if (group) - { - //first see what the next lowest LOD available might be - for (S32 i = detail-1; i >= 0; --i) - { - LLVolume* lod = group->refLOD(i); - if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) - { - volume->copyVolumeFaces(lod); - group->derefLOD(lod); - return; - } - - group->derefLOD(lod); - } - - //no lower LOD is a available, is a higher lod available? - for (S32 i = detail+1; i < 4; ++i) - { - LLVolume* lod = group->refLOD(i); - if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) - { - volume->copyVolumeFaces(lod); - group->derefLOD(lod); - return; - } - - group->derefLOD(lod); - } - } - else - { - llerrs << "WTF?" << llendl; - } - - //nothing found, so make a tetrahedron - volume->makeTetrahedron(); - } -} - -//static -void LLPipeline::getMeshAssetCallback(LLVFS *vfs, - const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status) -{ - gPipeline.mPendingMeshes.push_back(new LLMeshThread(asset_uuid, (LLVolume*) user_data)); -} - - -LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail) -: LLThread("mesh_loading_thread") -{ - mMeshID = mesh_id; - mVolume = NULL; - mDetail = target->getDetail(); - - if (detail == -1) - { - mDetailIndex = LLVolumeLODGroup::getVolumeDetailFromScale(target->getDetail()); - } - else - { - mDetailIndex = detail; - } - - mTargetVolume = target; -} - -LLPipeline::LLMeshThread::~LLMeshThread() -{ - -} - -void LLPipeline::LLMeshThread::run() -{ - if (!gAssetStorage || LLApp::instance()->isQuitting()) - { - return; - } - - char* buffer = NULL; - S32 size = 0; - - LLVFS* vfs = gAssetStorage->mVFS; - - { - LLVFile file(vfs, mMeshID, LLAssetType::AT_MESH, LLVFile::READ); - file.waitForLock(VFSLOCK_READ); - size = file.getSize(); - - if (size == 0) - { - gPipeline.meshLoaded(this); - return; - } - - buffer = new char[size]; - file.read((U8*)&buffer[0], size); - } - - { - std::string buffer_string(buffer, size); - std::istringstream buffer_stream(buffer_string); - - { - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - volume_params.setSculptID(mMeshID, LL_SCULPT_TYPE_MESH); - mVolume = new LLVolume(volume_params, mDetail); - mVolume->createVolumeFacesFromStream(buffer_stream); - } - } - delete[] buffer; - - gPipeline.meshLoaded(this); -} - -void LLPipeline::meshLoaded(LLPipeline::LLMeshThread* mesh_thread) -{ - LLMutexLock lock(mMeshMutex); - mLoadedMeshes.push_back(mesh_thread); -} - -void LLPipeline::notifyLoadedMeshes() -{ //called from main thread - - U32 max_thread_count = llmax(gSavedSettings.getU32("MeshThreadCount"), (U32) 1); - while (mMeshThreadCount < max_thread_count && !mPendingMeshes.empty()) - { - LLMeshThread* mesh_thread = mPendingMeshes.front(); - mesh_thread->start(); - ++mMeshThreadCount; - mPendingMeshes.pop_front(); - } - - LLMutexLock lock(mMeshMutex); - std::list stopping_threads; - - for (std::list::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) - { //for each mesh done loading - LLMeshThread* mesh = *iter; - - if (!mesh->isStopped()) - { //don't process a LLMeshThread until it's stopped - stopping_threads.push_back(mesh); - continue; - } - - S32 detail = mesh->mDetailIndex; - - //get list of objects waiting to be notified this mesh is loaded - mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh->mMeshID); - - if (mesh->mVolume && obj_iter != mLoadingMeshes[detail].end()) - { - //make sure target volume is still valid - BOOL valid = FALSE; - - for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) - { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); - - if (vobj) - { - if (vobj->getVolume() == mesh->mTargetVolume) - { - valid = TRUE; - } - } - } - - - if (valid) - { - if (mesh->mVolume->getNumVolumeFaces() <= 0) - { - llwarns << "Mesh loading returned empty volume." << llendl; - mesh->mVolume->makeTetrahedron(); - } - - mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); - - for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) - { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); - if (vobj) - { - vobj->notifyMeshLoaded(); - } - } - } - - mLoadingMeshes[detail].erase(mesh->mMeshID); - } - - delete mesh; - --mMeshThreadCount; - } - - mLoadedMeshes = stopping_threads; -} - diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index f41f6173a9..0b040acf51 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -58,6 +58,8 @@ class LLCubeMap; class LLCullResult; class LLVOAvatar; class LLGLSLShader; +class LLCurlRequest; +class LLMeshResponder; typedef enum e_avatar_skinning_method { @@ -278,10 +280,6 @@ public: LLCullResult::sg_list_t::iterator beginAlphaGroups(); LLCullResult::sg_list_t::iterator endAlphaGroups(); - - //mesh management functions - void loadMesh(LLVOVolume* volume, LLUUID mesh_id, S32 detail = 0); - void addTrianglesDrawn(S32 count); BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1< > mesh_load_map; mesh_load_map mLoadingMeshes[4]; - LLMutex* mMeshMutex; - - class LLMeshThread : public LLThread - { - public: - LLPointer mVolume; - LLVolume* mTargetVolume; - LLUUID mMeshID; - F32 mDetail; - S32 mDetailIndex; - LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail = -1); - ~LLMeshThread(); - void run(); - }; - - static void getMeshAssetCallback(LLVFS *vfs, - const LLUUID& asset_uuid, - LLAssetType::EType type, - void* user_data, S32 status, LLExtStat ext_status); - - std::list mLoadedMeshes; - std::list mPendingMeshes; - U32 mMeshThreadCount; - - void meshLoaded(LLMeshThread* mesh_thread); - void notifyLoadedMeshes(); + typedef std::list mesh_response_list; + mesh_response_list mMeshResponseList; LLPointer mFaceSelectImagep; LLPointer mBloomImagep; -- cgit v1.3 From 081fa98a47d2b592ada0fbb049ff959ac2cd6294 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 15 Dec 2009 17:43:05 -0600 Subject: HTTP Mesh transfer relatively blocking-free. --- indra/llmath/llvolume.cpp | 2 +- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llvovolume.cpp | 20 ++++++++++++++++---- 3 files changed, 28 insertions(+), 5 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 44ff173502..844918432d 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2171,7 +2171,7 @@ void LLVolume::makeTetrahedron() LLVolumeFace face; - F32 x = 0.5f; + F32 x = 0.25f; LLVector3 p[] = { //unit tetrahedron corners LLVector3(x,x,x), diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a4142b41b0..4f17775dfd 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7463,6 +7463,17 @@ Value 8 + MeshMaxConcurrentRequests + + Comment + Number of threads to use for loading meshes. + Persist + 1 + Type + U32 + Value + 32 + SafeMode diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index f66f0c2d72..ea0aa54751 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -862,13 +862,21 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool { LLVolumeParams volume_params = params; + S32 lod = mLOD; + if (isSculpted()) { // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { //meshes might not have all LODs, get the force detail to best existing LOD LLUUID mesh_id = params.getSculptID(); - mLOD = gMeshRepo.getActualMeshLOD(mesh_id, mLOD); + + //profile and path params don't matter for meshes + volume_params = LLVolumeParams(); + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH); + + lod = gMeshRepo.getActualMeshLOD(mesh_id, lod); } } @@ -901,13 +909,13 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool - if ((LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) + if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) { mFaceMappingChanged = TRUE; if (mVolumeImpl) { - mVolumeImpl->onSetVolume(volume_params, detail); + mVolumeImpl->onSetVolume(volume_params, mLOD); } if (isSculpted()) @@ -919,7 +927,11 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool { //load request not yet issued, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); - gMeshRepo.loadMesh(this, asset_id, LLVolumeLODGroup::getVolumeDetailFromScale(getVolume()->getDetail())); + S32 available_lod = gMeshRepo.loadMesh(this, asset_id, lod); + if (available_lod != lod) + { + LLPrimitive::setVolume(volume_params, available_lod); + } } } else // otherwise is sculptie -- cgit v1.3 From 512a5736dceb1cc6db286e5f5baad867ac7a5935 Mon Sep 17 00:00:00 2001 From: "Karl Stiefvater (qarl)" Date: Wed, 23 Dec 2009 14:40:48 -0600 Subject: LODs for scene upload --- indra/llmath/llvolume.cpp | 14 ++++++++++++++ indra/llmath/llvolume.h | 2 ++ indra/newview/CMakeLists.txt | 2 ++ 3 files changed, 18 insertions(+) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 844918432d..de32070da1 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -3807,6 +3807,20 @@ S32 LLVolume::getNumTriangleIndices() const return count; } + +S32 LLVolume::getNumTriangles() const +{ + U32 triangle_count = 0; + + for (S32 i = 0; i < getNumVolumeFaces(); ++i) + { + triangle_count += getVolumeFace(i).mIndices.size()/3; + } + + return triangle_count; +} + + //----------------------------------------------------------------------------- // generateSilhouetteVertices() //----------------------------------------------------------------------------- diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 9970b24a94..e3ab648fe3 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -912,6 +912,8 @@ public: // returns number of triangle indeces required for path/profile mesh S32 getNumTriangleIndices() const; + S32 getNumTriangles() const; + void generateSilhouetteVertices(std::vector &vertices, std::vector &normals, std::vector &segments, diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 193109e9f4..cae426e37b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -285,6 +285,7 @@ set(viewer_SOURCE_FILES llmemoryview.cpp llmenucommands.cpp llmeshrepository.cpp + llmeshreduction.cpp llmetricperformancetester.cpp llmimetypes.cpp llmorphview.cpp @@ -796,6 +797,7 @@ set(viewer_HEADER_FILES llmemoryview.h llmenucommands.h llmeshrepository.h + llmeshreduction.h llmetricperformancetester.h llmimetypes.h llmorphview.h -- cgit v1.3 From d3e84ea77baa7d60fe225f7b440297e9a49318a6 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 20 Jan 2010 15:08:29 -0600 Subject: First stab at making model importer act more like scene importer. Upload button still doesn't work. --- indra/llmath/m4math.cpp | 17 +++++++++++++++++ indra/llmath/m4math.h | 1 + 2 files changed, 18 insertions(+) (limited to 'indra/llmath') diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 7c7f60154d..3700142982 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -785,6 +785,23 @@ bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b) return FALSE; } +bool operator<(const LLMatrix4& a, const LLMatrix4 &b) +{ + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + if (a.mMatrix[i][j] != b.mMatrix[i][j]) + { + return a.mMatrix[i][j] < b.mMatrix[i][j]; + } + } + } + + return false; +} + const LLMatrix4& operator*=(LLMatrix4 &a, F32 k) { U32 i, j; diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index de981b7646..6007b96bd9 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -237,6 +237,7 @@ public: friend bool operator==(const LLMatrix4 &a, const LLMatrix4 &b); // Return a == b friend bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b); // Return a != b + friend bool operator<(const LLMatrix4 &a, const LLMatrix4& b); // Return a < b friend const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b); // Return a + b friend const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b); // Return a - b -- cgit v1.3 From 024c0ebe19588f8452bae7ea01756fd7b4b30540 Mon Sep 17 00:00:00 2001 From: "Karl Stiefvater (qarl)" Date: Fri, 29 Jan 2010 14:33:04 -0600 Subject: enable mirror and invert flags for meshes. --- indra/llmath/llvolume.cpp | 59 +++++++++++++++++++++++++++++++++++++++++--- indra/llmath/llvolume.h | 7 +++--- indra/newview/llvovolume.cpp | 7 +++--- 3 files changed, 62 insertions(+), 11 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index de32070da1..0328c09c9a 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1694,7 +1694,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge generate(); - if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) + if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) { createVolumeFaces(); } @@ -2142,6 +2142,59 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) (F32) t[1] / 65535.f * tc_range.mV[1] + min_tc.mV[1]); } + + // modifier flags? + BOOL do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); + BOOL do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); + + + // translate to actions: + BOOL do_reflect_x = FALSE; + BOOL do_reverse_triangles = FALSE; + BOOL do_invert_normals = FALSE; + + if (do_mirror) + { + do_reflect_x = TRUE; + do_reverse_triangles = !do_reverse_triangles; + } + + if (do_invert) + { + do_invert_normals = TRUE; + do_reverse_triangles = !do_reverse_triangles; + } + + // now do the work + + if (do_reflect_x) + { + for (S32 i = 0; i < face.mVertices.size(); i++) + { + face.mVertices[i].mPosition.mV[VX] *= -1.0f; + face.mVertices[i].mNormal.mV[VX] *= -1.0f; + } + } + + if (do_invert_normals) + { + for (S32 i = 0; i < face.mVertices.size(); i++) + { + face.mVertices[i].mNormal *= -1.0f; + } + } + + if (do_reverse_triangles) + { + for (U32 j = 0; j < face.mIndices.size(); j += 3) + { + // swap the 2nd and 3rd index + S32 swap = face.mIndices[j+1]; + face.mIndices[j+1] = face.mIndices[j+2]; + face.mIndices[j+2] = swap; + } + } + } } @@ -3838,7 +3891,7 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, normals.clear(); segments.clear(); - if (mParams.getSculptType() == LL_SCULPT_TYPE_MESH) + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { return; } @@ -5500,7 +5553,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { mIndices.resize(num_indices); - if (volume->getParams().getSculptType() != LL_SCULPT_TYPE_MESH) + if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH) { mEdge.resize(num_indices); } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index e3ab648fe3..0bc64f4487 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -183,12 +183,11 @@ const U8 LL_SCULPT_TYPE_SPHERE = 1; const U8 LL_SCULPT_TYPE_TORUS = 2; const U8 LL_SCULPT_TYPE_PLANE = 3; const U8 LL_SCULPT_TYPE_CYLINDER = 4; - -const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER; - -// need to change this (these) names const U8 LL_SCULPT_TYPE_MESH = 5; +const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | + LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; + const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 4acf3cb6fb..3f1ddc0ee7 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -905,14 +905,13 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { //meshes might not have all LODs, get the force detail to best existing LOD + LLUUID mesh_id = params.getSculptID(); //profile and path params don't matter for meshes - volume_params = LLVolumeParams(); volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH); - lod = gMeshRepo.getActualMeshLOD(mesh_id, lod); + lod = gMeshRepo.getActualMeshLOD(volume_params, lod); } } @@ -963,7 +962,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool { //load request not yet issued, request pipeline load this mesh LLUUID asset_id = volume_params.getSculptID(); - S32 available_lod = gMeshRepo.loadMesh(this, asset_id, lod); + S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod); if (available_lod != lod) { LLPrimitive::setVolume(volume_params, available_lod); -- cgit v1.3 From 1805369b58d98677c726bb0bcb52618bd66e8fdd Mon Sep 17 00:00:00 2001 From: "Karl Stiefvater (qarl)" Date: Wed, 3 Feb 2010 18:08:19 -0600 Subject: handle reflected geometry in scene import implement determinant for 4x4 matrices fix materials for collada --- indra/llmath/m4math.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 3700142982..5c112b52b2 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -221,8 +221,33 @@ const LLMatrix4& LLMatrix4::transpose() F32 LLMatrix4::determinant() const { - llerrs << "Not implemented!" << llendl; - return 0.f; + F32 value = + mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][0] - + mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][0] - + mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][0] + + mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][0] + + mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][0] - + mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][0] - + mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][1] + + mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][1] + + mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][1] - + mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][1] - + mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][1] + + mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][1] + + mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][2] - + mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][2] - + mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][2] + + mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][2] + + mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][2] - + mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][2] - + mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][3] + + mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][3] + + mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][3] - + mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][3] - + mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][3] + + mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][3]; + + return value; } // Only works for pure orthonormal, homogeneous transform matrices. -- cgit v1.3 From 095a5e84408b47ef3c5610e111aefe51d77633ca Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 6 Feb 2010 17:33:12 -0600 Subject: Draw prims using triangle strips instead of triangle lists. --- indra/llmath/llvolume.cpp | 201 +++++++++++++++++++++++++------- indra/llmath/llvolume.h | 4 +- indra/newview/app_settings/settings.xml | 11 ++ indra/newview/lldrawpool.cpp | 4 +- indra/newview/lldrawpoolalpha.cpp | 8 +- indra/newview/lldrawpoolbump.cpp | 8 +- indra/newview/lldrawpooltree.cpp | 4 +- indra/newview/llface.cpp | 25 +++- indra/newview/llspatialpartition.cpp | 3 +- indra/newview/llspatialpartition.h | 1 + indra/newview/llviewercontrol.cpp | 1 + indra/newview/llviewerjointmesh.cpp | 2 +- indra/newview/llvotree.cpp | 6 +- indra/newview/llvovolume.cpp | 16 ++- indra/newview/llvowlsky.cpp | 2 +- indra/newview/pipeline.cpp | 15 ++- indra/newview/pipeline.h | 4 +- 17 files changed, 242 insertions(+), 73 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index df4c618ac1..cd7d7a12e3 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4520,15 +4520,65 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) if (!partial_build) { - int idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; - for(int gx = 0;gx=0;i--)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); - }else{ - for(int i=0;i<6;i++)mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); + mTriStrip.clear(); + S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; + for(S32 gx = 0;gx=0;i--) + { + mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); + } + + if (gy == 0) + { + mTriStrip.push_back((gx+1)*(grid_size+1)); + mTriStrip.push_back((gx+1)*(grid_size+1)); + mTriStrip.push_back(gx*(grid_size+1)); + } + + mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1)); + mTriStrip.push_back(gy+1+gx*(grid_size+1)); + + + if (gy == grid_size-1) + { + mTriStrip.push_back(gy+1+gx*(grid_size+1)); + } + } + else + { + for(S32 i=0;i<6;i++) + { + mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); + } + + if (gy == 0) + { + mTriStrip.push_back(gx*(grid_size+1)); + mTriStrip.push_back(gx*(grid_size+1)); + mTriStrip.push_back((gx+1)*(grid_size+1)); + } + + mTriStrip.push_back(gy+1+gx*(grid_size+1)); + mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1)); + + if (gy == grid_size-1) + { + mTriStrip.push_back(gy+1+(gx+1)*(grid_size+1)); + } } } + + } + + if (mTriStrip.size()%2 == 1) + { + mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); } } @@ -4770,6 +4820,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) pt2--; } } + + makeTriStrip(); } else { @@ -4874,67 +4926,108 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) pt2--; } } + + makeTriStrip(); } } else { // Not hollow, generate the triangle fan. + U16 v1 = 2; + U16 v2 = 1; + if (mTypeMask & TOP_MASK) { - if (mTypeMask & OPEN_MASK) - { - // SOLID OPEN TOP - // Generate indices - // This is a tri-fan, so we reuse the same first point for all triangles. - for (S32 i = 0; i < (num_vertices - 2); i++) - { - mIndices[3*i] = num_vertices - 1; - mIndices[3*i+1] = i; - mIndices[3*i+2] = i + 1; - } - } - else - { - // SOLID CLOSED TOP - for (S32 i = 0; i < (num_vertices - 2); i++) - { - //MSMSM fix these caps but only for the un-cut case - mIndices[3*i] = num_vertices - 1; - mIndices[3*i+1] = i; - mIndices[3*i+2] = i + 1; - } - } + v1 = 1; + v2 = 2; + } + + for (S32 i = 0; i < (num_vertices - 2); i++) + { + mIndices[3*i] = num_vertices - 1; + mIndices[3*i+v1] = i; + mIndices[3*i+v2] = i + 1; + } + + //make tri strip + if (mTypeMask & OPEN_MASK) + { + makeTriStrip(); } else { - if (mTypeMask & OPEN_MASK) + S32 j = num_vertices-2; + if (mTypeMask & TOP_MASK) { - // SOLID OPEN BOTTOM - // Generate indices - // This is a tri-fan, so we reuse the same first point for all triangles. - for (S32 i = 0; i < (num_vertices - 2); i++) + mTriStrip.push_back(0); + for (S32 i = 1; i <= j; ++i) { - mIndices[3*i] = num_vertices - 1; - mIndices[3*i+1] = i + 1; - mIndices[3*i+2] = i; + mTriStrip.push_back(i); + if (i != j) + { + mTriStrip.push_back(j); + } + --j; } } else { - // SOLID CLOSED BOTTOM - for (S32 i = 0; i < (num_vertices - 2); i++) + mTriStrip.push_back(j); + for (S32 i = 1; i <= j; ++i) { - //MSMSM fix these caps but only for the un-cut case - mIndices[3*i] = num_vertices - 1; - mIndices[3*i+1] = i + 1; - mIndices[3*i+2] = i; + if (i != j) + { + mTriStrip.push_back(j); + } + mTriStrip.push_back(i); + --j; } } + + mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); + + if (mTriStrip.size()%2 == 1) + { + mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); + } } } + return TRUE; } +void LLVolumeFace::makeTriStrip() +{ + for (U32 i = 0; i < mIndices.size(); i+=3) + { + U16 i0 = mIndices[i]; + U16 i1 = mIndices[i+1]; + U16 i2 = mIndices[i+2]; + + if ((i/3)%2 == 1) + { + mTriStrip.push_back(i0); + mTriStrip.push_back(i0); + mTriStrip.push_back(i1); + mTriStrip.push_back(i2); + mTriStrip.push_back(i2); + } + else + { + mTriStrip.push_back(i2); + mTriStrip.push_back(i2); + mTriStrip.push_back(i1); + mTriStrip.push_back(i0); + mTriStrip.push_back(i0); + } + } + + if (mTriStrip.size()%2 == 1) + { + mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); + } +} + void LLVolumeFace::createBinormals() { LLMemType m1(LLMemType::MTYPE_VOLUME); @@ -5135,9 +5228,14 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) if (!partial_build) { + mTriStrip.clear(); + // Now we generate the indices. for (t = 0; t < (mNumT-1); t++) { + //prepend terminating index to strip + mTriStrip.push_back(mNumS*t); + for (s = 0; s < (mNumS-1); s++) { mIndices[cur_index++] = s + mNumS*t; //bottom left @@ -5147,6 +5245,14 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) mIndices[cur_index++] = s+1 + mNumS*t; //bottom right mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right + if (s == 0) + { + mTriStrip.push_back(s+mNumS*t); + mTriStrip.push_back(s+mNumS*(t+1)); + } + mTriStrip.push_back(s+1+mNumS*t); + mTriStrip.push_back(s+1+mNumS*(t+1)); + mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1; //bottom left/top right neighbor face if (t < mNumT-2) { //top right/top left neighbor face mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1; @@ -5187,6 +5293,13 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) } mEdge[cur_edge++] = (mNumS-1)*2*t+s*2; //top right/bottom left neighbor face } + //append terminating vertex to strip + mTriStrip.push_back(mNumS-1+mNumS*(t+1)); + } + + if (mTriStrip.size()%2 == 1) + { + mTriStrip.push_back(mTriStrip[mTriStrip.size()-1]); } } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 871b334452..d9f80f0e30 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -798,7 +798,8 @@ public: BOOL create(LLVolume* volume, BOOL partial_build = FALSE); void createBinormals(); - + void makeTriStrip(); + class VertexData { public: @@ -839,6 +840,7 @@ public: std::vector mVertices; std::vector mIndices; + std::vector mTriStrip; std::vector mEdge; private: diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8a447502b0..ce19dda9a5 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7386,6 +7386,17 @@ Value 1 + RenderUseTriStrips + + Comment + Use triangle strips for rendering prims. + Persist + 1 + Type + Boolean + Value + 1 + RenderUseFarClip Comment diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 95ddacb722..ef946ac49e 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -496,8 +496,8 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) params.mGroup->rebuildMesh(); } params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount/3); + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); } if (params.mTextureMatrix && texture && params.mTexture.notNull()) diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 6d77361414..0e02bc4b01 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -250,8 +250,8 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) params.mGroup->rebuildMesh(); } params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount/3); + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); } } } @@ -380,8 +380,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount/3); + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); if (params.mTextureMatrix && params.mTexture.notNull()) { diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 03a8b108e2..d09d4a412f 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -560,8 +560,8 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL params.mGroup->rebuildMesh(); } params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount/3); + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); } } @@ -1231,8 +1231,8 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) params.mGroup->rebuildMesh(); } params.mVertexBuffer->setBuffer(mask); - params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); - gPipeline.addTrianglesDrawn(params.mCount/3); + params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); + gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); if (params.mTextureMatrix) { if (mShiny) diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 5521fb05a8..1a5d55d793 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -115,7 +115,7 @@ void LLDrawPoolTree::render(S32 pass) LLFace *face = *iter; face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); - gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3); + gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()); } } } @@ -237,7 +237,7 @@ void LLDrawPoolTree::renderForSelect() face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); - gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3); + gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()); } } } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 965ac1cad0..93840e077c 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -868,7 +868,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, llpushcallstacks ; const LLVolumeFace &vf = volume.getVolumeFace(f); S32 num_vertices = (S32)vf.mVertices.size(); - S32 num_indices = (S32)vf.mIndices.size(); + S32 num_indices = LLPipeline::sUseTriStrips ? (S32)vf.mTriStrip.size() : (S32) vf.mIndices.size(); if (mVertexBuffer.notNull()) { @@ -1058,9 +1058,19 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); - for (U16 i = 0; i < num_indices; i++) + if (LLPipeline::sUseTriStrips) { - *indicesp++ = vf.mIndices[i] + index_offset; + for (U16 i = 0; i < num_indices; i++) + { + *indicesp++ = vf.mTriStrip[i] + index_offset; + } + } + else + { + for (U16 i = 0; i < num_indices; i++) + { + *indicesp++ = vf.mIndices[i] + index_offset; + } } } @@ -1572,8 +1582,13 @@ S32 LLFace::pushVertices(const U16* index_array) const { if (mIndicesCount) { - mVertexBuffer->drawRange(LLRender::TRIANGLES, mGeomIndex, mGeomIndex+mGeomCount-1, mIndicesCount, mIndicesIndex); - gPipeline.addTrianglesDrawn(mIndicesCount/3); + U32 render_type = LLRender::TRIANGLES; + if (mDrawInfo) + { + render_type = mDrawInfo->mDrawMode; + } + mVertexBuffer->drawRange(render_type, mGeomIndex, mGeomIndex+mGeomCount-1, mIndicesCount, mIndicesIndex); + gPipeline.addTrianglesDrawn(mIndicesCount, render_type); } return mIndicesCount; diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 2a57d48f16..d6e9256fee 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3380,7 +3380,8 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, mVSize(0.f), mGroup(NULL), mFace(NULL), - mDistance(0.f) + mDistance(0.f), + mDrawMode(LLRender::TRIANGLES) { mDebugColor = (rand() << 16) + rand(); if (mStart >= mVertexBuffer->getRequestedVerts() || diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 64c2a9acbc..7896488379 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -93,6 +93,7 @@ public: LLFace* mFace; //associated face F32 mDistance; LLVector3 mExtents[2]; + U32 mDrawMode; struct CompareTexture { diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 827d34138f..0b7f6900ed 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -510,6 +510,7 @@ void settings_setup_listeners() gSavedSettings.getControl("FirstPersonAvatarVisible")->getSignal()->connect(boost::bind(&handleRenderAvatarMouselookChanged, _2)); gSavedSettings.getControl("RenderFarClip")->getSignal()->connect(boost::bind(&handleRenderFarClipChanged, _2)); gSavedSettings.getControl("RenderTerrainDetail")->getSignal()->connect(boost::bind(&handleTerrainDetailChanged, _2)); + gSavedSettings.getControl("RenderUseTriStrips")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 1a67fc0966..7225aa1523 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -626,7 +626,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); glPopMatrix(); } - gPipeline.addTrianglesDrawn(count/3); + gPipeline.addTrianglesDrawn(count); triangle_count += count; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 24f1c4bd24..55e2c58a52 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -1141,7 +1141,7 @@ U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD glLoadMatrixf((F32*) scale_mat.mMatrix); glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_SHORT, indicesp + sLODIndexOffset[trunk_LOD]); - gPipeline.addTrianglesDrawn(LEAF_INDICES/3); + gPipeline.addTrianglesDrawn(LEAF_INDICES); stop_glerror(); ret += sLODIndexCount[trunk_LOD]; } @@ -1191,7 +1191,7 @@ U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD glLoadMatrixf((F32*) scale_mat.mMatrix); glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp); - gPipeline.addTrianglesDrawn(LEAF_INDICES/3); + gPipeline.addTrianglesDrawn(LEAF_INDICES); stop_glerror(); ret += LEAF_INDICES; } @@ -1216,7 +1216,7 @@ U32 LLVOTree::drawBranchPipeline(LLMatrix4& matrix, U16* indicesp, S32 trunk_LOD glLoadMatrixf((F32*) scale_mat.mMatrix); glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_SHORT, indicesp); - gPipeline.addTrianglesDrawn(LEAF_INDICES/3); + gPipeline.addTrianglesDrawn(LEAF_INDICES); stop_glerror(); ret += LEAF_INDICES; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 25ed931fb5..b87ad7fc47 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1514,7 +1514,14 @@ void LLVOVolume::updateFaceSize(S32 idx) else { const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + if (LLPipeline::sUseTriStrips) + { + facep->setSize(vol_face.mVertices.size(), vol_face.mTriStrip.size()); + } + else + { + facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + } } } @@ -3264,6 +3271,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mExtents[0] = facep->mExtents[0]; draw_info->mExtents[1] = facep->mExtents[1]; validate_draw_info(*draw_info); + + if (LLPipeline::sUseTriStrips) + { + draw_info->mDrawMode = LLRender::TRIANGLE_STRIP; + } } } @@ -3348,7 +3360,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); - if (cur_total > max_total) + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) { facep->mVertexBuffer = NULL; facep->mLastVertexBuffer = NULL; diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 0272a2ab34..1749ccef94 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -519,7 +519,7 @@ void LLVOWLSky::drawDome(void) LLRender::TRIANGLE_STRIP, 0, strips_segment->getRequestedVerts()-1, strips_segment->getRequestedIndices(), 0); - gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices() - 2); + gPipeline.addTrianglesDrawn(strips_segment->getRequestedIndices(), LLRender::TRIANGLE_STRIP); } #else diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index d5f87b73fe..91da9e39e0 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -270,6 +270,7 @@ BOOL LLPipeline::sDelayVBUpdate = TRUE; BOOL LLPipeline::sFastAlpha = TRUE; BOOL LLPipeline::sDisableShaders = FALSE; BOOL LLPipeline::sRenderBump = TRUE; +BOOL LLPipeline::sUseTriStrips = TRUE; BOOL LLPipeline::sUseFarClip = TRUE; BOOL LLPipeline::sShadowRender = FALSE; BOOL LLPipeline::sWaterReflections = FALSE; @@ -358,6 +359,7 @@ void LLPipeline::init() sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); + sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); @@ -3495,9 +3497,19 @@ void LLPipeline::renderGeomShadow(LLCamera& camera) } -void LLPipeline::addTrianglesDrawn(S32 count) +void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type) { assertInitialized(); + S32 count = 0; + if (render_type == LLRender::TRIANGLE_STRIP) + { + count = index_count-2; + } + else + { + count = index_count/3; + } + mTrianglesDrawn += count; mBatchCount++; mMaxBatchSize = llmax(mMaxBatchSize, count); @@ -5349,6 +5361,7 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) void LLPipeline::resetVertexBuffers() { sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); + sUseTriStrips = gSavedSettings.getBOOL("RenderUseTriStrips"); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index c5285943e8..1bf2ee941b 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -277,7 +277,7 @@ public: LLCullResult::sg_list_t::iterator beginAlphaGroups(); LLCullResult::sg_list_t::iterator endAlphaGroups(); - void addTrianglesDrawn(S32 count); + void addTrianglesDrawn(S32 index_count, U32 render_type = LLRender::TRIANGLES); BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1< Date: Mon, 8 Feb 2010 10:14:11 -0600 Subject: Enable FBO multisampling for OSX. Fix bad triangle in prim caps. --- indra/llmath/llvolume.cpp | 4 ++-- indra/llrender/llrendertarget.cpp | 11 ----------- indra/newview/llviewerdisplay.cpp | 4 ++++ 3 files changed, 6 insertions(+), 13 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index cd7d7a12e3..ae5c9bc8cf 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -4960,7 +4960,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) if (mTypeMask & TOP_MASK) { mTriStrip.push_back(0); - for (S32 i = 1; i <= j; ++i) + for (S32 i = 0; i <= j; ++i) { mTriStrip.push_back(i); if (i != j) @@ -4973,7 +4973,7 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) else { mTriStrip.push_back(j); - for (S32 i = 1; i <= j; ++i) + for (S32 i = 0; i <= j; ++i) { if (i != j) { diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index d9520b3bf6..3f2558f1f5 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -390,8 +390,6 @@ void LLRenderTarget::flush(BOOL fetch_depth) } else { -#if !LL_DARWIN - stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); @@ -435,7 +433,6 @@ void LLRenderTarget::flush(BOOL fetch_depth) } } } -#endif glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } @@ -444,7 +441,6 @@ void LLRenderTarget::flush(BOOL fetch_depth) void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { -#if !LL_DARWIN gGL.flush(); if (!source.mFBO || !mFBO) { @@ -483,14 +479,12 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, stop_glerror(); } } -#endif } //static void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { -#if !LL_DARWIN if (!source.mFBO) { llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; @@ -507,7 +501,6 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); stop_glerror(); } -#endif } BOOL LLRenderTarget::isComplete() const @@ -652,7 +645,6 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) { -#if !LL_DARWIN if (color_fmt == 0) { return; @@ -693,12 +685,10 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) } mTex.push_back(tex); -#endif } void LLMultisampleBuffer::allocateDepth() { -#if !LL_DARWIN glGenRenderbuffersEXT(1, (GLuint* ) &mDepth); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); if (mStencil) @@ -709,6 +699,5 @@ void LLMultisampleBuffer::allocateDepth() { glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY); } -#endif } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index ba256d70e8..64b3bccd4c 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -862,10 +862,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.mDeferredScreen.flush(); + LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), + 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); } else { gPipeline.mScreen.flush(); + LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), gPipeline.mScreen.getHeight(), + 0, 0, gPipeline.mScreen.getWidth(), gPipeline.mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); } } -- cgit v1.3 From 2cb5b0b66ec9633d4c6563acf5ff9d0f7bc7cbf7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 9 Feb 2010 12:26:09 -0600 Subject: consolidate button work in progress --- indra/llmath/llvolume.cpp | 19 +++++++++++++++++++ indra/llmath/llvolume.h | 2 ++ 2 files changed, 21 insertions(+) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index de32070da1..596c5fe231 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5468,6 +5468,25 @@ void LLVolumeFace::createBinormals() } } +void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& norm_transform) +{ + for (U32 i = 0; i < face.mVertices.size(); ++i) + { + VertexData v = face.mVertices[i]; + v.mPosition *= mat; + v.mNormal *= norm_transform; + + + mVertices.push_back(v); + } + + U16 offset = mIndices.size(); + for (U32 i = 0; i < face.mIndices.size(); ++i) + { + mIndices.push_back(face.mIndices[i]+offset); + } +} + BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { LLMemType m1(LLMemType::MTYPE_VOLUME); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index e3ab648fe3..1bf6fac305 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -805,6 +805,8 @@ public: BOOL create(LLVolume* volume, BOOL partial_build = FALSE); void createBinormals(); + void appendFace(const LLVolumeFace& face); + class VertexData { public: -- cgit v1.3 From ffcbbf4aaabc652c2050ca6147a9388217cfcaa7 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 11 Feb 2010 18:00:00 -0600 Subject: Multi-threaded asset uploading with proper ordering first draft. --- indra/llmath/llvolume.cpp | 20 ++++++++++++++++---- indra/llmath/llvolume.h | 2 +- indra/llmessage/llcurl.cpp | 28 ++++++++++++++++++++++++++++ indra/llmessage/llcurl.h | 3 +++ indra/llmessage/llhttpclient.cpp | 1 + indra/newview/llface.cpp | 4 ++-- indra/newview/llviewermenufile.h | 10 ++++++++++ 7 files changed, 61 insertions(+), 7 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index d1716e1407..7e1517fba7 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5614,19 +5614,31 @@ void LLVolumeFace::createBinormals() } } -void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& norm_transform) +void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat, LLMatrix4& norm_mat) { + U16 offset = mVertices.size(); + + for (U32 i = 0; i < face.mVertices.size(); ++i) { VertexData v = face.mVertices[i]; - v.mPosition *= mat; - v.mNormal *= norm_transform; + v.mPosition = v.mPosition*mat; + v.mNormal = v.mNormal * norm_mat; mVertices.push_back(v); + + if (offset == 0 && i == 0) + { + mExtents[0] = mExtents[1] = v.mPosition; + } + else + { + update_min_max(mExtents[0], mExtents[1], v.mPosition); + } } - U16 offset = mIndices.size(); + for (U32 i = 0; i < face.mIndices.size(); ++i) { mIndices.push_back(face.mIndices[i]+offset); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 1059c29566..36811785dc 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -805,7 +805,7 @@ public: void createBinormals(); void makeTriStrip(); - void appendFace(const LLVolumeFace& face); + void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform); class VertexData { diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 024e17a777..b93b94cd25 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -55,6 +55,7 @@ #include "llstl.h" #include "llsdserialize.h" #include "llthread.h" +#include "llvfile.h" ////////////////////////////////////////////////////////////////////////////// /* @@ -801,7 +802,34 @@ bool LLCurlRequest::post(const std::string& url, bool res = addEasy(easy); return res; } + +bool LLCurlRequest::post(const std::string& url, + const headers_t& headers, + const std::string& data, + LLCurl::ResponderPtr responder) +{ + LLCurl::Easy* easy = allocEasy(); + if (!easy) + { + return false; + } + easy->prepRequest(url, headers, responder); + + easy->getInput().write(data.data(), data.size()); + S32 bytes = easy->getInput().str().length(); + easy->setopt(CURLOPT_POST, 1); + easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL); + easy->setopt(CURLOPT_POSTFIELDSIZE, bytes); + + easy->slist_append("Content-Type: application/octet-stream"); + easy->setHeaders(); + + lldebugs << "POSTING: " << bytes << " bytes." << llendl; + bool res = addEasy(easy); + return res; +} + // Note: call once per frame S32 LLCurlRequest::process() { diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index caf02cccd9..4302c19113 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -44,6 +44,7 @@ #include #include // TODO: remove dependency +#include "llassettype.h" #include "llbuffer.h" #include "lliopipe.h" #include "llsd.h" @@ -213,6 +214,8 @@ public: void get(const std::string& url, LLCurl::ResponderPtr responder); bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder); bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder); + bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder); + S32 process(); S32 getQueued(); diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index dd56e18caf..46952fa434 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -194,6 +194,7 @@ namespace fileBuffer = new U8 [fileSize]; vfile.read(fileBuffer, fileSize); ostream.write((char*)fileBuffer, fileSize); + delete [] fileBuffer; eos = true; return STATUS_DONE; } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 0a9976f511..4822c303bf 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1081,14 +1081,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); if (LLPipeline::sUseTriStrips) { - for (U16 i = 0; i < num_indices; i++) + for (U32 i = 0; i < num_indices; i++) { *indicesp++ = vf.mTriStrip[i] + index_offset; } } else { - for (U16 i = 0; i < num_indices; i++) + for (U32 i = 0; i < num_indices; i++) { *indicesp++ = vf.mIndices[i] + index_offset; } diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 7167903311..7ffa5d5e57 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -100,4 +100,14 @@ void assign_defaults_and_show_upload_message( const std::string& display_name, std::string& description); +LLSD generate_new_resource_upload_capability_body( + LLAssetType::EType asset_type, + const std::string& name, + const std::string& desc, + LLFolderType::EType destination_folder_type, + LLInventoryType::EType inv_type, + U32 next_owner_perms, + U32 group_perms, + U32 everyone_perms); + #endif -- cgit v1.3 From ee8036712847315141c78d37646d629796442d09 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 17 Feb 2010 18:08:00 -0600 Subject: 16-bit limit awareness when consolidating models. --- indra/llmath/llvolume.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 7c98536e72..33a00b80ca 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5619,6 +5619,10 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat, LLMatrix { U16 offset = mVertices.size(); + if (face.mVertices.size() + mVertices.size() > 65536) + { + llerrs << "Cannot append face -- 16-bit overflow will occur." << llendl; + } for (U32 i = 0; i < face.mVertices.size(); ++i) { -- cgit v1.3 From 237f1a1ba362aa2dfd9bb386e431713bdfcad2dc Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 19 Feb 2010 12:41:08 -0600 Subject: Consolidate now preserves materials. --- indra/llmath/v4color.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'indra/llmath') diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index d6fbdec61e..6b63b976b0 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -114,6 +114,7 @@ class LLColor4 const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4 + bool operator<(const LLColor4& rhs) const; friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b @@ -595,6 +596,23 @@ inline LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u) a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); } +inline bool LLColor4::operator<(const LLColor4& rhs) const +{ + if (mV[0] != rhs.mV[0]) + { + return mV[0] < rhs.mV[0]; + } + if (mV[1] != rhs.mV[1]) + { + return mV[1] < rhs.mV[1]; + } + if (mV[2] != rhs.mV[2]) + { + return mV[2] < rhs.mV[2]; + } + + return mV[3] < rhs.mV[3]; +} void LLColor4::clamp() { -- cgit v1.3 From 066f9de07ecfcf142103f646695e5be63a22a667 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 23 Feb 2010 16:57:06 -0600 Subject: Fix for normals getting squished on consolidation. Replaced some magic numbers with constants. Switched up throttling of mesh upload HTTP posts to prevent overloading one capability at a time. Added some feedback on upload progress via debug text. Made debug text move with side panel (keep debug text from rendering on top of side panel). --- indra/llmath/llvolume.cpp | 1 + indra/newview/llviewerwindow.cpp | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 33a00b80ca..704308f20f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -5630,6 +5630,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat, LLMatrix v.mPosition = v.mPosition*mat; v.mNormal = v.mNormal * norm_mat; + v.mNormal.normalize(); mVertices.push_back(v); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index fd59ea41b2..5c039c9f94 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -31,7 +31,6 @@ */ #include "llviewerprecompiledheaders.h" - #include "llviewerwindow.h" #if LL_WINDOWS @@ -45,6 +44,7 @@ #include #include "llfloaterreg.h" +#include "llmeshrepository.h" #include "llpanellogin.h" #include "llviewerkeyboard.h" #include "llviewermenu.h" @@ -318,7 +318,7 @@ public: mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f ); // Draw stuff growing up from right lower corner of screen - U32 xpos = mWindow->getWindowWidthScaled() - 350; + U32 xpos = mWindow->getWorldViewWidthScaled() - 350; U32 ypos = 64; const U32 y_inc = 20; @@ -583,6 +583,22 @@ public: ypos += y_inc; } } + + //temporary hack to give feedback on mesh upload progress + if (!gMeshRepo.mUploads.empty()) + { + for (std::vector::iterator iter = gMeshRepo.mUploads.begin(); + iter != gMeshRepo.mUploads.end(); ++iter) + { + LLMeshUploadThread* thread = *iter; + + addText(xpos, ypos, llformat("Mesh Upload -- price quote: %d:%d | upload: %d:%d | create: %d", + thread->mPendingConfirmations, thread->mUploadQ.size(), + thread->mPendingUploads, thread->mConfirmedQ.size(), + thread->mCompletedQ.size())); + ypos += y_inc; + } + } } void draw() -- cgit v1.3 From 3c78771acee787e087bd2e2391397794d4d98f6d Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 24 Feb 2010 22:02:01 -0600 Subject: Removed scale from model importer. Removed support for scale entry in mesh assets. Fixed MeshMaxConcurrentRequests being ignored. Added mesh download queue debug text. --- indra/llmath/llvolume.cpp | 4 ---- indra/newview/llviewerwindow.cpp | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 704308f20f..904786079f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2098,8 +2098,6 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); - F32 scale = llclamp((F32) mdl[i]["Scale"].asReal(), 1.f, 10.f); - LLVector3 pos_range = max_pos - min_pos; LLVector2 tc_range = max_tc - min_tc; @@ -2117,8 +2115,6 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) (F32) v[1] / 65535.f * pos_range.mV[1] + min_pos.mV[1], (F32) v[2] / 65535.f * pos_range.mV[2] + min_pos.mV[2]); - face.mVertices[j].mPosition *= scale; - if (j == 0) { min = max = face.mVertices[j].mPosition; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 6bdb322c09..f554acf1df 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -599,6 +599,20 @@ public: ypos += y_inc; } } + + S32 pending = (S32) gMeshRepo.mPendingRequests.size(); + S32 header = (S32) gMeshRepo.mThread->mHeaderReqQ.size(); + S32 lod = (S32) gMeshRepo.mThread->mLODReqQ.size(); + + if (pending + header + lod + LLMeshRepoThread::sActiveHeaderRequests + LLMeshRepoThread::sActiveLODRequests != 0) + { + addText(xpos, ypos, llformat ("Mesh Queue - %d pending (%d:%d header | %d:%d LOD)", + pending, + LLMeshRepoThread::sActiveHeaderRequests, header, + LLMeshRepoThread::sActiveLODRequests, lod)); + + ypos += y_inc; + } } void draw() -- cgit v1.3 From b414b5067e3e47da7d9baf490d94534b4c65a8eb Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sun, 28 Feb 2010 16:40:30 -0600 Subject: Remove some dead code. Add LH transform to LLVector3 Add DebugShowUploadCost Make LOD generation on model preview less finnicky. Remove error level based LOD generation. Better framing of model before upload. Better error handling for model uploader. Remove [COST] argument from model upload menu item. Remove L$ check from model upload menu item being enabled. --- indra/llmath/m4math.cpp | 31 ------------ indra/llmath/m4math.h | 5 +- indra/llmath/v3math.cpp | 22 +++++++++ indra/llmath/v3math.h | 3 ++ indra/llrender/llvertexbuffer.cpp | 6 +++ indra/newview/app_settings/settings.xml | 13 ++++- indra/newview/llviewermenu.cpp | 3 +- indra/newview/llviewermenufile.cpp | 10 ++++ indra/newview/llviewermessage.cpp | 1 - indra/newview/llviewerwindow.cpp | 14 ++++++ indra/newview/pipeline.cpp | 57 ++++++++++++++++++++++ indra/newview/pipeline.h | 4 ++ .../skins/default/xui/en/menu_inventory_add.xml | 4 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 11 +++++ .../skins/default/xui/en/panel_main_inventory.xml | 4 +- 15 files changed, 145 insertions(+), 43 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index 5c112b52b2..ce5428f0e1 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -684,37 +684,6 @@ const LLMatrix4& LLMatrix4::initMatrix(const LLMatrix3 &mat, const LLVector4 & // LLMatrix4 Operators - -/* Not implemented to help enforce code consistency with the syntax of - row-major notation. This is a Good Thing. -LLVector4 operator*(const LLMatrix4 &a, const LLVector4 &b) -{ - // Operate "to the right" on column-vector b - LLVector4 vec; - vec.mV[VX] = a.mMatrix[VX][VX] * b.mV[VX] + - a.mMatrix[VY][VX] * b.mV[VY] + - a.mMatrix[VZ][VX] * b.mV[VZ] + - a.mMatrix[VW][VX] * b.mV[VW]; - - vec.mV[VY] = a.mMatrix[VX][VY] * b.mV[VX] + - a.mMatrix[VY][VY] * b.mV[VY] + - a.mMatrix[VZ][VY] * b.mV[VZ] + - a.mMatrix[VW][VY] * b.mV[VW]; - - vec.mV[VZ] = a.mMatrix[VX][VZ] * b.mV[VX] + - a.mMatrix[VY][VZ] * b.mV[VY] + - a.mMatrix[VZ][VZ] * b.mV[VZ] + - a.mMatrix[VW][VZ] * b.mV[VW]; - - vec.mV[VW] = a.mMatrix[VX][VW] * b.mV[VX] + - a.mMatrix[VY][VW] * b.mV[VY] + - a.mMatrix[VZ][VW] * b.mV[VZ] + - a.mMatrix[VW][VW] * b.mV[VW]; - return vec; -} -*/ - - LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b) { // Operate "to the left" on row-vector a diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index 6007b96bd9..40599a0886 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -226,10 +226,7 @@ public: // Operators // -// Not implemented to enforce code that agrees with symbolic syntax -// friend LLVector4 operator*(const LLMatrix4 &a, const LLVector4 &b); // Apply rotation a to vector b - -// friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b + // friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b); // Return transform of vector a by matrix b friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b); // Rotates a but does not translate diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp index 63683ed496..82aad6550b 100644 --- a/indra/llmath/v3math.cpp +++ b/indra/llmath/v3math.cpp @@ -197,6 +197,28 @@ const LLVector3& LLVector3::rotVec(const LLQuaternion &q) return *this; } +const LLVector3& LLVector3::transVec(const LLMatrix4& mat) +{ + setVec( + mV[VX] * mat.mMatrix[VX][VX] + + mV[VY] * mat.mMatrix[VX][VY] + + mV[VZ] * mat.mMatrix[VX][VZ] + + mat.mMatrix[VX][VW], + + mV[VX] * mat.mMatrix[VY][VX] + + mV[VY] * mat.mMatrix[VY][VY] + + mV[VZ] * mat.mMatrix[VY][VZ] + + mat.mMatrix[VY][VW], + + mV[VX] * mat.mMatrix[VZ][VX] + + mV[VY] * mat.mMatrix[VZ][VY] + + mV[VZ] * mat.mMatrix[VZ][VZ] + + mat.mMatrix[VZ][VW]); + + return *this; +} + + const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec) { if ( !vec.isExactlyZero() && angle ) diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 73738cffd2..76dd938887 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -36,10 +36,12 @@ #include "llerror.h" #include "llmath.h" + #include "llsd.h" class LLVector2; class LLVector4; class LLMatrix3; +class LLMatrix4; class LLVector3d; class LLQuaternion; @@ -115,6 +117,7 @@ class LLVector3 const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q + const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v) const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 116e265914..415d2f603b 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -668,6 +668,12 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) { LLMemType mt2(LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER); + if (nverts < 0 || nindices < 0 || + nverts > 65536) + { + llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl; + } + updateNumVerts(nverts); updateNumIndices(nindices); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index bb90aeb91a..cb30147925 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1687,7 +1687,7 @@ DebugShowRenderInfo Comment - Show depth buffer contents + Show stats about current scene Persist 1 Type @@ -1695,6 +1695,17 @@ Value 0 + DebugShowUploadCost + + Comment + Show what it would cost to upload assets in current scene + Persist + 1 + Type + Boolean + Value + 0 + DebugShowRenderMatrices Comment diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index b25d622d17..9404d7ce6b 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -445,8 +445,7 @@ void init_menus() gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", upload_cost); gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", upload_cost); gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", upload_cost); - gMenuHolder->childSetLabelArg("Upload Model", "[COST]", upload_cost); - + gAFKMenu = gMenuBarView->getChild("Set Away", TRUE); gBusyMenu = gMenuBarView->getChild("Set Busy", TRUE); gAttachSubMenu = gMenuBarView->findChildMenuByName("Attach Object", TRUE); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 0f26975149..53688f1210 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -92,6 +92,15 @@ class LLFileEnableUpload : public view_listener_t } }; +class LLFileEnableUploadModel : public view_listener_t +{ + bool handleEvent(const LLSD& userdata) + { + bool new_value = gAgent.getRegion() && !gAgent.getRegion()->getCapability("NewFileAgentInventoryVariablePrice").empty(); + return new_value; + } +}; + //============================================================================ #if LL_WINDOWS @@ -1283,6 +1292,7 @@ void init_menu_file() view_listener_t::addCommit(new LLFileQuit(), "File.Quit"); view_listener_t::addEnable(new LLFileEnableUpload(), "File.EnableUpload"); + view_listener_t::addEnable(new LLFileEnableUploadModel(), "File.EnableUploadModel"); // "File.SaveTexture" moved to llpanelmaininventory so that it can be properly handled. } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 6a9e6f090f..a8702b2c6b 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4842,7 +4842,6 @@ void process_economy_data(LLMessageSystem *msg, void** /*user_data*/) gMenuHolder->childSetLabelArg("Upload Image", "[COST]", llformat("%d", upload_cost)); gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", llformat("%d", upload_cost)); - gMenuHolder->childSetLabelArg("Upload Model", "[COST]", llformat("%d", upload_cost)); gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", llformat("%d", upload_cost)); gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", llformat("%d", upload_cost)); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index f554acf1df..5b21e13bf1 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -584,6 +584,20 @@ public: } } + + if (gSavedSettings.getBOOL("DebugShowUploadCost")) + { + addText(xpos, ypos, llformat(" Meshes: L$%d", gPipeline.mDebugMeshUploadCost)); + ypos += y_inc/2.f; + addText(xpos, ypos, llformat(" Sculpties: L$%d", gPipeline.mDebugSculptUploadCost)); + ypos += y_inc/2.f; + addText(xpos, ypos, llformat(" Textures: L$%d", gPipeline.mDebugTextureUploadCost)); + ypos += y_inc/2.f; + addText(xpos, ypos, "Upload Cost: "); + + ypos += y_inc; + } + //temporary hack to give feedback on mesh upload progress if (!gMeshRepo.mUploads.empty()) { diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 559ae83182..43b2104135 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -3553,6 +3553,63 @@ void LLPipeline::renderDebug() } } + if (gSavedSettings.getBOOL("DebugShowUploadCost")) + { + std::set textures; + std::set sculpts; + std::set meshes; + + BOOL selected = TRUE; + if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) + { + selected = FALSE; + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + LLSpatialGroup::OctreeNode* node = group->mOctreeNode; + for (LLSpatialGroup::OctreeNode::element_iter elem = node->getData().begin(); elem != node->getData().end(); ++elem) + { + LLDrawable* drawable = *elem; + LLVOVolume* volume = drawable->getVOVolume(); + if (volume && volume->isSelected() == selected) + { + for (U32 i = 0; i < volume->getNumTEs(); ++i) + { + LLTextureEntry* te = volume->getTE(i); + textures.insert(te->getID()); + } + + if (volume->isSculpted()) + { + LLUUID sculpt_id = volume->getVolume()->getParams().getSculptID(); + if (volume->isMesh()) + { + meshes.insert(sculpt_id); + } + else + { + sculpts.insert(sculpt_id); + } + } + } + } + } + + gPipeline.mDebugTextureUploadCost = textures.size() * 10; + gPipeline.mDebugSculptUploadCost = sculpts.size()*10; + + U32 mesh_cost = 0; + + for (std::set::iterator iter = meshes.begin(); iter != meshes.end(); ++iter) + { + mesh_cost += gMeshRepo.getResourceCost(*iter)*10; + } + + gPipeline.mDebugMeshUploadCost = mesh_cost; + } + for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 33c18c1b86..814c54326a 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -435,6 +435,10 @@ public: S32 mNumVisibleNodes; S32 mVerticesRelit; + S32 mDebugTextureUploadCost; + S32 mDebugSculptUploadCost; + S32 mDebugMeshUploadCost; + S32 mLightingChanges; S32 mGeometryChanges; diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml index 0d974075f5..05a4e60de7 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -43,14 +43,14 @@ function="File.EnableUpload" /> + function="File.EnableUploadModel" /> + + + + + function="File.EnableUploadModel" /> Date: Tue, 9 Mar 2010 14:28:06 -0600 Subject: Tool tips for model preview. Rename "Impostor" to "Lowest" --- indra/llmath/llvolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 904786079f..d85c56046f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1918,7 +1918,7 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) std::string nm[] = { - "impostor", + "lowest_lod", "low_lod", "medium_lod", "high_lod" -- cgit v1.3 From 4c0e2f79219913b57424bfe136b75a6a58fb8639 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 11 Mar 2010 12:02:37 -0600 Subject: "Generate Normals" is less busted now. --- indra/llmath/llvolume.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++--- indra/llmath/llvolume.h | 33 +++++++++++++++++++++++ 2 files changed, 97 insertions(+), 3 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index d85c56046f..9ea3912a88 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1882,9 +1882,15 @@ bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs bool retval = false; if (rhs.mPosition == mPosition && rhs.mTexCoord == mTexCoord) { - F32 cur_angle = rhs.mNormal*mNormal; - - retval = cur_angle > angle_cutoff; + if (angle_cutoff > 1.f) + { + retval = (mNormal == rhs.mNormal); + } + else + { + F32 cur_angle = rhs.mNormal*mNormal; + retval = cur_angle > angle_cutoff; + } } return retval; @@ -4953,6 +4959,61 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) } } +void LLVolumeFace::optimize(F32 angle_cutoff) +{ + LLVolumeFace new_face; + + VertexMapData::PointMap point_map; + + //remove redundant vertices + for (U32 i = 0; i < mIndices.size(); ++i) + { + U16 index = mIndices[i]; + + LLVolumeFace::VertexData cv = mVertices[index]; + + BOOL found = FALSE; + VertexMapData::PointMap::iterator point_iter = point_map.find(cv.mPosition); + if (point_iter != point_map.end()) + { //duplicate point might exist + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + LLVolumeFace::VertexData& tv = (point_iter->second)[j]; + if (tv.compareNormal(cv, angle_cutoff)) + { + found = TRUE; + new_face.mIndices.push_back((point_iter->second)[j].mIndex); + break; + } + } + } + + if (!found) + { + new_face.mVertices.push_back(cv); + U16 index = (U16) new_face.mVertices.size()-1; + new_face.mIndices.push_back(index); + + VertexMapData d; + d.mPosition = cv.mPosition; + d.mTexCoord = cv.mTexCoord; + d.mNormal = cv.mNormal; + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[d.mPosition].push_back(d); + } + } + } + + mVertices = new_face.mVertices; + mIndices = new_face.mIndices; +} + void LerpPlanarVertex(LLVolumeFace::VertexData& v0, LLVolumeFace::VertexData& v1, LLVolumeFace::VertexData& v2, diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 36811785dc..f1c1fdceba 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -820,6 +820,39 @@ public: bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; }; + class VertexMapData : public LLVolumeFace::VertexData + { + public: + U16 mIndex; + + bool operator==(const LLVolumeFace::VertexData& rhs) const + { + return mPosition == rhs.mPosition && + mTexCoord == rhs.mTexCoord && + mNormal == rhs.mNormal; + } + + struct ComparePosition + { + bool operator()(const LLVector3& a, const LLVector3& b) const + { + if (a.mV[0] != b.mV[0]) + { + return a.mV[0] < b.mV[0]; + } + if (a.mV[1] != b.mV[1]) + { + return a.mV[1] < b.mV[1]; + } + return a.mV[2] < b.mV[2]; + } + }; + + typedef std::map, VertexMapData::ComparePosition > PointMap; + }; + + void optimize(F32 angle_cutoff = 2.f); + enum { SINGLE_MASK = 0x0001, -- cgit v1.3 From 71d11af31083ced30da7b67a2a63e624c93b44a3 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Sat, 13 Mar 2010 17:39:32 -0600 Subject: Mesh cache. Has a bug. --- indra/llmath/llvolume.cpp | 28 ++++++++++++++-------------- indra/llmath/llvolume.h | 2 +- indra/llvfs/llvfile.cpp | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 9ea3912a88..52a3fb2195 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1962,7 +1962,7 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is) return unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger()); } -BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) +bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) { U8* result = NULL; U32 cur_size = 0; @@ -2002,7 +2002,7 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) inflateEnd(&strm); free(result); delete [] in; - return FALSE; + return false; } switch (ret) @@ -2014,7 +2014,7 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) inflateEnd(&strm); free(result); delete [] in; - return FALSE; + return false; break; } @@ -2032,7 +2032,7 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) if (ret != Z_STREAM_END) { free(result); - return FALSE; + return false; } } @@ -2047,7 +2047,7 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) if (!LLSDSerialize::deserialize(mdl, istr, cur_size)) { llwarns << "not a valid mesh asset!" << llendl; - return FALSE; + return false; } } @@ -2074,7 +2074,7 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) LLVolumeFace& face = mVolumeFaces[i]; - face.mHasBinormals = FALSE; + face.mHasBinormals = false; //copy out indices face.mIndices.resize(idx.size()/2); @@ -2146,24 +2146,24 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) // modifier flags? - BOOL do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); - BOOL do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); + bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); + bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); // translate to actions: - BOOL do_reflect_x = FALSE; - BOOL do_reverse_triangles = FALSE; - BOOL do_invert_normals = FALSE; + bool do_reflect_x = false; + bool do_reverse_triangles = false; + bool do_invert_normals = false; if (do_mirror) { - do_reflect_x = TRUE; + do_reflect_x = true; do_reverse_triangles = !do_reverse_triangles; } if (do_invert) { - do_invert_normals = TRUE; + do_invert_normals = true; do_reverse_triangles = !do_reverse_triangles; } @@ -2201,7 +2201,7 @@ BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) } mSculptLevel = 0; // success! - return TRUE; + return true; } void tetrahedron_set_normal(LLVolumeFace::VertexData* cv) diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index f1c1fdceba..60c1569e55 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1009,7 +1009,7 @@ protected: public: virtual BOOL createVolumeFacesFromFile(const std::string& file_name); virtual BOOL createVolumeFacesFromStream(std::istream& is); - virtual BOOL unpackVolumeFaces(std::istream& is, S32 size); + virtual bool unpackVolumeFaces(std::istream& is, S32 size); virtual void makeTetrahedron(); virtual BOOL isTetrahedron(); diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index e0e282d7af..6751f3eb93 100644 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -320,7 +320,7 @@ BOOL LLVFile::setMaxSize(S32 size) if (!mVFS->checkAvailable(size)) { - LLFastTimer t(FTM_VFILE_WAIT); + //LLFastTimer t(FTM_VFILE_WAIT); S32 count = 0; while (sVFSThread->getPending() > 1000) { -- cgit v1.3 From 807d835c2bfc5d794a74f9690d1fafbe55ff88cc Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 2 Apr 2010 14:43:05 -0500 Subject: First draft of skin weights in .mesh asset --- indra/llcommon/llsdserialize.cpp | 137 +++++++++++++++++++++++++++++++++++++++ indra/llcommon/llsdserialize.h | 4 ++ indra/llmath/llvolume.cpp | 135 +++++++++++++------------------------- indra/llmath/llvolume.h | 6 ++ 4 files changed, 192 insertions(+), 90 deletions(-) (limited to 'indra/llmath') 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 #include "apr_base64.h" +#include "zlib/zlib.h" // for davep's dirty little zip functions #if !LL_WINDOWS #include // 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 mTriStrip; std::vector mEdge; + //list of skin weights for rigged volumes + // format is mWeights[vertex_index].mV[influence] = . + // mWeights.size() should be empty or match mVertices.size() + std::vector mWeights; + private: BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE); BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE); -- cgit v1.3 From 47ffcdb93d6e2ac1f9d497e43e0213c98d129254 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 6 Apr 2010 16:24:08 -0500 Subject: Rigged attachments (almost works). --- indra/llmath/llvolume.cpp | 22 +++++--- indra/llrender/llglslshader.cpp | 14 ++++- indra/llrender/llglslshader.h | 3 +- indra/llrender/llshadermgr.cpp | 8 +++ indra/newview/lldrawpoolavatar.cpp | 26 ++++++++- indra/newview/lldrawpoolavatar.h | 2 + indra/newview/llface.cpp | 18 +++++- indra/newview/llface.h | 4 +- indra/newview/llspatialpartition.h | 7 +++ indra/newview/llviewershadermgr.cpp | 25 +++++++++ indra/newview/llviewershadermgr.h | 3 + indra/newview/llvoavatar.cpp | 109 ++++++++++++++++++++++++++++++++++++ indra/newview/llvoavatar.h | 1 + indra/newview/llvovolume.cpp | 20 +++++++ 14 files changed, 247 insertions(+), 15 deletions(-) (limited to 'indra/llmath') diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index c563af592f..fdd48b9e9e 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2013,22 +2013,23 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) if (mdl[i].has("Weights")) { face.mWeights.resize(num_verts); + LLSD::Binary weights = mdl[i]["Weights"]; - LLSD::Binary::iterator iter = weights.begin(); + U32 idx = 0; U32 cur_vertex = 0; - while (iter != weights.end()) + while (idx < weights.size() && cur_vertex < num_verts) { - const S32 END_INFLUENCES = 0xFF; - U8 joint = *(iter++); + const U8 END_INFLUENCES = 0xFF; + U8 joint = weights[idx++]; U32 cur_influence = 0; while (joint != END_INFLUENCES) { - U16 influence = *(iter++); + U16 influence = weights[idx++]; influence = influence << 8; - influence |= *(iter++); + influence |= weights[idx++]; F32 w = llmin((F32) influence / 65535.f, 0.99999f); face.mWeights[cur_vertex].mV[cur_influence++] = (F32) joint + w; @@ -2039,13 +2040,18 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) } else { - joint = *(iter++); + joint = weights[idx++]; } } cur_vertex++; - iter++; } + + if (cur_vertex != num_verts || idx != weights.size()) + { + llwarns << "Vertex weight count does not match vertex count!" << llendl; + } + } LLVector3 min_pos; 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/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 colors; LLStrider binormals; LLStrider indicesp; + LLStrider 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 c400e8510e..535440692f 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" @@ -3644,6 +3646,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; -- cgit v1.3