Flipped the MESH_ENABLED switch. Added missing components and updated stuff to be closer to mesh-development head.

This commit is contained in:
Shyotl
2011-07-30 20:30:07 -05:00
parent c081efa460
commit b258b71e07
51 changed files with 3264 additions and 1451 deletions

View File

@@ -297,6 +297,7 @@ endif (STANDALONE)
if(1 EQUAL 1)
add_definitions(-DOPENSIM_RULES=1)
add_definitions(-DMESH_ENABLED=1)
endif(1 EQUAL 1)
if(SERVER)

View File

@@ -56,6 +56,9 @@ LLJoint::LLJoint()
mUpdateXform = TRUE;
mJointNum = -1;
touch();
#if MESH_ENABLED
mResetAfterRestoreOldXform = false;
#endif //MESH_ENABLED
}
@@ -239,6 +242,43 @@ void LLJoint::setPosition( const LLVector3& pos )
}
}
#if MESH_ENABLED
//--------------------------------------------------------------------
// setPosition()
//--------------------------------------------------------------------
void LLJoint::setDefaultFromCurrentXform( void )
{
mDefaultXform = mXform;
touch(MATRIX_DIRTY | POSITION_DIRTY);
}
//--------------------------------------------------------------------
// storeCurrentXform()
//--------------------------------------------------------------------
void LLJoint::storeCurrentXform( const LLVector3& pos )
{
mOldXform = mXform;
mResetAfterRestoreOldXform = true;
setPosition( pos );
}
//--------------------------------------------------------------------
// restoreOldXform()
//--------------------------------------------------------------------
void LLJoint::restoreOldXform( void )
{
mResetAfterRestoreOldXform = false;
mXform = mOldXform;
}
//--------------------------------------------------------------------
// restoreOldXform()
//--------------------------------------------------------------------
void LLJoint::restoreToDefaultXform( void )
{
mXform = mDefaultXform;
setPosition( mXform.getPosition() );
}
#endif //MESH_ENABLED
//--------------------------------------------------------------------
// getWorldPosition()

View File

@@ -86,10 +86,19 @@ protected:
// explicit transformation members
LLXformMatrix mXform;
#if MESH_ENABLED
LLXformMatrix mOldXform;
LLXformMatrix mDefaultXform;
LLUUID mId;
#endif //MESH_ENABLED
public:
U32 mDirtyFlags;
BOOL mUpdateXform;
#if MESH_ENABLED
BOOL mResetAfterRestoreOldXform;
#endif //MESH_ENABLED
// describes the skin binding pose
LLVector3 mSkinOffset;
@@ -179,6 +188,24 @@ public:
S32 getJointNum() const { return mJointNum; }
void setJointNum(S32 joint_num) { mJointNum = joint_num; }
#if MESH_ENABLED
void restoreOldXform( void );
void restoreToDefaultXform( void );
void setDefaultFromCurrentXform( void );
void storeCurrentXform( const LLVector3& pos );
//Accessor for the joint id
LLUUID getId( void ) { return mId; }
//Setter for the joints id
void setId( const LLUUID& id ) { mId = id;}
//If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it
const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
//Setter for joint reset flag
void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; }
#endif //MESH_ENABLED
// <edit>
std::string exportString(U32 tabs = 0);
// </edit>

View File

@@ -105,6 +105,9 @@ LLAssetDictionary::LLAssetDictionary()
//addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("FOLDER_LINK", "current", "current outfit", false, false, false));
//addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", false, false, false));
//addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", false, false, false));
#if MESH_ENABLED
addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false));
#endif //MESH_ENABLED
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false));
};

View File

@@ -138,13 +138,19 @@ public:
// Inventory folder link
AT_LINK_FOLDER = 25,
//AT_CURRENT_OUTFIT = 46,
//AT_OUTFIT = 47,
//AT_MY_OUTFITS = 48,
#if MESH_ENABLED
AT_MESH = 49,
// Mesh data in our proprietary SLM format
AT_COUNT = 50,
#endif //MESH_ENABLED
// +*********************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
// +*********************************************+
@@ -155,8 +161,9 @@ public:
// +*********************************************+
//AT_COUNT = 49,
#if !MESH_ENABLED
AT_COUNT = 26,
#endif //!MESH_ENABLED
AT_NONE = -1
};

View File

@@ -72,7 +72,12 @@ public:
FTM_UPDATE_GRASS,
FTM_UPDATE_TREE,
FTM_UPDATE_AVATAR,
#if MESH_ENABLED
FTM_UPDATE_RIGGED_VOLUME,
FTM_SKIN_RIGGED,
FTM_RIGGED_OCTREE,
#endif //MESH_ENABLED
// common render components
FTM_SHADOW_GEOMETRY,
FTM_SHADOW_RENDER,
@@ -131,6 +136,12 @@ public:
FTM_STATESORT,
FTM_STATESORT_DRAWABLE,
FTM_STATESORT_POSTSORT,
#if MESH_ENABLED
FTM_MESH_UPDATE,
FTM_MESH_LOCK1,
FTM_MESH_LOCK2,
FTM_LOAD_MESH_LOD,
#endif //MESH_ENABLED
FTM_REBUILD_VBO,
FTM_REBUILD_VOLUME_VB,
FTM_REBUILD_BRIDGE_VB,

View File

@@ -41,7 +41,8 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
LLThread(name),
mThreaded(threaded),
mIdleThread(TRUE),
mNextHandle(0)
mNextHandle(0),
mStarted(FALSE)
{
if (mThreaded)
{
@@ -52,6 +53,10 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) :
// MAIN THREAD
LLQueuedThread::~LLQueuedThread()
{
if (!mThreaded)
{
endThread();
}
shutdown();
// ~LLThread() will be called here
}
@@ -90,6 +95,7 @@ void LLQueuedThread::shutdown()
if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS)
{
++active_count;
req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest
}
req->deleteRequest();
}
@@ -105,6 +111,14 @@ void LLQueuedThread::shutdown()
// virtual
S32 LLQueuedThread::update(U32 max_time_ms)
{
if (!mStarted)
{
if (!mThreaded)
{
startThread();
mStarted = TRUE;
}
}
return updateQueue(max_time_ms);
}
@@ -118,8 +132,11 @@ S32 LLQueuedThread::updateQueue(U32 max_time_ms)
if (mThreaded)
{
pending = getPending();
if(pending > 0)
{
unpause();
}
}
else
{
while (pending > 0)
@@ -349,9 +366,9 @@ bool LLQueuedThread::completeRequest(handle_t handle)
#if _DEBUG
// llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
#endif
//re insert to the queue to schedule for a delete later
req->setStatus(STATUS_DELETE);
mRequestQueue.insert(req);
mRequestHash.erase(handle);
req->deleteRequest();
// check();
res = true;
}
unlockData();
@@ -395,19 +412,11 @@ S32 LLQueuedThread::processNextRequest()
}
req = *mRequestQueue.begin();
mRequestQueue.erase(mRequestQueue.begin());
if(req->getStatus() == STATUS_DELETE)
{
mRequestHash.erase(req);
req->deleteRequest();
continue;
}
if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
{
req->setStatus(STATUS_ABORTED);
req->finishRequest(false);
if ((req->getFlags() & FLAG_AUTO_COMPLETE))
if (req->getFlags() & FLAG_AUTO_COMPLETE)
{
mRequestHash.erase(req);
req->deleteRequest();
@@ -418,9 +427,11 @@ S32 LLQueuedThread::processNextRequest()
llassert_always(req->getStatus() == STATUS_QUEUED);
break;
}
U32 start_priority = 0 ;
if (req)
{
req->setStatus(STATUS_INPROGRESS);
start_priority = req->getPriority();
}
unlockData();
@@ -436,13 +447,12 @@ S32 LLQueuedThread::processNextRequest()
{
lockData();
req->setStatus(STATUS_COMPLETE);
req->finishRequest(true);
if ((req->getFlags() & FLAG_AUTO_COMPLETE))
if (req->getFlags() & FLAG_AUTO_COMPLETE)
{
mRequestHash.erase(req);
req->deleteRequest();
// check();
}
unlockData();
}
@@ -451,9 +461,8 @@ S32 LLQueuedThread::processNextRequest()
lockData();
req->setStatus(STATUS_QUEUED);
mRequestQueue.insert(req);
U32 priority = req->getPriority();
unlockData();
if (priority < PRIORITY_NORMAL)
if (mThreaded && start_priority < PRIORITY_NORMAL)
{
ms_sleep(1); // sleep the thread a little
}
@@ -481,6 +490,7 @@ void LLQueuedThread::run()
// call checPause() immediately so we don't try to do anything before the class is fully constructed
checkPause();
startThread();
mStarted = TRUE;
while (1)
{

View File

@@ -184,7 +184,7 @@ public:
void waitOnPending();
void printQueueStats();
S32 getPending();
virtual S32 getPending();
bool getThreaded() { return mThreaded ? true : false; }
// Request accessors
@@ -202,6 +202,7 @@ public:
protected:
BOOL mThreaded; // if false, run on main thread and do updates during update()
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;

View File

@@ -39,6 +39,13 @@
#include <iostream>
#include "apr_base64.h"
#if MESH_ENABLED
#ifdef LL_STANDALONE
# include <zlib.h>
#else
# include "zlib/zlib.h" // for davep's dirty little zip functions
#endif
#endif //MESH_ENABLED
#if !LL_WINDOWS
#include <netinet/in.h> // htonl & ntohl
@@ -1990,3 +1997,181 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
return s;
}
#if MESH_ENABLED
//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::toBinary(data, llsd_strm);
const U32 CHUNK = 65536;
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();
U8 out[CHUNK];
strm.avail_in = source.size();
strm.next_in = (U8*) source.data();
U8* output = NULL;
U32 cur_size = 0;
U32 have = 0;
do
{
strm.avail_out = CHUNK;
strm.next_out = out;
ret = deflate(&strm, Z_FINISH);
if (ret == Z_OK || ret == Z_STREAM_END)
{ //copy result into output
if (strm.avail_out >= CHUNK)
{
free(output);
llwarns << "Failed to compress LLSD block." << llendl;
return std::string();
}
have = CHUNK-strm.avail_out;
output = (U8*) realloc(output, cur_size+have);
memcpy(output+cur_size, out, have);
cur_size += have;
}
else
{
free(output);
llwarns << "Failed to compress LLSD block." << llendl;
return std::string();
}
}
while (ret == Z_OK);
std::string::size_type size = cur_size;
std::string result((char*) output, size);
deflateEnd(&strm);
free(output);
#if 0 //verify results work with unzip_llsd
std::istringstream test(result);
LLSD test_sd;
if (!unzip_llsd(test_sd, test, result.size()))
{
llerrs << "Invalid compression result!" << llendl;
}
#endif
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);
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 (ret == Z_OK);
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::string deprecated_header("<? LLSD/Binary ?>");
if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
{
res_str = res_str.substr(deprecated_header.size()+1, cur_size);
}
cur_size = res_str.size();
std::istringstream istr(res_str);
if (!LLSDSerialize::fromBinary(data, istr, cur_size))
{
llwarns << "Failed to unzip LLSD block" << llendl;
free(result);
return false;
}
}
free(result);
return true;
}
#endif //MESH_ENABLED

View File

@@ -787,4 +787,9 @@ public:
}
};
#if MESH_ENABLED
//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 //MESH_ENABLED
#endif // LL_LLSDSERIALIZE_H

View File

