Flipped the MESH_ENABLED switch. Added missing components and updated stuff to be closer to mesh-development head.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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 ¶ms_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 ¶ms_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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user