@@ -2138,6 +2138,13 @@ LLVolume::~LLVolume()
mPathp = NULL;
mProfilep = NULL;
mVolumeFaces.clear();
#if MESH_ENABLED
ll_aligned_free_16(mHullPoints);
mHullPoints = NULL;
ll_aligned_free_16(mHullIndices);
mHullIndices = NULL;
#endif //MESH_ENABLED
}
BOOL LLVolume::generate()
@@ -2378,11 +2385,16 @@ bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)co
bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const
{
bool retval = false;
if (rhs.mData[POSITION].equals3(mData[POSITION]) && rhs.mTexCoord == mTexCoord)
const F32 epsilon = 0.00001f;
if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) &&
fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon &&
fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon)
{
if (angle_cutoff > 1.f)
{
retval = (mData[NORMAL].equals3(rhs.mData[NORMAL]));
retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon));
}
else
{
@@ -2499,9 +2511,9 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
}
{
U16* n = (U16*) &(norm[0]);
if(n)
if (!norm.empty())
{
U16* n = (U16*) &(norm[0]);
for (U32 j = 0; j < num_verts; ++j)
{
norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]);
@@ -2512,12 +2524,16 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
n += 3;
}
}
else
{
memset(norm_out, 0, sizeof(LLVector4a)*num_verts);
}
}
{
U16* t = (U16*) &(tc[0]);
if(t)
if (!tc.empty())
{
U16* t = (U16*) &(tc[0]);
for (U32 j = 0; j < num_verts; j+=2)
{
if (j < num_verts-1)
@@ -2538,6 +2554,10 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
tc_out++;
}
}
else
{
memset(tc_out, 0, sizeof(LLVector2)*num_verts);
}
}
if (mdl[i].has("Weights"))
@@ -2635,7 +2655,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
if (do_reverse_triangles)
{
for (U32 j = 0; j < face.mNumIndices; j += 3)
for (U32 j = 0; j < (U32)face.mNumIndices; j += 3)
{
// swap the 2nd and 3rd index
S32 swap = face.mIndices[j+1];
@@ -2662,6 +2682,25 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
min.setMin(min, face.mPositions[i]);
max.setMax(max, face.mPositions[i]);
}
if (face.mTexCoords)
{
LLVector2& min_tc = face.mTexCoordExtents[0];
LLVector2& max_tc = face.mTexCoordExtents[1];
min_tc = face.mTexCoords[0];
max_tc = face.mTexCoords[0];
for (U32 j = 1; j < (U32)face.mNumVertices; ++j)
{
update_min_max(min_tc, max_tc, face.mTexCoords[j]);
}
}
else
{
face.mTexCoordExtents[0].set(0,0);
face.mTexCoordExtents[1].set(1,1);
}
}
}
}
@@ -2741,11 +2780,13 @@ void LLVolume::makeTetrahedron()
n[2] = cv[2].getNormal();
n += 3;
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
if(tc)
{
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
}
//side 2
cv[0].setPosition(p[3]);
@@ -2764,11 +2805,14 @@ void LLVolume::makeTetrahedron()
n[2] = cv[2].getNormal();
n += 3;
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
if(tc)
{
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
}
//side 3
cv[0].setPosition(p[3]);
cv[1].setPosition(p[1]);
@@ -2786,10 +2830,13 @@ void LLVolume::makeTetrahedron()
n[2] = cv[2].getNormal();
n += 3;
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
if(tc)
{
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
}
//side 4
cv[0].setPosition(p[2]);
@@ -2808,10 +2855,13 @@ void LLVolume::makeTetrahedron()
n[2] = cv[2].getNormal();
n += 3;
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
if(tc)
{
tc[0] = cv[0].mTexCoord;
tc[1] = cv[1].mTexCoord;
tc[2] = cv[2].mTexCoord;
tc += 3;
}
//set index buffer
for (U16 i = 0; i < 12; i++)
@@ -2833,7 +2883,7 @@ void LLVolume::copyVolumeFaces(const LLVolume* volume)
void LLVolume::cacheOptimize()
{
for (S32 i = 0; i < mVolumeFaces.size(); ++i)
for (S32 i = 0; i < (S32)mVolumeFaces.size(); ++i)
{
mVolumeFaces[i].cacheOptimize();
}
@@ -5523,6 +5573,9 @@ LLVolumeFace::LLVolumeFace() :
mBinormals(NULL),
mTexCoords(NULL),
mIndices(NULL),
#if MESH_ENABLED
mWeights(NULL),
#endif //MESH_ENABLED
mOctree(NULL)
{
mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
@@ -5590,7 +5643,16 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
if(src.mTexCoords)
{
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
}
else
{
ll_aligned_free_16(mTexCoords) ;
mTexCoords = NULL ;
}
if (src.mBinormals)
@@ -5715,8 +5777,23 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)
void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv)
{
cv.setPosition(mPositions[index]);
cv.setNormal(mNormals[index]);
cv.mTexCoord = mTexCoords[index];
if (mNormals)
{
cv.setNormal(mNormals[index]);
}
else
{
cv.getNormal().clear();
}
if (mTexCoords)
{
cv.mTexCoord = mTexCoords[index];
}
else
{
cv.mTexCoord.clear();
}
}
bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const
@@ -5746,7 +5823,10 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
LLVolumeFace new_face;
//map of points to vector of vertices at that point
VertexMapData::PointMap point_map;
std::map<U64, std::vector<VertexMapData> > point_map;
LLVector4a range;
range.setSub(mExtents[1],mExtents[0]);
//remove redundant vertices
for (U32 i = 0; i < (U32)mNumIndices; ++i)
@@ -5757,7 +5837,19 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
getVertexData(index, cv);
BOOL found = FALSE;
VertexMapData::PointMap::iterator point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr()));
LLVector4a pos;
pos.setSub(mPositions[index], mExtents[0]);
pos.div(range);
U64 pos64 = 0;
pos64 = (U16) (pos[0]*65535);
pos64 = pos64 | (((U64) (pos[1]*65535)) << 16);
pos64 = pos64 | (((U64) (pos[2]*65535)) << 32);
std::map<U64, std::vector<VertexMapData> >::iterator point_iter = point_map.find(pos64);
if (point_iter != point_map.end())
{ //duplicate point might exist
for (U32 j = 0; j < point_iter->second.size(); ++j)
@@ -5789,11 +5881,26 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
}
else
{
point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d);
point_map[pos64].push_back(d);
}
}
}
llassert(new_face.mNumIndices == mNumIndices);
llassert(new_face.mNumVertices <= mNumVertices);
if (angle_cutoff > 1.f && !mNormals)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!mTexCoords)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
swapData(new_face);
}
@@ -7026,6 +7133,7 @@ void LLVolumeFace::allocateBinormals(S32 num_verts)
#if MESH_ENABLED
void LLVolumeFace::allocateWeights(S32 num_verts)
{
ll_aligned_free_16(mWeights);
mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
}

View File

@@ -958,7 +958,12 @@ class LLVolume : public LLRefCount
{
friend class LLVolumeLODGroup;
#if MESH_ENABLED
protected:
#endif //MESH_ENABLED
#if !MESH_ENABLED
private:
#endif //!MESH_ENABLED
LLVolume(const LLVolume&); // Don't implement
~LLVolume(); // use unref

View File

@@ -154,7 +154,7 @@ void LLVolumeMgr::unrefVolume(LLVolume *volumep)
volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params);
if( iter == mVolumeLODGroups.end() )
{
llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
llwarns << "Warning! Tried to cleanup unknown volume type! " << *params << llendl;
if (mDataMutex)
{
mDataMutex->unlock();

View File

@@ -17,7 +17,7 @@ include_directories(
set(llprimitive_SOURCE_FILES
llmaterialtable.cpp
#llmodel.cpp
llmodel.cpp
llprimitive.cpp
llprimtexturelist.cpp
lltextureanim.cpp
@@ -33,7 +33,7 @@ set(llprimitive_HEADER_FILES
legacy_object_types.h
llmaterialtable.h
#llmodel.h
llmodel.h
llprimitive.h
llprimtexturelist.h
lltextureanim.h

View File

@@ -26,15 +26,20 @@
#include "linden_common.h"
#if MESH_ENABLED
#include "llmodel.h"
#if MESH_IMPORT
#include "llconvexdecomposition.h"
#endif //MESH_IMPORT
#include "llsdserialize.h"
#include "llvector4a.h"
#if MESH_IMPORT
#include "dae.h"
#include "dae/daeErrorHandler.h"
#include "dom/domConstants.h"
#include "dom/domMesh.h"
#endif //MESH_IMPORT
#ifdef LL_STANDALONE
# include <zlib.h>
@@ -67,87 +72,13 @@ LLModel::~LLModel()
{
if (mDecompID >= 0)
{
#if MESH_IMPORT
LLConvexDecomposition::getInstance()->deleteDecomposition(mDecompID);
#endif //MESH_IMPORT
}
}
void load_face_from_dom_inputs(LLVolumeFace& face, const domInputLocalOffset_Array& inputs, U32 min_idx, U32 max_idx)
{
for (U32 j = 0; j < inputs.getCount(); ++j)
{
if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0)
{ //found vertex array
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domVertices* vertices = (domVertices*) elem.cast();
domInputLocal_Array& v_inp = vertices->getInput_array();
if (inputs[j]->getOffset() != 0)
{
llerrs << "Vertex array offset MUST be zero." << llendl;
}
for (U32 k = 0; k < v_inp.getCount(); ++k)
{
if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0)
{
const domURIFragmentType& uri = v_inp[k]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
if (src->getTechnique_common()->getAccessor()->getStride() != 3)
{
llerrs << "Vertex array stride MUST be three." << llendl;
}
domListOfFloats& v = src->getFloat_array()->getValue();
LLVector4a min;
min.set(v[min_idx], v[min_idx+1], v[min_idx+2]);
LLVector4a max = min;
for (U32 j = min_idx; j <= max_idx; ++j)
{ //copy vertex array
face.mPositions[j-min_idx].set(v[j*3+0], v[j*3+1], v[j*3+2]);
update_min_max(min, max, face.mPositions[j-min_idx]);
}
face.mExtents[0] = min;
face.mExtents[1] = max;
}
}
}
if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0)
{
//found normal array for this triangle list
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
domListOfFloats& n = src->getFloat_array()->getValue();
for (U32 j = min_idx; j <= max_idx; ++j)
{
LLVector4a* norm = (LLVector4a*) face.mNormals + (j-min_idx);
norm->set(n[j*3+0], n[j*3+1], n[j*3+2]);
norm->normalize3();
}
}
else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0)
{ //found texCoords
const domURIFragmentType& uri = inputs[j]->getSource();
daeElementRef elem = uri.getElement();
domSource* src = (domSource*) elem.cast();
domListOfFloats& u = src->getFloat_array()->getValue();
for (U32 j = min_idx; j <= max_idx; ++j)
{
face.mTexCoords[j-min_idx].setVec(u[j*2+0], u[j*2+1]);
}
}
}
}
#if MESH_IMPORT
bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride,
domSource* &pos_source, domSource* &tc_source, domSource* &norm_source)
@@ -329,6 +260,19 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
{
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
face = LLVolumeFace();
point_map.clear();
}
@@ -348,6 +292,18 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
return LLModel::NO_ERRORS ;
@@ -524,6 +480,19 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
{
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
face = LLVolumeFace();
verts.clear();
indices.clear();
@@ -544,6 +513,19 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac
materials.push_back(material);
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!norm_source)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!tc_source)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
return LLModel::NO_ERRORS ;
@@ -733,6 +715,19 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac
materials.push_back(material);
face_list.push_back(face);
face_list.rbegin()->fillFromLegacyData(new_verts, indices);
LLVolumeFace& new_face = *face_list.rbegin();
if (!n)
{
ll_aligned_free_16(new_face.mNormals);
new_face.mNormals = NULL;
}
if (!t)
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
}
return LLModel::NO_ERRORS ;
@@ -817,9 +812,9 @@ BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
if (getNumVolumeFaces() > 0)
{
optimizeVolumeFaces();
normalizeVolumeFaces();
optimizeVolumeFaces();
if (getNumVolumeFaces() > 0)
{
return TRUE;
@@ -833,6 +828,7 @@ BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh)
return FALSE;
}
#endif //MESH_IMPORT
void LLModel::offsetMesh( const LLVector3& pivotPoint )
{
@@ -844,7 +840,7 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint )
LLVolumeFace& face = *currentFaceIt;
LLVector4a *pos = (LLVector4a*) face.mPositions;
for (U32 i=0; i<face.mNumVertices; ++i )
for (U32 i=0; i< (U32)face.mNumVertices; ++i )
{
pos[i].add( pivot );
}
@@ -853,81 +849,10 @@ void LLModel::offsetMesh( const LLVector3& pivotPoint )
void LLModel::optimizeVolumeFaces()
{
#if 0 //VECTORIZE ?
for (std::vector<LLVolumeFace>::iterator iter = mVolumeFaces.begin(); iter != mVolumeFaces.end(); )
for (U32 i = 0; i < (U32)getNumVolumeFaces(); ++i)
{
std::vector<LLVolumeFace>::iterator cur_iter = iter++;
LLVolumeFace& face = *cur_iter;
for (S32 i = 0; i < (S32) face.mNumIndices; i += 3)
{ //remove zero area triangles
U16 i0 = face.mIndices[i+0];
U16 i1 = face.mIndices[i+1];
U16 i2 = face.mIndices[i+2];
if (i0 == i1 ||
i1 == i2 ||
i0 == i2)
{ //duplicate index in triangle, remove triangle
face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3);
i -= 3;
}
else
{
LLVolumeFace::VertexData& v0 = face.mVertices[i0];
LLVolumeFace::VertexData& v1 = face.mVertices[i1];
LLVolumeFace::VertexData& v2 = face.mVertices[i2];
if (v0.mPosition == v1.mPosition ||
v1.mPosition == v2.mPosition ||
v2.mPosition == v0.mPosition)
{ //zero area triangle, delete
face.mIndices.erase(face.mIndices.begin()+i, face.mIndices.begin()+i+3);
i-=3;
}
}
}
//remove unreference vertices
std::vector<bool> ref;
ref.resize(face.mNumVertices);
for (U32 i = 0; i < ref.size(); ++i)
{
ref[i] = false;
}
for (U32 i = 0; i < face.mNumIndices; ++i)
{
ref[face.mIndices[i]] = true;
}
U32 unref_count = 0;
for (U32 i = 0; i < ref.size(); ++i)
{
if (!ref[i])
{
//vertex is unreferenced
face.mVertices.erase(face.mVertices.begin()+(i-unref_count));
U16 idx = (U16) (i-unref_count);
for (U32 j = 0; j < face.mNumIndices; ++j)
{ //decrement every index array value greater than idx
if (face.mIndices[j] > idx)
{
--face.mIndices[j];
}
}
++unref_count;
}
}
if (face.mVertices.empty() || face.mIndices.empty())
{ //face is empty, remove it
iter = mVolumeFaces.erase(cur_iter);
}
mVolumeFaces[i].optimize();
}
#endif
}
// Shrink the model to fit
@@ -962,6 +887,25 @@ void LLModel::normalizeVolumeFaces()
update_min_max(min, max, face.mExtents[0]);
update_min_max(min, max, face.mExtents[1]);
if (face.mTexCoords)
{
LLVector2& min_tc = face.mTexCoordExtents[0];
LLVector2& max_tc = face.mTexCoordExtents[1];
min_tc = face.mTexCoords[0];
max_tc = face.mTexCoords[0];
for (U32 j = 1; j < (U32)face.mNumVertices; ++j)
{
update_min_max(min_tc, max_tc, face.mTexCoords[j]);
}
}
else
{
face.mTexCoordExtents[0].set(0,0);
face.mTexCoordExtents[1].set(1,1);
}
}
// Now that we have the extents of the model
@@ -1025,12 +969,15 @@ void LLModel::normalizeVolumeFaces()
LLVector4a* pos = (LLVector4a*) face.mPositions;
LLVector4a* norm = (LLVector4a*) face.mNormals;
for (U32 j = 0; j < face.mNumVertices; ++j)
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
{
pos[j].add(trans);
pos[j].mul(scale);
norm[j].mul(inv_scale);
norm[j].normalize3();
if (norm && !norm[j].equals3(LLVector4a::getZero()))
{
norm[j].mul(inv_scale);
norm[j].normalize3();
}
}
}
@@ -1073,8 +1020,26 @@ void LLModel::setVolumeFaceData(
face.resizeIndices(num_indices);
LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32));
LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
if (norm.get())
{
LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32));
}
else
{
ll_aligned_free_16(face.mNormals);
face.mNormals = NULL;
}
if (tc.get())
{
LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32));
}
else
{
ll_aligned_free_16(face.mTexCoords);
face.mTexCoords = NULL;
}
U32 size = (num_indices*2+0xF)&~0xF;
LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size);
}
@@ -1160,7 +1125,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
faceted.resizeVertices(vol_face.mNumIndices);
faceted.resizeIndices(vol_face.mNumIndices);
//bake out triangles into temporary face, clearing texture coordinates
for (U32 i = 0; i < vol_face.mNumIndices; ++i)
for (U32 i = 0; i < (U32)vol_face.mNumIndices; ++i)
{
U32 idx = vol_face.mIndices[i];
@@ -1170,7 +1135,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
}
//generate normals for temporary face
for (U32 i = 0; i < faceted.mNumIndices; i += 3)
for (U32 i = 0; i < (U32)faceted.mNumIndices; i += 3)
{ //for each triangle
U16 i0 = faceted.mIndices[i+0];
U16 i1 = faceted.mIndices[i+1];
@@ -1199,12 +1164,12 @@ void LLModel::generateNormals(F32 angle_cutoff)
//generate normals for welded face based on new topology (step 3)
for (U32 i = 0; i < faceted.mNumVertices; i++)
for (U32 i = 0; i < (U32)faceted.mNumVertices; i++)
{
faceted.mNormals[i].clear();
}
for (U32 i = 0; i < faceted.mNumIndices; i += 3)
for (U32 i = 0; i < (U32)faceted.mNumIndices; i += 3)
{ //for each triangle
U16 i0 = faceted.mIndices[i+0];
U16 i1 = faceted.mIndices[i+1];
@@ -1233,7 +1198,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
//normalize normals and build point map
LLVolumeFace::VertexMapData::PointMap point_map;
for (U32 i = 0; i < faceted.mNumVertices; ++i)
for (U32 i = 0; i < (U32)faceted.mNumVertices; ++i)
{
faceted.mNormals[i].normalize3();
@@ -1251,18 +1216,31 @@ void LLModel::generateNormals(F32 angle_cutoff)
new_face.resizeIndices(vol_face.mNumIndices);
new_face.resizeVertices(vol_face.mNumIndices);
for (U32 i = 0; i < vol_face.mNumIndices; ++i)
for (U32 i = 0; i < (U32)vol_face.mNumIndices; ++i)
{
U32 idx = vol_face.mIndices[i];
LLVolumeFace::VertexData v;
new_face.mPositions[i] = vol_face.mPositions[idx];
new_face.mNormals[i].clear();
new_face.mTexCoords[i] = vol_face.mTexCoords[idx];
new_face.mIndices[i] = i;
}
if (vol_face.mTexCoords)
{
for (U32 i = 0; i < (U32)vol_face.mNumIndices; i++)
{
U32 idx = vol_face.mIndices[i];
new_face.mTexCoords[i] = vol_face.mTexCoords[idx];
}
}
else
{
ll_aligned_free_16(new_face.mTexCoords);
new_face.mTexCoords = NULL;
}
//generate normals for new face
for (U32 i = 0; i < new_face.mNumIndices; i += 3)
for (U32 i = 0; i < (U32)new_face.mNumIndices; i += 3)
{ //for each triangle
U16 i0 = new_face.mIndices[i+0];
U16 i1 = new_face.mIndices[i+1];
@@ -1287,7 +1265,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
}
//swap out normals in new_face with best match from point map (step 5)
for (U32 i = 0; i < new_face.mNumVertices; ++i)
for (U32 i = 0; i < (U32)new_face.mNumVertices; ++i)
{
//LLVolumeFace::VertexData v = new_face.mVertices[i];
@@ -1320,6 +1298,8 @@ void LLModel::generateNormals(F32 angle_cutoff)
}
}
#if MESH_IMPORT
//static
std::string LLModel::getElementLabel(daeElement *element)
{ // try to get a decent label for this element
@@ -1375,6 +1355,7 @@ LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh)
ret->mLabel = getElementLabel(mesh);
return ret;
}
#endif MESH_IMPORT
std::string LLModel::getName() const
{
@@ -1395,7 +1376,8 @@ LLSD LLModel::writeModel(
const LLModel::Decomposition& decomp,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite)
BOOL nowrite,
BOOL as_slm)
{
LLSD mdl;
@@ -1419,12 +1401,20 @@ LLSD LLModel::writeModel(
!decomp.mHull.empty())
{
mdl["physics_convex"] = decomp.asLLSD();
if (!decomp.mHull.empty())
{ //convex decomposition exists, physics mesh will not be used
if (!decomp.mHull.empty() && !as_slm)
{ //convex decomposition exists, physics mesh will not be used (unless this is an slm file)
model[LLModel::LOD_PHYSICS] = NULL;
}
}
if (as_slm)
{ //save material list names
for (U32 i = 0; i < high->mMaterialList.size(); ++i)
{
mdl["material_list"][i] = high->mMaterialList[i];
}
}
for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx)
{
if (model[idx] && model[idx]->getNumVolumeFaces() > 0)
@@ -1436,7 +1426,7 @@ LLSD LLModel::writeModel(
for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i)
{ //for each face
const LLVolumeFace& face = model[idx]->getVolumeFace(i);
for (U32 j = 0; j < face.mNumVertices; ++j)
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
{
update_min_max(min_pos, max_pos, face.mPositions[j].getF32ptr());
}
@@ -1462,24 +1452,30 @@ LLSD LLModel::writeModel(
U32 tc_idx = 0;
LLVector2* ftc = (LLVector2*) face.mTexCoords;
LLVector2 min_tc = ftc[0];
LLVector2 max_tc = min_tc;
//get texture coordinate domain
for (U32 j = 0; j < face.mNumVertices; ++j)
LLVector2 min_tc;
LLVector2 max_tc;
if (ftc)
{
update_min_max(min_tc, max_tc, ftc[j]);
min_tc = ftc[0];
max_tc = min_tc;
//get texture coordinate domain
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
{
update_min_max(min_tc, max_tc, ftc[j]);
}
}
LLVector2 tc_range = max_tc - min_tc;
for (U32 j = 0; j < face.mNumVertices; ++j)
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
{ //for each vert
F32* pos = face.mPositions[j].getF32ptr();
F32* norm = face.mNormals[j].getF32ptr();
//position + normal
//position
for (U32 k = 0; k < 3; ++k)
{ //for each component
//convert to 16-bit normalized across domain
@@ -1489,33 +1485,44 @@ LLSD LLModel::writeModel(
//write to binary buffer
verts[vert_idx++] = buff[0];
verts[vert_idx++] = buff[1];
//convert to 16-bit normalized
val = (U16) ((norm[k]+1.f)*0.5f*65535);
//write to binary buffer
normals[norm_idx++] = buff[0];
normals[norm_idx++] = buff[1];
}
if (face.mNormals)
{ //normals
F32* norm = face.mNormals[j].getF32ptr();
for (U32 k = 0; k < 3; ++k)
{ //for each component
//convert to 16-bit normalized
U16 val = (U16) ((norm[k]+1.f)*0.5f*65535);
U8* buff = (U8*) &val;
//write to binary buffer
normals[norm_idx++] = buff[0];
normals[norm_idx++] = buff[1];
}
}
F32* src_tc = (F32*) face.mTexCoords[j].mV;
//texcoord
for (U32 k = 0; k < 2; ++k)
{ //for each component
//convert to 16-bit normalized
U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535);
if (face.mTexCoords)
{
for (U32 k = 0; k < 2; ++k)
{ //for each component
//convert to 16-bit normalized
U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535);
U8* buff = (U8*) &val;
//write to binary buffer
tc[tc_idx++] = buff[0];
tc[tc_idx++] = buff[1];
U8* buff = (U8*) &val;
//write to binary buffer
tc[tc_idx++] = buff[0];
tc[tc_idx++] = buff[1];
}
}
}
U32 idx_idx = 0;
for (U32 j = 0; j < face.mNumIndices; ++j)
for (U32 j = 0; j < (U32)face.mNumIndices; ++j)
{
U8* buff = (U8*) &(face.mIndices[j]);
indices[idx_idx++] = buff[0];
@@ -1525,12 +1532,19 @@ LLSD LLModel::writeModel(
//write out face data
mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue();
mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
mdl[model_names[idx]][i]["Position"] = verts;
mdl[model_names[idx]][i]["Normal"] = normals;
mdl[model_names[idx]][i]["TexCoord0"] = tc;
if (face.mNormals)
{
mdl[model_names[idx]][i]["Normal"] = normals;
}
if (face.mTexCoords)
{
mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue();
mdl[model_names[idx]][i]["TexCoord0"] = tc;
}
mdl[model_names[idx]][i]["TriangleList"] = indices;
if (skinning)
@@ -1544,7 +1558,7 @@ LLSD LLModel::writeModel(
std::stringstream ostr;
for (U32 j = 0; j < face.mNumVertices; ++j)
for (U32 j = 0; j < (U32)face.mNumVertices; ++j)
{
LLVector3 pos(face.mPositions[j].getF32ptr());
@@ -1588,10 +1602,10 @@ LLSD LLModel::writeModel(
}
}
return writeModelToStream(ostr, mdl, nowrite);
return writeModelToStream(ostr, mdl, nowrite, as_slm);
}
LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BOOL as_slm)
{
U32 bytes = 0;
@@ -1599,6 +1613,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite)
LLSD header;
if (as_slm && mdl.has("material_list"))
{ //save material binding names to header
header["material_list"] = mdl["material_list"];
}
std::string skin;
if (mdl.has("skin"))
@@ -1689,13 +1708,13 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
}
else
{ //no exact match found, get closest point
const F32 epsilon = 2.f/65536;
const F32 epsilon = 1e-5f;
weight_map::iterator iter_up = mSkinWeights.lower_bound(pos);
weight_map::iterator iter_down = ++iter_up;
weight_map::iterator best = iter_up;
F32 min_dist = (iter->first - pos).magVecSquared();
F32 min_dist = (iter->first - pos).magVec();
bool done = false;
while (!done)
@@ -1706,7 +1725,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
if (iter_up != mSkinWeights.end() && ++iter_up != mSkinWeights.end())
{
done = false;
F32 dist = (iter_up->first - pos).magVecSquared();
F32 dist = (iter_up->first - pos).magVec();
if (dist < epsilon)
{
@@ -1724,7 +1743,7 @@ LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos)
{
done = false;
F32 dist = (iter_down->first - pos).magVecSquared();
F32 dist = (iter_down->first - pos).magVec();
if (dist < epsilon)
{
@@ -1792,6 +1811,15 @@ bool LLModel::loadModel(std::istream& is)
}
}
if (header.has("material_list"))
{ //load material list names
mMaterialList.clear();
for (U32 i = 0; i < (U32)header["material_list"].size(); ++i)
{
mMaterialList.push_back(header["material_list"][i].asString());
}
}
std::string nm[] =
{
"lowest_lod",
@@ -1808,6 +1836,7 @@ bool LLModel::loadModel(std::istream& is)
if (header[nm[lod]]["offset"].asInteger() == -1 ||
header[nm[lod]]["size"].asInteger() == 0 )
{ //cannot load requested LOD
llwarns << "LoD data is invalid!" << llendl;
return false;
}
@@ -1821,7 +1850,7 @@ bool LLModel::loadModel(std::istream& is)
is.seekg(cur_pos);
}
if (lod == LLModel::LOD_PHYSICS)
if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS)
{
std::ios::pos_type cur_pos = is.tellg();
loadDecomposition(header, is);
@@ -1868,11 +1897,66 @@ bool LLModel::loadModel(std::istream& is)
}
return true;
}
else
{
llwarns << "unpackVolumeFaces failed!" << llendl;
}
return false;
}
void LLModel::matchMaterialOrder(LLModel* ref)
{
llassert(ref->mMaterialList.size() == mMaterialList.size());
std::map<std::string, U32> index_map;
//build a map of material slot names to face indexes
bool reorder = false;
std::set<std::string> base_mat;
std::set<std::string> cur_mat;
for (U32 i = 0; i < mMaterialList.size(); i++)
{
index_map[ref->mMaterialList[i]] = i;
if (!reorder)
{ //if any material name does not match reference, we need to reorder
reorder = ref->mMaterialList[i] != mMaterialList[i];
}
base_mat.insert(ref->mMaterialList[i]);
cur_mat.insert(mMaterialList[i]);
}
if (reorder &&
base_mat == cur_mat) //don't reorder if material name sets don't match
{
std::vector<LLVolumeFace> new_face_list;
new_face_list.resize(mVolumeFaces.size());
std::vector<std::string> new_material_list;
new_material_list.resize(mVolumeFaces.size());
//rebuild face list so materials have the same order
//as the reference model
for (U32 i = 0; i < mMaterialList.size(); ++i)
{
U32 ref_idx = index_map[mMaterialList[i]];
new_face_list[ref_idx] = mVolumeFaces[i];
new_material_list[ref_idx] = mMaterialList[i];
}
llassert(new_material_list == ref->mMaterialList);
mVolumeFaces = new_face_list;
}
//override material list with reference model ordering
mMaterialList = ref->mMaterialList;
}
bool LLModel::loadSkinInfo(LLSD& header, std::istream &is)
{
@@ -1926,7 +2010,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
{
if (skin.has("joint_names"))
{
for (U32 i = 0; i < skin["joint_names"].size(); ++i)
for (U32 i = 0; i < (U32)skin["joint_names"].size(); ++i)
{
mJointNames.push_back(skin["joint_names"][i]);
}
@@ -1934,7 +2018,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
if (skin.has("inverse_bind_matrix"))
{
for (U32 i = 0; i < skin["inverse_bind_matrix"].size(); ++i)
for (U32 i = 0; i < (U32)skin["inverse_bind_matrix"].size(); ++i)
{
LLMatrix4 mat;
for (U32 j = 0; j < 4; j++)
@@ -1962,7 +2046,7 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
if (skin.has("alt_inverse_bind_matrix"))
{
for (U32 i = 0; i < skin["alt_inverse_bind_matrix"].size(); ++i)
for (U32 i = 0; i < (U32)skin["alt_inverse_bind_matrix"].size(); ++i)
{
LLMatrix4 mat;
for (U32 j = 0; j < 4; j++)
@@ -2034,7 +2118,7 @@ LLModel::Decomposition::Decomposition(LLSD& data)
void LLModel::Decomposition::fromLLSD(LLSD& decomp)
{
if (decomp.has("HullList"))
if (decomp.has("HullList") && decomp.has("Positions"))
{
// updated for const-correctness. gcc is picky about this type of thing - Nyx
const LLSD::Binary& hulls = decomp["HullList"].asBinary();
@@ -2190,6 +2274,8 @@ LLSD LLModel::Decomposition::asLLSD() const
ret["Min"] = min.getValue();
ret["Max"] = max.getValue();
LLVector3 range = max-min;
if (!hulls.empty())
{
ret["HullList"] = hulls;
@@ -2199,10 +2285,6 @@ LLSD LLModel::Decomposition::asLLSD() const
{
LLSD::Binary p(total*3*2);
LLVector3 min(-0.5f, -0.5f, -0.5f);
LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 i = 0; i < mHull.size(); ++i)
@@ -2214,12 +2296,10 @@ LLSD LLModel::Decomposition::asLLSD() const
for (U32 j = 0; j < mHull[i].size(); ++j)
{
U64 test = 0;
const F32* src = mHull[i][j].mV;
for (U32 k = 0; k < 3; k++)
{
F32* src = (F32*) (mHull[i][j].mV);
llassert(src[k] <= 0.501f && src[k] >= -0.501f);
//convert to 16-bit normalized across domain
U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535);
@@ -2258,19 +2338,15 @@ LLSD LLModel::Decomposition::asLLSD() const
{
LLSD::Binary p(mBaseHull.size()*3*2);
LLVector3 min(-0.5f, -0.5f, -0.5f);
LLVector3 max(0.5f, 0.5f, 0.5f);
LLVector3 range = max-min;
U32 vert_idx = 0;
for (U32 j = 0; j < mBaseHull.size(); ++j)
{
const F32* v = mBaseHull[j].mV;
for (U32 k = 0; k < 3; k++)
{
llassert(mBaseHull[j].mV[k] <= 0.51f && mBaseHull[j].mV[k] >= -0.51f);
//convert to 16-bit normalized across domain
U16 val = (U16) (((mBaseHull[j].mV[k]-min.mV[k])/range.mV[k])*65535);
U16 val = (U16) (((v[k]-min.mV[k])/range.mV[k])*65535);
U8* buff = (U8*) &val;
//write to binary buffer
@@ -2315,4 +2391,4 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs)
mPhysicsShapeMesh = rhs->mPhysicsShapeMesh;
}
}
#endif //MESH_ENABLED

View File

@@ -32,8 +32,10 @@
#include "v4math.h"
#include "m4math.h"
#if MESH_IMPORT
class daeElement;
class domMesh;
#endif //MESH_IMPORT
#define MAX_MODEL_FACES 8
@@ -137,16 +139,20 @@ public:
const LLModel::Decomposition& decomp,
BOOL upload_skin,
BOOL upload_joints,
BOOL nowrite = FALSE);
BOOL nowrite = FALSE,
BOOL as_slm = FALSE);
static LLSD writeModelToStream(
std::ostream& ostr,
LLSD& mdl,
BOOL nowrite = FALSE);
BOOL nowrite = FALSE, BOOL as_slm = FALSE);
#if MESH_IMPORT
static LLModel* loadModelFromDomMesh(domMesh* mesh);
static std::string getElementLabel(daeElement* element);
#endif //MESH_IMPORT
std::string getName() const;
std::string getMetric() const {return mMetric;}
EModelStatus getStatus() const {return mStatus;}
static std::string getStatusString(U32 status) ;
@@ -171,6 +177,11 @@ public:
void optimizeVolumeFaces();
void offsetMesh( const LLVector3& pivotPoint );
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
//reorder face list based on mMaterialList in this and reference so
//order matches that of reference (material ordering touchup)
void matchMaterialOrder(LLModel* reference);
std::vector<std::string> mMaterialList;
//data used for skin weights
@@ -211,6 +222,22 @@ public:
}
};
struct JointPositionalCompare
{
//Are the doubles the same w/in epsilon specified tolerance
bool areEqual( double a, double b )
{
const float epsilon = 1e-5f;
return (abs((int)(a - b)) < epsilon) && (a < b);
}
//Make sure that we return false for any values that are within the tolerance for equivalence
bool operator() ( const LLVector3& a, const LLVector3& b )
{
return ( areEqual( a[0],b[0]) && areEqual( a[1],b[1] ) && areEqual( a[2],b[2]) ) ? false : true;
}
};
//copy of position array for this model -- mPosition[idx].mV[X,Y,Z]
std::vector<LLVector3> mPosition;
@@ -228,6 +255,8 @@ public:
std::string mRequestedLabel; // name requested in UI, if any.
std::string mLabel; // name computed from dae.
std::string mMetric; // user-supplied metric data for upload
LLVector3 mNormalizedScale;
LLVector3 mNormalizedTranslation;
@@ -250,8 +279,10 @@ public:
EModelStatus mStatus ;
protected:
#if MESH_IMPORT
void addVolumeFacesFromDomMesh(domMesh* mesh);
virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh);
#endif //MESH_IMPORT
};
#endif //LL_LLMODEL_H

View File

@@ -109,6 +109,10 @@ public:
PARAMS_LIGHT = 0x20,
PARAMS_SCULPT = 0x30,
PARAMS_LIGHT_IMAGE = 0x40,
#if MESH_ENABLED
PARAMS_RESERVED = 0x50, // Used on server-side
PARAMS_MESH = 0x60,
#endif MESH_ENABLED
};
public:

View File

@@ -63,6 +63,9 @@ LLShaderFeatures::LLShaderFeatures()
: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false),
hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false),
hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
#if MESH_ENABLED
, hasObjectSkinning(false)
#endif //MESH_ENABLED
{
}

View File

@@ -48,6 +48,9 @@ public:
bool hasWaterFog; // implies no gamma
bool hasTransport; // implies no lighting (it's possible to have neither though)
bool hasSkinning;
#if MESH_ENABLED
bool hasObjectSkinning;
#endif //MESH_ENABLED
bool hasAtmospherics;
bool hasGamma;

View File

@@ -152,6 +152,16 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
return FALSE;
}
}
#if MESH_ENABLED
if (features->hasObjectSkinning)
{
if (!shader->attachObject("avatar/objectSkinV.glsl"))
{
return FALSE;
}
}
#endif //MESH_ENABLED
///////////////////////////////////////
// Attach Fragment Shader Features Next

View File

@@ -293,6 +293,7 @@ set(viewer_SOURCE_FILES
llmediaremotectrl.cpp
llmemoryview.cpp
llmenucommands.cpp
llmeshrepository.cpp
llmimetypes.cpp
llmorphview.cpp
llmoveview.cpp
@@ -771,6 +772,7 @@ set(viewer_HEADER_FILES
llmediaremotectrl.h
llmemoryview.h
llmenucommands.h
llmeshrepository.h
llmimetypes.h
llmorphview.h
llmoveview.h

View File

@@ -7885,6 +7885,51 @@
<key>Value</key>
<integer>410</integer>
</map>
<key>MeshEnabled</key>
<map>
<key>Comment</key>
<string>Expose UI for mesh functionality (may require restart to take effect).</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<real>1</real>
</map>
<key>MeshImportUseSLM</key>
<map>
<key>Comment</key>
<string>Use cached copy of last upload for a dae if available instead of loading dae file from scratch.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<real>0</real>
</map>
<key>MeshUploadLogXML</key>
<map>
<key>Comment</key>
<string>Verbose XML logging on mesh upload</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<real>0</real>
</map>
<key>MeshUploadFakeErrors</key>
<map>
<key>Comment</key>
<string>Force upload errors (for testing)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<real>0</real>
</map>
<key>MigrateCacheDirectory</key>
<map>
<key>Comment</key>
@@ -11037,6 +11082,39 @@
<key>Value</key>
<real>1.0</real>
</map>
<key>MeshStreamingCostScaler</key>
<map>
<key>Comment</key>
<string>DEBUG</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>2.0</real>
</map>
<key>MeshThreadCount</key>
<map>
<key>Comment</key>
<string>Number of threads to use for loading meshes.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>8</integer>
</map>
<key>MeshMaxConcurrentRequests</key>
<map>
<key>Comment</key>
<string>Number of threads to use for loading meshes.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>32</integer>
</map>
<key>RunBtnState</key>
<map>
<key>Comment</key>

View File

@@ -0,0 +1,30 @@
/**
* @file objectSkinV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
attribute vec4 object_weight;
uniform mat4 matrixPalette[32];
mat4 getObjectSkinnedTransform()
{
int i;
vec4 w = fract(object_weight);
vec4 index = floor(object_weight);
float scale = 1.0/(w.x+w.y+w.z+w.w);
w *= scale;
mat4 mat = matrixPalette[int(index.x)]*w.x;
mat += matrixPalette[int(index.y)]*w.y;
mat += matrixPalette[int(index.z)]*w.z;
mat += matrixPalette[int(index.w)]*w.w;
return mat;
}

View File

@@ -0,0 +1,112 @@
/**
* @file alphaSkinnedV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
mat4 getObjectSkinnedTransform();
void calcAtmospherics(vec3 inPositionEye);
float calcDirectionalLight(vec3 n, vec3 l);
vec3 atmosAmbient(vec3 light);
vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec3 scaleUpLight(vec3 light);
varying vec3 vary_position;
varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_normal;
varying vec3 vary_fragcoord;
varying vec3 vary_pointlight_col;
uniform float near_clip;
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
vec3 lv = lp.xyz-v;
//get distance
float d = length(lv);
float da = 0.0;
if (d > 0.0 && la > 0.0 && fa > 0.0)
{
//normalize light vector
lv *= 1.0/d;
//distance attenuation
float dist2 = d*d/(la*la);
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
// spotlight coefficient.
float spot = max(dot(-ln, lv), is_pointlight);
da *= spot*spot; // GL_SPOT_EXPONENT=2
//angular attenuation
da *= calcDirectionalLight(n, lv);
}
return da;
}
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
vec4 pos;
vec3 norm;
mat4 trans = getObjectSkinnedTransform();
trans = gl_ModelViewMatrix * trans;
pos = trans * gl_Vertex;
norm = gl_Vertex.xyz + gl_Normal.xyz;
norm = normalize(( trans*vec4(norm, 1.0) ).xyz-pos.xyz);
vec4 frag_pos = gl_ProjectionMatrix * pos;
gl_Position = frag_pos;
vary_position = pos.xyz;
vary_normal = norm;
calcAtmospherics(pos.xyz);
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
// Collect normal lights
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a);
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a);
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a);
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a);
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a);
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a);
vary_pointlight_col = col.rgb*gl_Color.rgb;
col.rgb = vec3(0,0,0);
// Add windlight lights
col.rgb = atmosAmbient(vec3(0.));
vary_ambient = col.rgb*gl_Color.rgb;
vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
col.rgb = min(col.rgb*gl_Color.rgb, 1.0);
gl_FrontColor = col;
gl_FogFragCoord = pos.z;
vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip);
}

View File

@@ -0,0 +1,18 @@
/**
* @file avatarShadowF.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
uniform sampler2D diffuseMap;
void main()
{
//gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a);
gl_FragColor = vec4(1,1,1,1);
}

View File

@@ -0,0 +1,27 @@
/**
* @file attachmentShadowV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
mat4 getObjectSkinnedTransform();
void main()
{
//transform vertex
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
mat4 mat = getObjectSkinnedTransform();
mat = gl_ModelViewMatrix * mat;
vec3 pos = (mat*gl_Vertex).xyz;
gl_FrontColor = gl_Color;
vec4 p = gl_ProjectionMatrix * vec4(pos, 1.0);
p.z = max(p.z, -p.w+0.01);
gl_Position = p;
}

View File

@@ -0,0 +1,37 @@
/**
* @file bumpV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
varying vec3 vary_mat0;
varying vec3 vary_mat1;
varying vec3 vary_mat2;
mat4 getObjectSkinnedTransform();
void main()
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
mat4 mat = getObjectSkinnedTransform();
mat = gl_ModelViewMatrix * mat;
vec3 pos = (mat*gl_Vertex).xyz;
vec3 n = normalize((mat * vec4(gl_Normal.xyz+gl_Vertex.xyz, 1.0)).xyz-pos.xyz);
vec3 b = normalize((mat * vec4(gl_MultiTexCoord2.xyz+gl_Vertex.xyz, 1.0)).xyz-pos.xyz);
vec3 t = cross(b, n);
vary_mat0 = vec3(t.x, b.x, n.x);
vary_mat1 = vec3(t.y, b.y, n.y);
vary_mat2 = vec3(t.z, b.z, n.z);
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
gl_FrontColor = gl_Color;
}

View File

@@ -0,0 +1,33 @@
/**
* @file diffuseSkinnedV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
varying vec3 vary_normal;
mat4 getObjectSkinnedTransform();
void main()
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
mat4 mat = getObjectSkinnedTransform();
mat = gl_ModelViewMatrix * mat;
vec3 pos = (mat*gl_Vertex).xyz;
vec4 norm = gl_Vertex;
norm.xyz += gl_Normal.xyz;
norm.xyz = (mat*norm).xyz;
norm.xyz = normalize(norm.xyz-pos.xyz);
vary_normal = norm.xyz;
gl_FrontColor = gl_Color;
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
}

View File

@@ -0,0 +1,39 @@
/**
* @file shinySimpleSkinnedV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
attribute vec4 object_weight;
void main()
{
mat4 mat = getObjectSkinnedTransform();
mat = gl_ModelViewMatrix * mat;
vec3 pos = (mat*gl_Vertex).xyz;
vec4 norm = gl_Vertex;
norm.xyz += gl_Normal.xyz;
norm.xyz = (mat*norm).xyz;
norm.xyz = normalize(norm.xyz-pos.xyz);
vec3 ref = reflect(pos.xyz, -norm.xyz);
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0);
calcAtmospherics(pos.xyz);
gl_FrontColor = gl_Color;
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
gl_FogFragCoord = pos.z;
}

View File

@@ -0,0 +1,37 @@
/**
* @file fullbrightSkinnedV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
attribute vec4 object_weight;
void main()
{
//transform vertex
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
mat4 mat = getObjectSkinnedTransform();
mat = gl_ModelViewMatrix * mat;
vec3 pos = (mat*gl_Vertex).xyz;
vec4 norm = gl_Vertex;
norm.xyz += gl_Normal.xyz;
norm.xyz = (mat*norm).xyz;
norm.xyz = normalize(norm.xyz-pos.xyz);
calcAtmospherics(pos.xyz);
gl_FrontColor = gl_Color;
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
gl_FogFragCoord = pos.z;
}

View File

@@ -0,0 +1,39 @@
/**
* @file shinySimpleSkinnedV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
attribute vec4 object_weight;
void main()
{
mat4 mat = getObjectSkinnedTransform();
mat = gl_ModelViewMatrix * mat;
vec3 pos = (mat*gl_Vertex).xyz;
vec4 norm = gl_Vertex;
norm.xyz += gl_Normal.xyz;
norm.xyz = (mat*norm).xyz;
norm.xyz = normalize(norm.xyz-pos.xyz);
vec3 ref = reflect(pos.xyz, -norm.xyz);
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0);
calcAtmospherics(pos.xyz);
vec4 color = calcLighting(pos.xyz, norm.xyz, gl_Color, vec4(0.));
gl_FrontColor = color;
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
}

View File

@@ -0,0 +1,39 @@
/**
* @file simpleSkinnedV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
attribute vec4 object_weight;
void main()
{
//transform vertex
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
mat4 mat = getObjectSkinnedTransform();
mat = gl_ModelViewMatrix * mat;
vec3 pos = (mat*gl_Vertex).xyz;
vec4 norm = gl_Vertex;
norm.xyz += gl_Normal.xyz;
norm.xyz = (mat*norm).xyz;
norm.xyz = normalize(norm.xyz-pos.xyz);
calcAtmospherics(pos.xyz);
vec4 color = calcLighting(pos.xyz, norm.xyz, gl_Color, vec4(0.));
gl_FrontColor = color;
gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0);
gl_FogFragCoord = pos.z;
}

View File

@@ -0,0 +1,115 @@
/**
* @file alphaSkinnedV.glsl
*
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#version 120
vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
void calcAtmospherics(vec3 inPositionEye);
float calcDirectionalLight(vec3 n, vec3 l);
mat4 getObjectSkinnedTransform();
vec3 atmosAmbient(vec3 light);
vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec3 scaleUpLight(vec3 light);
varying vec3 vary_ambient;
varying vec3 vary_directional;
varying vec3 vary_fragcoord;
varying vec3 vary_position;
varying vec3 vary_pointlight_col;
uniform float near_clip;
uniform float shadow_offset;
uniform float shadow_bias;
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
{
//get light vector
vec3 lv = lp.xyz-v;
//get distance
float d = length(lv);
float da = 0.0;
if (d > 0.0 && la > 0.0 && fa > 0.0)
{
//normalize light vector
lv *= 1.0/d;
//distance attenuation
float dist2 = d*d/(la*la);
da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
// spotlight coefficient.
float spot = max(dot(-ln, lv), is_pointlight);
da *= spot*spot; // GL_SPOT_EXPONENT=2
//angular attenuation
da *= calcDirectionalLight(n, lv);
}
return da;
}
void main()
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
mat4 mat = getObjectSkinnedTransform();
mat = gl_ModelViewMatrix * mat;
vec3 pos = (mat*gl_Vertex).xyz;
gl_Position = gl_ProjectionMatrix * vec4(pos, 1.0);
vec4 n = gl_Vertex;
n.xyz += gl_Normal.xyz;
n.xyz = (mat*n).xyz;
n.xyz = normalize(n.xyz-pos.xyz);
vec3 norm = n.xyz;
float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset;
calcAtmospherics(pos.xyz);
//vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
// Collect normal lights
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a);
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a);
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a);
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a);
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a);
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a);
vary_pointlight_col = col.rgb*gl_Color.rgb;
col.rgb = vec3(0,0,0);
// Add windlight lights
col.rgb = atmosAmbient(vec3(0.));
vary_ambient = col.rgb*gl_Color.rgb;
vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
col.rgb = min(col.rgb*gl_Color.rgb, 1.0);
gl_FrontColor = col;
gl_FogFragCoord = pos.z;
pos.xyz = (gl_ModelViewProjectionMatrix * gl_Vertex).xyz;
vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
}

View File

@@ -0,0 +1,346 @@
/**
* @file softenLightF.glsl
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* $/LicenseInfo$
*/
#version 120
#extension GL_ARB_texture_rectangle : enable
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
uniform sampler2DRect depthMap;
uniform sampler2D noiseMap;
uniform samplerCube environmentMap;
uniform sampler2D lightFunc;
uniform vec3 gi_quad;
uniform float blur_size;
uniform float blur_fidelity;
// Inputs
uniform vec4 morphFactor;
uniform vec3 camPosLocal;
//uniform vec4 camPosWorld;
uniform vec4 gamma;
uniform vec4 lightnorm;
uniform vec4 sunlight_color;
uniform vec4 ambient;
uniform vec4 blue_horizon;
uniform vec4 blue_density;
uniform vec4 haze_horizon;
uniform vec4 haze_density;
uniform vec4 cloud_shadow;
uniform vec4 density_multiplier;
uniform vec4 distance_multiplier;
uniform vec4 max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform vec3 env_mat[3];
uniform vec4 shadow_clip;
uniform mat3 ssao_effect_mat;
uniform mat4 inv_proj;
uniform vec2 screen_res;
varying vec4 vary_light;
varying vec2 vary_fragcoord;
vec3 vary_PositionEye;
vec3 vary_SunlitColor;
vec3 vary_AmblitColor;
vec3 vary_AdditiveColor;
vec3 vary_AtmosAttenuation;
vec4 getPosition_d(vec2 pos_screen, float depth)
{
vec2 sc = pos_screen.xy*2.0;
sc /= screen_res;
sc -= vec2(1.0,1.0);
vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
vec4 pos = inv_proj * ndc;
pos /= pos.w;
pos.w = 1.0;
return pos;
}
vec4 getPosition(vec2 pos_screen)
{ //get position in screen space (world units) given window coordinate and depth map
float depth = texture2DRect(depthMap, pos_screen.xy).a;
return getPosition_d(pos_screen, depth);
}
vec3 getPositionEye()
{
return vary_PositionEye;
}
vec3 getSunlitColor()
{
return vary_SunlitColor;
}
vec3 getAmblitColor()
{
return vary_AmblitColor;
}
vec3 getAdditiveColor()
{
return vary_AdditiveColor;
}
vec3 getAtmosAttenuation()
{
return vary_AtmosAttenuation;
}
void setPositionEye(vec3 v)
{
vary_PositionEye = v;
}
void setSunlitColor(vec3 v)
{
vary_SunlitColor = v;
}
void setAmblitColor(vec3 v)
{
vary_AmblitColor = v;
}
void setAdditiveColor(vec3 v)
{
vary_AdditiveColor = v;
}
void setAtmosAttenuation(vec3 v)
{
vary_AtmosAttenuation = v;
}
void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
vec3 P = inPositionEye;
setPositionEye(P);
//(TERRAIN) limit altitude
if (P.y > max_y.x) P *= (max_y.x / P.y);
if (P.y < -max_y.x) P *= (-max_y.x / P.y);
vec3 tmpLightnorm = lightnorm.xyz;
vec3 Pn = normalize(P);
float Plen = length(P);
vec4 temp1 = vec4(0);
vec3 temp2 = vec3(0);
vec4 blue_weight;
vec4 haze_weight;
vec4 sunlight = sunlight_color;
vec4 light_atten;
//sunlight attenuation effect (hue and brightness) due to atmosphere
//this is used later for sunlight modulation at various altitudes
light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x);
//I had thought blue_density and haze_density should have equal weighting,
//but attenuation due to haze_density tends to seem too strong
temp1 = blue_density + vec4(haze_density.r);
blue_weight = blue_density / temp1;
haze_weight = vec4(haze_density.r) / temp1;
//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
temp2.y = max(0.0, tmpLightnorm.y);
temp2.y = 1. / temp2.y;
sunlight *= exp( - light_atten * temp2.y);
// main atmospheric scattering line integral
temp2.z = Plen * density_multiplier.x;
// Transparency (-> temp1)
// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati
// compiler gets confused.
temp1 = exp(-temp1 * temp2.z * distance_multiplier.x);
//final atmosphere attenuation factor
setAtmosAttenuation(temp1.rgb);
//compute haze glow
//(can use temp2.x as temp because we haven't used it yet)
temp2.x = dot(Pn, tmpLightnorm.xyz);
temp2.x = 1. - temp2.x;
//temp2.x is 0 at the sun and increases away from sun
temp2.x = max(temp2.x, .03); //was glow.y
//set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
temp2.x *= glow.x;
//higher glow.x gives dimmer glow (because next step is 1 / "angle")
temp2.x = pow(temp2.x, glow.z);
//glow.z should be negative, so we're doing a sort of (1 / "angle") function
//add "minimum anti-solar illumination"
temp2.x += .25;
//increase ambient when there are more clouds
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
/* decrease value and saturation (that in HSV, not HSL) for occluded areas
* // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
* // The following line of code performs the equivalent of:
* float ambAlpha = tmpAmbient.a;
* float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
* vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
* tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
*/
tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
//haze color
setAdditiveColor(
vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient)
+ (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x
+ tmpAmbient)));
//brightness of surface both sunlight and ambient
setSunlitColor(vec3(sunlight * .5));
setAmblitColor(vec3(tmpAmbient * .25));
setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
}
vec3 atmosLighting(vec3 light)
{
light *= getAtmosAttenuation().r;
light += getAdditiveColor();
return (2.0 * light);
}
vec3 atmosTransport(vec3 light) {
light *= getAtmosAttenuation().r;
light += getAdditiveColor() * 2.0;
return light;
}
vec3 atmosGetDiffuseSunlightColor()
{
return getSunlitColor();
}
vec3 scaleDownLight(vec3 light)
{
return (light / scene_light_strength );
}
vec3 scaleUpLight(vec3 light)
{
return (light * scene_light_strength);
}
vec3 atmosAmbient(vec3 light)
{
return getAmblitColor() + light / 2.0;
}
vec3 atmosAffectDirectionalLight(float lightIntensity)
{
return getSunlitColor() * lightIntensity;
}
vec3 scaleSoftClip(vec3 light)
{
//soft clip effect:
light = 1. - clamp(light, vec3(0.), vec3(1.));
light = 1. - pow(light, gamma.xxx);
return light;
}
void main()
{
vec2 tc = vary_fragcoord.xy;
float depth = texture2DRect(depthMap, tc.xy).a;
vec3 pos = getPosition_d(tc, depth).xyz;
vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
//vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz;
float da = max(dot(norm.xyz, vary_light.xyz), 0.0);
vec4 diffuse = texture2DRect(diffuseRect, tc);
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
float scol = max(scol_ambocc.r, diffuse.a);
float ambocc = scol_ambocc.g;
calcAtmospherics(pos.xyz, ambocc);
vec3 col = atmosAmbient(vec3(0));
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
col *= diffuse.rgb;
if (spec.a > 0.0) // specular reflection
{
// the old infinite-sky shiny reflection
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
/*
// screen-space cheap fakey reflection map
//
vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz));
depth -= 0.5; // unbias depth
// first figure out where we'll make our 2D guess from
vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth;
// Offset the guess source a little according to a trivial
// checkerboard dither function and spec.a.
// This is meant to be similar to sampling a blurred version
// of the diffuse map. LOD would be better in that regard.
// The goal of the blur is to soften reflections in surfaces
// with low shinyness, and also to disguise our lameness.
float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0
float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5);
ref2d += vec2(checkoffset, checkoffset);
ref2d += tc.xy; // use as offset from destination
// Get attributes from the 2D guess point.
// We average two samples of diffuse (not of anything else) per
// pixel to try to reduce aliasing some more.
vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb +
texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
float refdepth = texture2DRect(depthMap, ref2d).a;
vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
float refshad = texture2DRect(lightMap, ref2d).r;
vec3 refn = texture2DRect(normalMap, ref2d).rgb;
refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
refn = normalize(refn);
// figure out how appropriate our guess actually was
float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
// darken reflections from points which face away from the reflected ray - our guess was a back-face
//refapprop *= step(dot(refnorm, refn), 0.0);
refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
// get appropriate light strength for guess-point
// reflect light direction to increase the illusion that
// these are reflections.
vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad);
// apply sun color to guess-point, dampen according to inappropriateness of guess
float refmod = min(refapprop, reflit);
vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
vec3 ssshiny = (refprod * spec.a);
ssshiny *= 0.3; // dampen it even more
*/
vec3 ssshiny = vec3(0,0,0);
// add the two types of shiny together
col += (ssshiny + dumbshiny) * spec.rgb;
}
col = atmosLighting(col);
col = scaleSoftClip(col);
gl_FragColor.rgb = col;
gl_FragColor.a = 0.0;
}

View File

@@ -37,16 +37,23 @@
#include "llvoavatar.h"
#include "m3math.h"
#include "llmatrix4a.h"
#include "llagent.h"
#include "llagent.h" //for gAgent.needsRenderAvatar()
#include "lldrawable.h"
#include "lldrawpoolbump.h"
#include "llface.h"
#if MESH_ENABLED
#include "llmeshrepository.h"
#endif //MESH_ENABLED
#include "llsky.h"
#include "llviewercamera.h"
#include "llviewerregion.h"
#include "noise.h"
#include "pipeline.h"
#include "llviewershadermgr.h"
#include "llvovolume.h"
#include "llvolume.h"
#include "llappviewer.h"
#include "llrendersphere.h"
#include "llviewerpartsim.h"
@@ -60,6 +67,10 @@ BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE;
BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE;
S32 LLDrawPoolAvatar::sDiffuseChannel = 0;
#if MESH_ENABLED
static bool is_deferred_render = false;
#endif //MESH_ENABLED
extern BOOL gUseGLPick;
F32 CLOTHING_GRAVITY_EFFECT = 0.7f;
@@ -157,6 +168,9 @@ LLMatrix4& LLDrawPoolAvatar::getModelView()
void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
{
sSkipTransparent = TRUE;
#if MESH_ENABLED
is_deferred_render = true;
#endif //MESH_ENABLED
if (LLPipeline::sImpostorRender)
{ //impostor pass does not have rigid or impostor rendering
@@ -187,7 +201,11 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
void LLDrawPoolAvatar::endDeferredPass(S32 pass)
{
sSkipTransparent = FALSE;
#if MESH_ENABLED
is_deferred_render = false;
#endif //MESH_ENABLED
if (LLPipeline::sImpostorRender)
{
@@ -1406,7 +1424,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
LLMatrix4a bind_shape_matrix;
bind_shape_matrix.loadu(skin->mBindShapeMatrix);
for (U32 j = 0; j < buffer->getRequestedVerts(); ++j)
for (U32 j = 0; j < (U32)buffer->getRequestedVerts(); ++j)
{
LLMatrix4a final_mat;
final_mat.clear();
@@ -1458,7 +1476,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace*
void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
{
if (avatar->isSelf() && !gAgent.needsRenderAvatar())
if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled())
{
return;
}
@@ -1495,7 +1513,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
continue;
}
const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id);
const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj);
if (!skin)
{
continue;
@@ -1754,7 +1772,7 @@ void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep)
if (index > -1)
{
if (mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep)
if ((S32)mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep)
{
facep->setRiggedIndex(i,-1);
mRiggedFace[i].erase(mRiggedFace[i].begin()+index);

View File

@@ -42,6 +42,7 @@
#include "llmatrix4a.h"
#include "v3color.h"
#include "lldrawpoolavatar.h"
#include "lldrawpoolbump.h"
#include "llgl.h"
#include "llrender.h"
@@ -153,6 +154,9 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
{
mLastUpdateTime = gFrameTimeSeconds;
mLastMoveTime = 0.f;
#if MESH_ENABLED
mLastSkinTime = gFrameTimeSeconds;
#endif //MESH_ENABLED
mVSize = 0.f;
mPixelArea = 16.f;
mState = GLOBAL;
@@ -1140,7 +1144,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
LLStrider<LLVector3> binormals;
LLStrider<U16> indicesp;
#if MESH_ENABLED
LLStrider<LLVector3> weights;
LLStrider<LLVector4> weights;
#endif //MESH_ENABLED
BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME);
@@ -1597,7 +1601,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
{
for (S32 i = 0; i < num_vertices; i++)
{
weights[i].set(weights.getF32ptr());
weights[i].set(*(weights.get()));
}
}
#endif //MESH_ENABLED

View File

@@ -239,6 +239,9 @@ public:
LLVector2 mTexExtents[2];
F32 mDistance;
F32 mLastUpdateTime;
#if MESH_ENABLED
F32 mLastSkinTime;
#endif //MESH_ENABLED
F32 mLastMoveTime;
LLMatrix4* mTextureMatrix;
LLDrawInfo* mDrawInfo;

View File

@@ -127,6 +127,11 @@ static struct ft_display_info ft_display_table[] =
{ LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 },
{ LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 1 },
{ LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 },
#if MESH_ENABLED
{ LLFastTimer::FTM_UPDATE_RIGGED_VOLUME," Rigged", &LLColor4::red3, 0 },
{ LLFastTimer::FTM_SKIN_RIGGED, " Skin", &LLColor4::green1, 0 },
{ LLFastTimer::FTM_RIGGED_OCTREE, " Octree", &LLColor4::green5, 0 },
#endif //MESH_ENABLED
{ LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 },
{ LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 },
{ LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 },
@@ -155,6 +160,12 @@ static struct ft_display_info ft_display_table[] =
{ LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 },
{ LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 },
{ LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 },
#if MESH_ENABLED
{ LLFastTimer::FTM_MESH_UPDATE, " Mesh Update", &LLColor4::orange4, 0 },
{ LLFastTimer::FTM_MESH_LOCK1, " Lock 1", &LLColor4::orange5, 0 },
{ LLFastTimer::FTM_MESH_LOCK2, " Lock 2", &LLColor4::orange6, 0 },
{ LLFastTimer::FTM_LOAD_MESH_LOD, " Load LOD", &LLColor4::yellow3, 0 },
#endif //MESH_ENABLED
{ LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 },
{ LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 },
{ LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 },

View File

@@ -58,11 +58,15 @@
#include "llui.h"
#include "llviewercamera.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
#include "llhudrender.h"
#include "llworld.h"
#include "v2math.h"
#include "llvoavatar.h"
#if MESH_ENABLED
#include "llmeshrepository.h"
#endif //MESH_ENABLED
const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f;
@@ -96,10 +100,7 @@ F32 get_default_max_prim_scale(bool is_flora)
// a bit of a hack, but if it's foilage, we don't want to use the
// new larger scale which would result in giant trees and grass
#if MESH_ENABLED
if (gSavedSettings.getBOOL("MeshEnabled") &&
gAgent.getRegion() &&
!gAgent.getRegion()->getCapability("GetMesh").empty() &&
!gAgent.getRegion()->getCapability("ObjectAdd").empty() &&
if (gMeshRepo.meshRezEnabled() &&
!is_flora)
{
return DEFAULT_MAX_PRIM_SCALE;

File diff suppressed because it is too large Load Diff

View File

@@ -33,9 +33,37 @@
#include "llviewertexture.h"
#include "llvolume.h"
#if MESH_IMPORT
#define LLCONVEXDECOMPINTER_STATIC 1
#include "llconvexdecomposition.h"
#endif //MESH_IMPORT
#if !MESH_IMPORT
//Placeholder structs from LLConvexDecomposition.h:
struct LLCDMeshData
{
enum IndexType
{
INT_16,
INT_32
};
const float* mVertexBase;
int mVertexStrideBytes;
int mNumVertices;
const void* mIndexBase;
IndexType mIndexType;
int mIndexStrideBytes;
int mNumTriangles;
};
struct LLCDHull
{
const float* mVertexBase;
int mVertexStrideBytes;
int mNumVertices;
};
#endif //!MESH_IMPORT
class LLVOVolume;
class LLMeshResponder;
@@ -91,6 +119,7 @@ public:
LLPointer<LLViewerFetchedTexture> mDiffuseMap;
std::string mDiffuseMapFilename;
std::string mDiffuseMapLabel;
std::string mBinding;
LLColor4 mDiffuseColor;
bool mFullbright;
@@ -119,9 +148,9 @@ public:
S32 mLocalMeshID;
LLMatrix4 mTransform;
std::vector<LLImportMaterial> mMaterial;
std::map<std::string, LLImportMaterial> mMaterial;
LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::vector<LLImportMaterial>& materials)
LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials)
: mModel(model), mLabel(label), mTransform(transform), mMaterial(materials)
{
mLocalMeshID = -1;
@@ -160,6 +189,17 @@ public:
virtual void completed() = 0;
virtual void setStatusMessage(const std::string& msg);
bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;}
protected:
//internal use
LLVector3 mBBox[2] ;
F32 mTriangleAreaThreshold ;
void assignData(LLModel* mdl) ;
void updateTriangleAreaThreshold() ;
bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ;
};
LLCondition* mSignal;
@@ -178,7 +218,7 @@ public:
static S32 llcdCallback(const char*, S32, S32);
void cancel();
void setMeshData(LLCDMeshData& mesh);
void setMeshData(LLCDMeshData& mesh, bool vertex_based);
void doDecomposition();
void doDecompositionSingleHull();
@@ -218,7 +258,6 @@ public:
mesh_header_map mMeshHeader;
std::map<LLUUID, U32> mMeshHeaderSize;
std::map<LLUUID, U32> mMeshResourceCost;
class HeaderRequest
{
@@ -310,7 +349,7 @@ public:
virtual void run();
void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod, bool do_lock = true);
bool fetchMeshHeader(const LLVolumeParams& mesh_params);
bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);
@@ -322,8 +361,7 @@ public:
void notifyLoadedMeshes();
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
U32 getResourceCost(const LLUUID& mesh_params);
void loadMeshSkinInfo(const LLUUID& mesh_id);
void loadMeshDecomposition(const LLUUID& mesh_id);
void loadMeshPhysicsShape(const LLUUID& mesh_id);
@@ -343,8 +381,12 @@ public:
};
#if MESH_IMPORT
class LLMeshUploadThread : public LLThread
{
private:
S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request.
public:
class DecompRequest : public LLPhysicsDecomp::Request
{
@@ -374,9 +416,7 @@ public:
LLMutex* mMutex;
LLCurlRequest* mCurlRequest;
S32 mPendingConfirmations;
S32 mPendingUploads;
S32 mPendingCost;
LLVector3 mOrigin;
bool mFinished;
bool mUploadTextures;
@@ -385,46 +425,24 @@ public:
BOOL mDiscarded ;
LLHost mHost;
std::string mUploadObjectAssetCapability;
std::string mNewInventoryCapability;
std::string mWholeModelFeeCapability;
std::string mWholeModelUploadURL;
std::queue<LLMeshUploadData> mUploadQ;
std::queue<LLMeshUploadData> mConfirmedQ;
std::queue<LLModelInstance> mInstanceQ;
std::queue<LLTextureUploadData> mTextureQ;
std::queue<LLTextureUploadData> mConfirmedTextureQ;
std::map<LLViewerFetchedTexture*, LLTextureUploadData> mTextureMap;
LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints);
bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true,
LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
~LLMeshUploadThread();
void uploadTexture(LLTextureUploadData& data);
void doUploadTexture(LLTextureUploadData& data);
void sendCostRequest(LLTextureUploadData& data);
void priceResult(LLTextureUploadData& data, const LLSD& content);
void onTextureUploaded(LLTextureUploadData& data);
void uploadModel(LLMeshUploadData& data);
void sendCostRequest(LLMeshUploadData& data);
void doUploadModel(LLMeshUploadData& data);
void onModelUploaded(LLMeshUploadData& data);
void createObjects(LLMeshUploadData& data);
LLSD createObject(LLModelInstance& instance);
void priceResult(LLMeshUploadData& data, const LLSD& content);
bool finished() { return mFinished; }
virtual void run();
void preStart();
void discard() ;
BOOL isDiscarded();
void generateHulls();
void doWholeModelUpload();
void doIterativeUpload();
void requestWholeModelFee();
void wholeModelToLLSD(LLSD& dest, bool include_textures);
@@ -432,7 +450,17 @@ public:
LLVector3& result_pos,
LLQuaternion& result_rot,
LLVector3& result_scale);
void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
private:
LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
bool mDoUpload; // if FALSE only model data will be requested, otherwise the model will be uploaded
};
#endif //MESH_IMPORT
class LLMeshRepository
{
@@ -465,20 +493,25 @@ public:
S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod);
static S32 getActualMeshLOD(LLSD& header, S32 lod);
U32 calcResourceCost(LLSD& header);
U32 getResourceCost(const LLUUID& mesh_params);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id);
const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj);
LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id);
void fetchPhysicsShape(const LLUUID& mesh_id);
bool hasPhysicsShape(const LLUUID& mesh_id);
void buildHull(const LLVolumeParams& params, S32 detail);
void buildPhysicsMesh(LLModel::Decomposition& decomp);
bool meshUploadEnabled();
bool meshRezEnabled();
LLSD& getMeshHeader(const LLUUID& mesh_id);
#if MESH_IMPORT
void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints);
bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true,
LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
#endif //MESH_IMPORT
S32 getMeshSize(const LLUUID& mesh_id, S32 lod);
@@ -496,7 +529,8 @@ public:
std::vector<LLMeshRepoThread::LODRequest> mPendingRequests;
//list of mesh ids awaiting skin info
std::set<LLUUID> mLoadingSkins;
typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map;
skin_load_map mLoadingSkins;
//list of mesh ids that need to send skin info fetch requests
std::queue<LLUUID> mPendingSkinRequests;
@@ -515,11 +549,15 @@ public:
U32 mMeshThreadCount;
#if MESH_IMPORT
void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header);
#endif //MESH_IMPORT
LLMeshRepoThread* mThread;
#if MESH_IMPORT
std::vector<LLMeshUploadThread*> mUploads;
std::vector<LLMeshUploadThread*> mUploadWaitList;
#endif //MESH_IMPORT
LLPhysicsDecomp* mDecompThread;

View File

@@ -4582,6 +4582,12 @@ void LLViewerObject::adjustAudioGain(const F32 gain)
bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp)
{
#if MESH_ENABLED
if (LLNetworkData::PARAMS_MESH == param_type)
{
param_type = LLNetworkData::PARAMS_SCULPT;
}
#endif //MESH_ENABLED
ExtraParameter* param = getExtraParameterEntryCreate(param_type);
if (param)
{
@@ -4623,7 +4629,7 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
}
default:
{
llinfos << "Unknown param type." << llendl;
llinfos << "Unknown param type. (" << llformat("0x%2x",param_type) << ")" << llendl;
break;
}
};
@@ -5363,3 +5369,20 @@ const LLUUID &LLViewerObject::extractAttachmentItemID()
return getAttachmentItemID();
}
//virtual
LLVOAvatar* LLViewerObject::getAvatar() const
{
if (isAttachment())
{
LLViewerObject* vobj = (LLViewerObject*) getParent();
while (vobj && !vobj->isAvatar())
{
vobj = (LLViewerObject*) vobj->getParent();
}
return (LLVOAvatar*) vobj;
}
return NULL;
}

View File

@@ -63,6 +63,7 @@ class LLWorld;
class LLNameValue;
class LLNetMap;
class LLMessageSystem;
class LLPartSysData;
class LLPrimitive;
class LLPipeline;
class LLTextureEntry;
@@ -73,7 +74,7 @@ class LLViewerPartSourceScript;
class LLViewerRegion;
class LLViewerObjectMedia;
class LLVOInventoryListener;
class LLPartSysData;
class LLVOAvatar;
typedef enum e_object_update_type
{
@@ -172,6 +173,7 @@ public:
void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; }
virtual BOOL isAttachment() const { return FALSE; }
virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment
virtual BOOL isHUDAttachment() const { return FALSE; }
virtual void updateRadius() {};
virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius()
@@ -220,6 +222,9 @@ public:
virtual BOOL isFlexible() const { return FALSE; }
virtual BOOL isSculpted() const { return FALSE; }
#if MESH_ENABLED
virtual BOOL isMesh() const { return FALSE; }
#endif //MESH_ENABLED
// This method returns true if the object is over land owned by
// the agent.

View File

@@ -69,7 +69,7 @@
#include "llspatialpartition.h"
#include "stringize.h"
#include "llviewercontrol.h"
#include "llsdserialize.h"
extern BOOL gNoRender;
@@ -1142,6 +1142,20 @@ void LLViewerRegion::getInfo(LLSD& info)
info["Region"]["Handle"]["y"] = (LLSD::Integer)y;
}
void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features)
{
sim_features = mSimulatorFeatures;
}
void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
{
std::stringstream str;
LLSDSerialize::toPrettyXML(sim_features, str);
llinfos << str.str() << llendl;
mSimulatorFeatures = sim_features;
}
LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp)
{
U32 local_id = objectp->getLocalID();
@@ -1520,6 +1534,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("SendUserReport");
capabilityNames.append("SendUserReportWithScreenshot");
capabilityNames.append("ServerReleaseNotes");
capabilityNames.append("SimulatorFeatures");
capabilityNames.append("SetDisplayName");
capabilityNames.append("StartGroupProposal");
capabilityNames.append("TextureStats");
@@ -1544,6 +1559,42 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr);
}
class SimulatorFeaturesReceived : public LLHTTPClient::Responder
{
LOG_CLASS(SimulatorFeaturesReceived);
public:
SimulatorFeaturesReceived(LLViewerRegion* region)
: mRegion(region)
{ }
void error(U32 statusNum, const std::string& reason)
{
LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL;
}
void result(const LLSD& content)
{
if(!mRegion) //region is removed or responder is not created.
{
return ;
}
mRegion->setSimulatorFeatures(content);
}
static boost::intrusive_ptr<SimulatorFeaturesReceived> build(
LLViewerRegion* region)
{
return boost::intrusive_ptr<SimulatorFeaturesReceived>(
new SimulatorFeaturesReceived(region));
}
private:
LLViewerRegion* mRegion;
};
void LLViewerRegion::setCapability(const std::string& name, const std::string& url)
{
if(name == "EventQueueGet")
@@ -1556,6 +1607,11 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u
{
LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url));
}
else if (name == "SimulatorFeatures")
{
// kick off a request for simulator features
LLHTTPClient::get(url, new SimulatorFeaturesReceived(this));
}
else
{
mImpl->mCapabilities[name] = url;
@@ -1589,6 +1645,21 @@ bool LLViewerRegion::capabilitiesReceived() const
void LLViewerRegion::setCapabilitiesReceived(bool received)
{
mCapabilitiesReceived = received;
// Tell interested parties that we've received capabilities,
// so that they can safely use getCapability().
if (received)
{
mCapabilitiesReceivedSignal(getRegionID());
// This is a single-shot signal. Forget callbacks to save resources.
mCapabilitiesReceivedSignal.disconnect_all_slots();
}
}
boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb)
{
return mCapabilitiesReceivedSignal.connect(cb);
}
void LLViewerRegion::logActiveCapabilities() const
@@ -1633,3 +1704,18 @@ std::string LLViewerRegion::getDescription() const
{
return stringize(*this);
}
#if MESH_ENABLED
bool LLViewerRegion::meshUploadEnabled() const
{
return (mSimulatorFeatures.has("MeshUploadEnabled") &&
mSimulatorFeatures["MeshUploadEnabled"].asBoolean());
}
bool LLViewerRegion::meshRezEnabled() const
{
return (mSimulatorFeatures.has("MeshRezEnabled") &&
mSimulatorFeatures["MeshRezEnabled"].asBoolean());
}
#endif //MESH_ENABLED

View File

@@ -96,6 +96,8 @@ public:
NUM_PARTITIONS
} eObjectPartitions;
typedef boost::signals2::signal<void(const LLUUID& region_id)> caps_received_signal_t;
LLViewerRegion(const U64 &handle,
const LLHost &host,
const U32 surface_grid_width,
@@ -240,6 +242,7 @@ public:
// has region received its final (not seed) capability list?
bool capabilitiesReceived() const;
void setCapabilitiesReceived(bool received);
boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb);
static bool isSpecialCapabilityName(const std::string &name);
void logActiveCapabilities() const;
@@ -279,6 +282,13 @@ public:
void getInfo(LLSD& info);
#if MESH_ENABLED
bool meshRezEnabled() const;
bool meshUploadEnabled() const;
#endif //MESH_ENABLED
void getSimulatorFeatures(LLSD& info);
void setSimulatorFeatures(const LLSD& info);
typedef enum
{
@@ -406,8 +416,11 @@ private:
bool mAlive; // can become false if circuit disconnects
bool mCapabilitiesReceived;
caps_received_signal_t mCapabilitiesReceivedSignal;
BOOL mReleaseNotesRequested;
LLSD mSimulatorFeatures;
};
inline BOOL LLViewerRegion::getAllowDamage() const

View File

@@ -82,7 +82,20 @@ LLGLSLShader gObjectFullbrightShinyProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gObjectFullbrightShinyWaterProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gObjectShinyProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gObjectShinyWaterProgram(LLViewerShaderMgr::SHADER_OBJECT);
#if MESH_ENABLED
//object hardware skinning shaders
LLGLSLShader gSkinnedObjectSimpleProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gSkinnedObjectFullbrightProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gSkinnedObjectFullbrightShinyProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gSkinnedObjectShinySimpleProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gSkinnedObjectSimpleWaterProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gSkinnedObjectFullbrightWaterProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram(LLViewerShaderMgr::SHADER_OBJECT);
LLGLSLShader gSkinnedObjectShinySimpleWaterProgram(LLViewerShaderMgr::SHADER_OBJECT);
#endif //MESH_ENABLED
//environment shaders
LLGLSLShader gTerrainProgram(LLViewerShaderMgr::SHADER_ENVIRONMENT);
LLGLSLShader gTerrainWaterProgram(LLViewerShaderMgr::SHADER_WATER); //note, water.
@@ -110,6 +123,11 @@ LLGLSLShader gDeferredImpostorProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredEdgeProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics
LLGLSLShader gDeferredDiffuseProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList
#if MESH_ENABLED
LLGLSLShader gDeferredSkinnedDiffuseProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredSkinnedBumpProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredSkinnedAlphaProgram(LLViewerShaderMgr::SHADER_DEFERRED);
#endif //MESH_ENABLED
LLGLSLShader gDeferredBumpProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
LLGLSLShader gDeferredTerrainProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList
LLGLSLShader gDeferredTreeProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
@@ -124,6 +142,9 @@ LLGLSLShader gDeferredBlurLightProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredSoftenProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList
LLGLSLShader gDeferredAvatarShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList
#if MESH_ENABLED
LLGLSLShader gDeferredAttachmentShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED);
#endif //MESH_ENABLED
LLGLSLShader gDeferredAlphaProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics
LLGLSLShader gDeferredFullbrightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics
LLGLSLShader gDeferredGIProgram(LLViewerShaderMgr::SHADER_DEFERRED);
@@ -414,11 +435,11 @@ void LLViewerShaderMgr::setShaders()
loadShadersWindLight();
loadShadersEffects();
loadShadersInterface();
#if 0 && LL_DARWIN // force avatar shaders off for mac
mVertexShaderLevel[SHADER_AVATAR] = 0;
sMaxAvatarShaderLevel = 0;
#else
// Load max avatar shaders to set the max level
mVertexShaderLevel[SHADER_AVATAR] = 3;
mMaxAvatarShaderLevel = 3;
if (gSavedSettings.getBOOL("RenderAvatarVP"))
{
BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth");
@@ -461,7 +482,6 @@ void LLViewerShaderMgr::setShaders()
{
gSavedSettings.setBOOL("RenderDeferred", FALSE);
}
#endif
}
else
{
@@ -554,6 +574,9 @@ 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 ) );
#if MESH_ENABLED
shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) );
#endif //MESH_ENABLED
// 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++)
@@ -834,7 +857,47 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredDiffuseProgram.createShader(NULL, NULL);
}
#if MESH_ENABLED
if (success)
{
gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader";
gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true;
gDeferredSkinnedDiffuseProgram.mShaderFiles.clear();
gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredSkinnedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL);
}
if (success)
{
gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader";
gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true;
gDeferredSkinnedBumpProgram.mShaderFiles.clear();
gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredSkinnedBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL);
}
if (success)
{
gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader";
gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true;
gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
}
#endif //MESH_ENABLED
if (success)
{
gDeferredBumpProgram.mName = "Deferred Bump Shader";
@@ -1020,7 +1083,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredAvatarShadowProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
}
if (success)
{
gTerrainProgram.mName = "Deferred Terrain Shader";
@@ -1280,6 +1342,145 @@ BOOL LLViewerShaderMgr::loadShadersObject()
success = gObjectFullbrightShinyWaterProgram.createShader(NULL, &mShinyUniforms);
}
#if MESH_ENABLED
if (mVertexShaderLevel[SHADER_AVATAR] > 0)
{ //load hardware skinned attachment shaders
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)
{
gSkinnedObjectFullbrightProgram.mName = "Skinned Fullbright Shader";
gSkinnedObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true;
gSkinnedObjectFullbrightProgram.mFeatures.hasGamma = true;
gSkinnedObjectFullbrightProgram.mFeatures.hasTransport = true;
gSkinnedObjectFullbrightProgram.mFeatures.isFullbright = true;
gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectFullbrightProgram.mShaderFiles.clear();
gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
gSkinnedObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL);
}
if (success)
{
gSkinnedObjectFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader";
gSkinnedObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true;
gSkinnedObjectFullbrightShinyProgram.mFeatures.hasGamma = true;
gSkinnedObjectFullbrightShinyProgram.mFeatures.hasTransport = true;
gSkinnedObjectFullbrightShinyProgram.mFeatures.isShiny = true;
gSkinnedObjectFullbrightShinyProgram.mFeatures.isFullbright = true;
gSkinnedObjectFullbrightShinyProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear();
gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms);
}
if (success)
{
gSkinnedObjectShinySimpleProgram.mName = "Skinned Shiny Simple Shader";
gSkinnedObjectShinySimpleProgram.mFeatures.calculatesLighting = true;
gSkinnedObjectShinySimpleProgram.mFeatures.calculatesAtmospherics = true;
gSkinnedObjectShinySimpleProgram.mFeatures.hasGamma = true;
gSkinnedObjectShinySimpleProgram.mFeatures.hasAtmospherics = true;
gSkinnedObjectShinySimpleProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectShinySimpleProgram.mFeatures.isShiny = true;
gSkinnedObjectShinySimpleProgram.mShaderFiles.clear();
gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
gSkinnedObjectShinySimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
success = gSkinnedObjectShinySimpleProgram.createShader(NULL, &mShinyUniforms);
}
if (success)
{
gSkinnedObjectSimpleWaterProgram.mName = "Skinned Simple Water Shader";
gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesLighting = true;
gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true;
gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear();
gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gSkinnedObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL);
}
if (success)
{
gSkinnedObjectFullbrightWaterProgram.mName = "Skinned Fullbright Water Shader";
gSkinnedObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true;
gSkinnedObjectFullbrightWaterProgram.mFeatures.hasGamma = true;
gSkinnedObjectFullbrightWaterProgram.mFeatures.hasTransport = true;
gSkinnedObjectFullbrightWaterProgram.mFeatures.isFullbright = true;
gSkinnedObjectFullbrightWaterProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true;
gSkinnedObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear();
gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL);
}
if (success)
{
gSkinnedObjectFullbrightShinyWaterProgram.mName = "Skinned Fullbright Shiny Water Shader";
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true;
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true;
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true;
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true;
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true;
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true;
gSkinnedObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, &mShinyUniforms);
}
if (success)
{
gSkinnedObjectShinySimpleWaterProgram.mName = "Skinned Shiny Simple Water Shader";
gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesLighting = true;
gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesAtmospherics = true;
gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasGamma = true;
gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAtmospherics = true;
gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasObjectSkinning = true;
gSkinnedObjectShinySimpleWaterProgram.mFeatures.isShiny = true;
gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasWaterFog = true;
gSkinnedObjectShinySimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear();
gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, &mShinyUniforms);
}
}
#endif //MESH_ENABLED
if( !success )
{
mVertexShaderLevel[SHADER_OBJECT] = 0;

View File

@@ -319,6 +319,18 @@ extern LLGLSLShader gObjectFullbrightShinyWaterProgram;
extern LLGLSLShader gObjectShinyProgram;
extern LLGLSLShader gObjectShinyWaterProgram;
#if MESH_ENABLED
extern LLGLSLShader gSkinnedObjectSimpleProgram;
extern LLGLSLShader gSkinnedObjectFullbrightProgram;
extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram;
extern LLGLSLShader gSkinnedObjectShinySimpleProgram;
extern LLGLSLShader gSkinnedObjectSimpleWaterProgram;
extern LLGLSLShader gSkinnedObjectFullbrightWaterProgram;
extern LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram;
extern LLGLSLShader gSkinnedObjectShinySimpleWaterProgram;
#endif //MESH_ENABLED
//environment shaders
extern LLGLSLShader gTerrainProgram;
extern LLGLSLShader gTerrainWaterProgram;
@@ -350,6 +362,11 @@ extern LLGLSLShader gDeferredImpostorProgram;
extern LLGLSLShader gDeferredEdgeProgram;
extern LLGLSLShader gDeferredWaterProgram;
extern LLGLSLShader gDeferredDiffuseProgram;
#if MESH_ENABLED
extern LLGLSLShader gDeferredSkinnedDiffuseProgram;
extern LLGLSLShader gDeferredSkinnedBumpProgram;
extern LLGLSLShader gDeferredSkinnedAlphaProgram;
#endif //MESH_ENABLED
extern LLGLSLShader gDeferredBumpProgram;
extern LLGLSLShader gDeferredTerrainProgram;
extern LLGLSLShader gDeferredTreeProgram;
@@ -368,6 +385,9 @@ extern LLGLSLShader gDeferredPostGIProgram;
extern LLGLSLShader gDeferredPostProgram;
extern LLGLSLShader gDeferredPostNoDoFProgram;
extern LLGLSLShader gDeferredAvatarShadowProgram;
#if MESH_ENABLED
extern LLGLSLShader gDeferredAttachmentShadowProgram;
#endif //MESH_ENABLED
extern LLGLSLShader gDeferredAlphaProgram;
extern LLGLSLShader gDeferredFullbrightProgram;
extern LLGLSLShader gDeferredAvatarAlphaProgram;

View File

@@ -725,10 +725,16 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mTexHairColor( NULL ),
mTexEyeColor( NULL ),
mNeedsSkin(FALSE),
#if MESH_ENABLED
mLastSkinTime(0.f),
#endif //MESH_ENABLED
mUpdatePeriod(1),
mFullyLoadedInitialized(FALSE),
mHasBakedHair( FALSE ),
mSupportsAlphaLayers(FALSE),
#if MESH_ENABLED
mHasPelvisOffset( FALSE ),
#endif //MESH_ENABLED
mFirstSetActualBoobGravRan( false ),
mSupportsPhysics( false )
//mFirstSetActualButtGravRan( false ),
@@ -838,6 +844,12 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mRuthTimer.reset();
#if MESH_ENABLED
mPelvisOffset = LLVector3(0.0f,0.0f,0.0f);
mLastPelvisToFoot = 0.0f;
mPelvisFixup = 0.0f;
mLastPelvisFixup = 0.0f;
#endif //MESH_ENABLED
//-------------------------------------------------------------------------
// initialize joint, mesh and shape members
//-------------------------------------------------------------------------
@@ -1527,6 +1539,16 @@ const LLVector3 LLVOAvatar::getRenderPosition() const
}
else if (isRoot() || !mDrawable->getParent())
{
#if MESH_ENABLED
if ( mHasPelvisOffset )
{
//Apply a pelvis fixup (as defined by the avs skin)
LLVector3 pos = mDrawable->getPositionAgent();
pos[VZ] += mPelvisFixup;
return pos;
}
else
#endif //MESH_ENABLED
return mDrawable->getPositionAgent();
}
else
@@ -1624,7 +1646,7 @@ void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
LLDrawable* drawable = attached_object->mDrawable;
if (drawable
#if MESH_ENABLED
&& !drawable->isState(LLDrawable::RIGGED))
&& !drawable->isState(LLDrawable::RIGGED)
#endif //MESH_ENABLED
)
{
@@ -2881,9 +2903,20 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled)
// here we get the approximate head position and set as sound source for the voice symbol
// (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing)
//--------------------------------------------------------------------------------------------
#if MESH_ENABLED
if( !mIsSitting )
{
LLVector3 tagPos = mRoot.getWorldPosition();
tagPos[VZ] -= mPelvisToFoot;
tagPos[VZ] += ( mBodySize[VZ] + 0.125f );
mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos );
}
else
#endif //MESH_ENABLED
{
LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] );
mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset );
}
}//if ( voiceEnabled )
}
@@ -4801,7 +4834,43 @@ void LLVOAvatar::updateHeadOffset()
mHeadOffset = lerp(midEyePt, mHeadOffset, u);
}
}
#if MESH_ENABLED
//------------------------------------------------------------------------
// setPelvisOffset
//------------------------------------------------------------------------
void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup )
{
mHasPelvisOffset = hasOffset;
if ( mHasPelvisOffset )
{
//Store off last pelvis to foot value
mLastPelvisToFoot = mPelvisToFoot;
mPelvisOffset = offsetAmount;
mLastPelvisFixup = mPelvisFixup;
mPelvisFixup = pelvisFixup;
}
}
//------------------------------------------------------------------------
// postPelvisSetRecalc
//------------------------------------------------------------------------
void LLVOAvatar::postPelvisSetRecalc( void )
{
computeBodySize();
mRoot.touch();
mRoot.updateWorldMatrixChildren();
dirtyMesh();
updateHeadOffset();
}
//------------------------------------------------------------------------
// pelisPoke
//------------------------------------------------------------------------
void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount )
{
mHasPelvisOffset = true;
mLastPelvisFixup = mPelvisFixup;
mPelvisFixup = pelvisFixupAmount;
}
#endif //MESH_ENABLED
//------------------------------------------------------------------------
// updateVisibility()
//------------------------------------------------------------------------
@@ -5020,6 +5089,9 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
mMeshLOD[MESH_ID_HAIR]->updateJointGeometry();
}
mNeedsSkin = FALSE;
#if MESH_ENABLED
mLastSkinTime = gFrameTimeSeconds;
#endif //MESH_ENABLED
LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer();
if (vb)
@@ -6006,13 +6078,89 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name )
}
return jointp;
}
#if MESH_ENABLED
//-----------------------------------------------------------------------------
// resetJointPositions
//-----------------------------------------------------------------------------
void LLVOAvatar::resetJointPositions( void )
{
for(S32 i = 0; i < (S32)mNumJoints; ++i)
{
mSkeleton[i].restoreOldXform();
mSkeleton[i].setId( LLUUID::null );
}
mHasPelvisOffset = false;
mPelvisFixup = mLastPelvisFixup;
}
//-----------------------------------------------------------------------------
// resetSpecificJointPosition
//-----------------------------------------------------------------------------
void LLVOAvatar::resetSpecificJointPosition( const std::string& name )
{
LLJoint* pJoint = mRoot.findJoint( name );
if ( pJoint && pJoint->doesJointNeedToBeReset() )
{
pJoint->restoreOldXform();
pJoint->setId( LLUUID::null );
//If we're reseting the pelvis position make sure not to apply offset
if ( name == "mPelvis" )
{
mHasPelvisOffset = false;
}
}
else
{
llinfos<<"Did not find "<< name.c_str()<<llendl;
}
}
//-----------------------------------------------------------------------------
// resetJointPositionsToDefault
//-----------------------------------------------------------------------------
void LLVOAvatar::resetJointPositionsToDefault( void )
{
const LLVector3& avPos = getCharacterPosition();
//Reposition the pelvis
LLJoint* pPelvis = mRoot.findJoint("mPelvis");
if ( pPelvis )
{
pPelvis->setPosition( avPos + pPelvis->getPosition() );
}
else
{
llwarns<<"Can't get pelvis joint."<<llendl;
return;
}
//Subsequent joints are relative to pelvis
for( S32 i = 0; i < (S32)mNumJoints; ++i )
{
LLJoint* pJoint = (LLJoint*)&mSkeleton[i];
if ( pJoint->doesJointNeedToBeReset() )
{
pJoint->setId( LLUUID::null );
//restore joints to default positions, however skip over the pelvis
if ( pJoint && pPelvis != pJoint )
{
pJoint->restoreOldXform();
}
}
}
//make sure we don't apply the joint offset
mHasPelvisOffset = false;
mPelvisFixup = mLastPelvisFixup;
postPelvisSetRecalc();
}
#endif //MESH_ENABLED
//-----------------------------------------------------------------------------
// getCharacterPosition()
//-----------------------------------------------------------------------------
LLVector3 LLVOAvatar::getCharacterPosition()
{
if (mDrawable && mDrawable.notNull())
if (mDrawable.notNull())
{
return mDrawable->getPositionAgent();
}
@@ -7202,7 +7350,7 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )
LLVOVolume* pVObj = pVO->mDrawable->getVOVolume();
if ( pVObj )
{
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID() );
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj );
if ( pSkinData )
{
const int jointCnt = pSkinData->mJointNames.size();

View File

@@ -171,6 +171,11 @@ public:
virtual LLJoint* getJoint(const std::string &name);
virtual LLJoint* getRootJoint() { return &mRoot; }
#if MESH_ENABLED
void resetJointPositions( void );
void resetJointPositionsToDefault( void );
void resetSpecificJointPosition( const std::string& name );
#endif //MESH_ENABLED
virtual const char* getAnimationPrefix() { return "avatar"; }
virtual const LLUUID& getID();
virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset);
@@ -289,7 +294,18 @@ private:
public:
void updateHeadOffset();
F32 getPelvisToFoot() const { return mPelvisToFoot; }
#if MESH_ENABLED
void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ;
bool hasPelvisOffset( void ) { return mHasPelvisOffset; }
void postPelvisSetRecalc( void );
void setPelvisOffset( F32 pelvixFixupAmount );
bool mHasPelvisOffset;
LLVector3 mPelvisOffset;
F32 mLastPelvisToFoot;
F32 mPelvisFixup;
F32 mLastPelvisFixup;
#endif //MESH_ENABLED
LLVector3 mHeadOffset; // current head position
LLViewerJoint mRoot;
protected:
@@ -358,6 +374,10 @@ public:
U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0);
U32 renderRigid();
U32 renderSkinned(EAvatarRenderPass pass);
#if MESH_ENABLED
F32 getLastSkinTime() { return mLastSkinTime; }
U32 renderSkinnedAttachments();
#endif //MESH_ENABLED
U32 renderTransparent(BOOL first_pass);
void renderCollisionVolumes();
static void deleteCachedImages(bool clearAll=true);
@@ -369,6 +389,9 @@ private:
bool shouldAlphaMask();
BOOL mNeedsSkin; // avatar has been animated and verts have not been updated
#if MESH_ENABLED
F32 mLastSkinTime; //value of gFrameTimeSeconds at last skin update
#endif //MESH_ENABLED
S32 mUpdatePeriod;
S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer.

View File

@@ -70,10 +70,11 @@
#include "llmatrix4a.h"
#include "llagent.h"
#if MESH_ENABLED
#include "lldrawpoolavatar.h
#include "lldrawpoolavatar.h"
#include "llmeshrepository.h"
#include "lldatapacker.h"
#include "llvoavatar.h"
#include "llfloatertools.h"
#endif //MESH_ENABLED
#include "llvocache.h"
@@ -755,7 +756,6 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
// 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 = volume_params.getSculptID();
//profile and path params don't matter for meshes
@@ -801,6 +801,8 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
if (is404)
{
setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI));
//render prim proxy when mesh loading attempts give up
volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE);
}
#endif //MESH_ENABLED
if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged)
@@ -992,8 +994,16 @@ BOOL LLVOVolume::calcLOD()
if (mDrawable->isState(LLDrawable::RIGGED))
{
LLVOAvatar* avatar = getAvatar();
distance = avatar->mDrawable->mDistanceWRTCamera;
radius = avatar->getBinRadius();
if(avatar)
{
distance = avatar->mDrawable->mDistanceWRTCamera;
radius = avatar->getBinRadius();
}
else
{
distance = mDrawable->mDistanceWRTCamera;
radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length();
}
}
else
#endif //MESH_ENABLED
@@ -1182,7 +1192,7 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
#if !MESH_ENABLED
LLVolume* volume = getVolume();
#endif //!MESH_ENABLED
for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++)
{
LLFace *face = mDrawable->getFace(i);
if (!face)
@@ -1347,7 +1357,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)
if (mDrawable->isState(LLDrawable::REBUILD_RIGGED))
{
{
LLFastTimer t(FTM_UPDATE_RIGGED_VOLUME);
LLFastTimer t2(LLFastTimer::FTM_UPDATE_RIGGED_VOLUME);
updateRiggedVolume();
}
genBBoxes(FALSE);
@@ -2022,6 +2032,7 @@ BOOL LLVOVolume::isSculpted() const
#if MESH_ENABLED
BOOL LLVOVolume::isMesh() const
{
if (isSculpted())
{
LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
@@ -2452,9 +2463,10 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
#if MESH_ENABLED
if (mDrawable->isState(LLDrawable::RIGGED))
{
if (LLFloater::isVisible(gFloaterTools) && getAvatar()->isSelf())
if (gFloaterTools->getVisible() && getAvatar()->isSelf())
{
gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE);
updateRiggedVolume();
genBBoxes(FALSE);
volume = mRiggedVolume;
transform = false;
}
@@ -2591,7 +2603,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
#if MESH_ENABLED
bool LLVOVolume::treatAsRigged()
{
return LLFloater::isVisible(gFloaterTools) &&
return gFloaterTools->getVisible() &&
isAttachment() &&
getAvatar() &&
getAvatar()->isSelf() &&
@@ -2627,7 +2639,7 @@ void LLVOVolume::updateRiggedVolume()
LLVolume* volume = getVolume();
const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID());
const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID(), this);
if (!skin)
{
@@ -2655,8 +2667,8 @@ void LLVOVolume::updateRiggedVolume()
}
static LLFastTimer::DeclareTimer FTM_SKIN_RIGGED("Skin");
static LLFastTimer::DeclareTimer FTM_RIGGED_OCTREE("Octree");
//static LLFastTimer::DeclareTimer FTM_SKIN_RIGGED("Skin");
//static LLFastTimer::DeclareTimer FTM_RIGGED_OCTREE("Octree");
void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume)
{
@@ -2711,9 +2723,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
LLVector4a* pos = dst_face.mPositions;
{
LLFastTimer t(FTM_SKIN_RIGGED);
LLFastTimer t(LLFastTimer::FTM_SKIN_RIGGED);
for (U32 j = 0; j < dst_face.mNumVertices; ++j)
for (U32 j = 0; j < (U32)dst_face.mNumVertices; ++j)
{
LLMatrix4a final_mat;
final_mat.clear();
@@ -2760,7 +2772,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
min = pos[0];
max = pos[1];
for (U32 j = 1; j < dst_face.mNumVertices; ++j)
for (U32 j = 1; j < (U32)dst_face.mNumVertices; ++j)
{
min.setMin(min, pos[j]);
max.setMax(max, pos[j]);
@@ -2772,7 +2784,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
}
{
LLFastTimer t(FTM_RIGGED_OCTREE);
LLFastTimer t(LLFastTimer::FTM_RIGGED_OCTREE);
delete dst_face.mOctree;
dst_face.mOctree = NULL;
@@ -2864,9 +2876,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
else
{
model_mat = &(drawable->getRegion()->mRenderMatrix);
if (model_mat->isIdentity())
{
model_mat = NULL;
}
}
U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0;
LLViewerTexture* tex = facep->getTexture();
@@ -3030,7 +3045,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
LLVOVolume* vobj = drawablep->getVOVolume();
#if MESH_ENABLED
if (vobj->getVolume() && vobj->getVolume()->isTetrahedron())
if (vobj->getVolume() && vobj->getVolume()->isTetrahedron() || (vobj->isMesh() && !gMeshRepo.meshRezEnabled()))
{
continue;
}
@@ -3044,9 +3059,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
#if MESH_ENABLED
bool rigged = vobj->isAttachment() &&
vobj->isMesh() &&
gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID());
bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic();
gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj);
bool is_rigged = false;
#endif //MESH_ENABLED
@@ -3085,7 +3098,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
if ( pAvatarVO )
{
LLUUID currentId = vobj->getVolume()->getParams().getSculptID();
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId );
const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj );
if ( pSkinData )
{
@@ -3362,8 +3375,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
}
genDrawInfo(group, simple_mask, simple_faces);
genDrawInfo(group, bump_mask, bump_faces);
genDrawInfo(group, fullbright_mask, fullbright_faces);
genDrawInfo(group, bump_mask, bump_faces, FALSE);
genDrawInfo(group, alpha_mask, alpha_faces, TRUE);
if (!LLPipeline::sDelayVBUpdate)

View File

@@ -266,12 +266,6 @@ public:
// Returns 'true' iff the media data for this object is in flight
bool isMediaDataBeingFetched() const;
// Returns the "last fetched" media version, or -1 if not fetched yet
S32 getLastFetchedMediaVersion() const { return mLastFetchedMediaVersion; }
void addMDCImpl() { ++mMDCImplCount; }
void removeMDCImpl() { --mMDCImplCount; }
S32 getMDCImplCount() { return mMDCImplCount; }
//rigged volume update (for raycasting)