merge
commit
8424ceb20f
|
|
@ -9,6 +9,7 @@ syntax: glob
|
|||
.*.swp
|
||||
#OSX image cache file
|
||||
*.DS_Store
|
||||
*.orig
|
||||
LICENSES
|
||||
indra/.distcc
|
||||
indra/build-darwin-*
|
||||
|
|
|
|||
|
|
@ -35,10 +35,10 @@ if (WINDOWS)
|
|||
# Don't build DLLs.
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /MP"
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /ZI /MDd /MP"
|
||||
CACHE STRING "C++ compiler debug options" FORCE)
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP"
|
||||
"${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /ZI /MD /MP"
|
||||
CACHE STRING "C++ compiler release-with-debug options" FORCE)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE
|
||||
"${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP"
|
||||
|
|
@ -49,11 +49,12 @@ if (WINDOWS)
|
|||
|
||||
add_definitions(
|
||||
/DLL_WINDOWS=1
|
||||
/DDOM_DYNAMIC
|
||||
/DUNICODE
|
||||
/D_UNICODE
|
||||
/GS
|
||||
/TP
|
||||
/W3
|
||||
/W2
|
||||
/c
|
||||
/Zc:forScope
|
||||
/nologo
|
||||
|
|
@ -207,7 +208,7 @@ if (LINUX OR DARWIN)
|
|||
set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")
|
||||
endif (NOT GCC_DISABLE_FATAL_WARNINGS)
|
||||
|
||||
set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual")
|
||||
set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor")
|
||||
|
||||
set(CMAKE_C_FLAGS "${GCC_WARNINGS} ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${GCC_CXX_WARNINGS} ${CMAKE_CXX_FLAGS}")
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ if(WINDOWS)
|
|||
set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-win32")
|
||||
set(vivox_files
|
||||
SLVoice.exe
|
||||
libsndfile-1.dll
|
||||
libsndfile-1.dll
|
||||
vivoxplatform.dll
|
||||
vivoxsdk.dll
|
||||
ortp.dll
|
||||
|
|
@ -38,6 +38,8 @@ if(WINDOWS)
|
|||
libapr-1.dll
|
||||
libaprutil-1.dll
|
||||
libapriconv-1.dll
|
||||
libcollada14dom21.dll
|
||||
glod.dll
|
||||
)
|
||||
|
||||
# *TODO - update this to use LIBS_PREBUILT_DIR and LL_ARCH_DIR variables
|
||||
|
|
@ -48,6 +50,8 @@ if(WINDOWS)
|
|||
libapr-1.dll
|
||||
libaprutil-1.dll
|
||||
libapriconv-1.dll
|
||||
libcollada14dom21.dll
|
||||
glod.dll
|
||||
)
|
||||
|
||||
if(USE_GOOGLE_PERFTOOLS)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,27 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# these should be moved to their own cmake file
|
||||
include(Prebuilt)
|
||||
use_prebuilt_binary(colladadom)
|
||||
use_prebuilt_binary(pcre)
|
||||
use_prebuilt_binary(libxml)
|
||||
|
||||
set(LLPRIMITIVE_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/llprimitive
|
||||
)
|
||||
|
||||
set(LLPRIMITIVE_LIBRARIES llprimitive)
|
||||
if (WINDOWS)
|
||||
set(LLPRIMITIVE_LIBRARIES
|
||||
llprimitive
|
||||
libcollada14dom21
|
||||
)
|
||||
else (WINDOWS)
|
||||
set(LLPRIMITIVE_LIBRARIES
|
||||
llprimitive
|
||||
collada14dom
|
||||
xml2
|
||||
pcrecpp
|
||||
pcre
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
|||
# NOTE: wont have a distributable build unless you add this on the configure line with:
|
||||
# -DCMAKE_OSX_ARCHITECTURES:STRING='i386;ppc'
|
||||
#set(CMAKE_OSX_ARCHITECTURES i386;ppc)
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.4u.sdk)
|
||||
set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk)
|
||||
if (CMAKE_OSX_ARCHITECTURES MATCHES "i386" AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc")
|
||||
set(ARCH universal)
|
||||
else (CMAKE_OSX_ARCHITECTURES MATCHES "i386" AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc")
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ LLAssetDictionary::LLAssetDictionary()
|
|||
addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", FALSE));
|
||||
addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", FALSE));
|
||||
|
||||
addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", FALSE));
|
||||
|
||||
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE));
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -114,8 +114,11 @@ public:
|
|||
|
||||
AT_LINK_FOLDER = 25,
|
||||
// Inventory folder link
|
||||
|
||||
AT_COUNT = 26,
|
||||
|
||||
AT_MESH = 49,
|
||||
// Mesh data in our proprietary SLM format
|
||||
|
||||
AT_COUNT = 50,
|
||||
|
||||
// +*********************************************************+
|
||||
// | TO ADD AN ELEMENT TO THIS ENUM: |
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ public:
|
|||
{
|
||||
U32 n = mVector.size();
|
||||
mIndexMap[k] = n;
|
||||
mVector.resize(n+1);
|
||||
mVector.push_back(Type());
|
||||
llassert(mVector.size() == mIndexMap.size());
|
||||
return mVector[n];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,9 @@ LLFolderDictionary::LLFolderDictionary()
|
|||
addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE));
|
||||
addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE));
|
||||
addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE));
|
||||
|
||||
addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
|
||||
|
||||
addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
|
||||
|
||||
addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
|
||||
|
|
|
|||
|
|
@ -86,9 +86,11 @@ public:
|
|||
FT_OUTFIT = 47,
|
||||
FT_MY_OUTFITS = 48,
|
||||
|
||||
FT_INBOX = 49,
|
||||
FT_MESH = 49,
|
||||
|
||||
FT_COUNT = 50,
|
||||
FT_INBOX = 50,
|
||||
|
||||
FT_COUNT = 51,
|
||||
|
||||
FT_NONE = -1
|
||||
};
|
||||
|
|
|
|||
|
|
@ -62,6 +62,12 @@
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if !LL_DARWIN
|
||||
U32 ll_thread_local sThreadID = 0;
|
||||
#endif
|
||||
|
||||
U32 LLThread::sIDIter = 0;
|
||||
|
||||
//
|
||||
// Handed to the APR thread creation function
|
||||
//
|
||||
|
|
@ -72,10 +78,14 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
|
|||
// Set thread state to running
|
||||
threadp->mStatus = RUNNING;
|
||||
|
||||
#if !LL_DARWIN
|
||||
sThreadID = threadp->mID;
|
||||
#endif
|
||||
|
||||
// Run the user supplied function
|
||||
threadp->run();
|
||||
|
||||
llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl;
|
||||
//llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl;
|
||||
|
||||
// We're done with the run function, this thread is done executing now.
|
||||
threadp->mStatus = STOPPED;
|
||||
|
|
@ -90,6 +100,8 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
|
|||
mAPRThreadp(NULL),
|
||||
mStatus(STOPPED)
|
||||
{
|
||||
mID = ++sIDIter;
|
||||
|
||||
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
|
||||
if (poolp)
|
||||
{
|
||||
|
|
@ -273,7 +285,7 @@ void LLThread::wakeLocked()
|
|||
//============================================================================
|
||||
|
||||
LLMutex::LLMutex(apr_pool_t *poolp) :
|
||||
mAPRMutexp(NULL)
|
||||
mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
|
||||
{
|
||||
//if (poolp)
|
||||
//{
|
||||
|
|
@ -305,7 +317,18 @@ LLMutex::~LLMutex()
|
|||
|
||||
void LLMutex::lock()
|
||||
{
|
||||
#if LL_DARWIN
|
||||
if (mLockingThread == LLThread::currentID())
|
||||
#else
|
||||
if (mLockingThread == sThreadID)
|
||||
#endif
|
||||
{ //redundant lock
|
||||
mCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
apr_thread_mutex_lock(mAPRMutexp);
|
||||
|
||||
#if MUTEX_DEBUG
|
||||
// Have to have the lock before we can access the debug info
|
||||
U32 id = LLThread::currentID();
|
||||
|
|
@ -313,10 +336,22 @@ void LLMutex::lock()
|
|||
llerrs << "Already locked in Thread: " << id << llendl;
|
||||
mIsLocked[id] = TRUE;
|
||||
#endif
|
||||
|
||||
#if LL_DARWIN
|
||||
mLockingThread = LLThread::currentID();
|
||||
#else
|
||||
mLockingThread = sThreadID;
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLMutex::unlock()
|
||||
{
|
||||
if (mCount > 0)
|
||||
{ //not the root unlock
|
||||
mCount--;
|
||||
return;
|
||||
}
|
||||
|
||||
#if MUTEX_DEBUG
|
||||
// Access the debug info while we have the lock
|
||||
U32 id = LLThread::currentID();
|
||||
|
|
@ -324,6 +359,8 @@ void LLMutex::unlock()
|
|||
llerrs << "Not locked in Thread: " << id << llendl;
|
||||
mIsLocked[id] = FALSE;
|
||||
#endif
|
||||
|
||||
mLockingThread = NO_THREAD;
|
||||
apr_thread_mutex_unlock(mAPRMutexp);
|
||||
}
|
||||
|
||||
|
|
@ -341,6 +378,11 @@ bool LLMutex::isLocked()
|
|||
}
|
||||
}
|
||||
|
||||
U32 LLMutex::lockingThread() const
|
||||
{
|
||||
return mLockingThread;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
LLCondition::LLCondition(apr_pool_t *poolp) :
|
||||
|
|
|
|||
|
|
@ -1,263 +1,285 @@
|
|||
/**
|
||||
* @file llthread.h
|
||||
* @brief Base classes for thread, mutex and condition handling.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLTHREAD_H
|
||||
#define LL_LLTHREAD_H
|
||||
|
||||
#include "llapp.h"
|
||||
#include "llapr.h"
|
||||
#include "apr_thread_cond.h"
|
||||
|
||||
class LLThread;
|
||||
class LLMutex;
|
||||
class LLCondition;
|
||||
|
||||
class LL_COMMON_API LLThread
|
||||
{
|
||||
public:
|
||||
typedef enum e_thread_status
|
||||
{
|
||||
STOPPED = 0, // The thread is not running. Not started, or has exited its run function
|
||||
RUNNING = 1, // The thread is currently running
|
||||
QUITTING= 2 // Someone wants this thread to quit
|
||||
} EThreadStatus;
|
||||
|
||||
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
|
||||
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
|
||||
virtual void shutdown(); // stops the thread
|
||||
|
||||
bool isQuitting() const { return (QUITTING == mStatus); }
|
||||
bool isStopped() const { return (STOPPED == mStatus); }
|
||||
|
||||
static U32 currentID(); // Return ID of current thread
|
||||
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
|
||||
|
||||
public:
|
||||
// PAUSE / RESUME functionality. See source code for important usage notes.
|
||||
// Called from MAIN THREAD.
|
||||
void pause();
|
||||
void unpause();
|
||||
bool isPaused() { return isStopped() || mPaused == TRUE; }
|
||||
|
||||
// Cause the thread to wake up and check its condition
|
||||
void wake();
|
||||
|
||||
// Same as above, but to be used when the condition is already locked.
|
||||
void wakeLocked();
|
||||
|
||||
// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
|
||||
void checkPause();
|
||||
|
||||
// this kicks off the apr thread
|
||||
void start(void);
|
||||
|
||||
apr_pool_t *getAPRPool() { return mAPRPoolp; }
|
||||
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
|
||||
|
||||
private:
|
||||
BOOL mPaused;
|
||||
|
||||
// static function passed to APR thread creation routine
|
||||
static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
|
||||
|
||||
protected:
|
||||
std::string mName;
|
||||
LLCondition* mRunCondition;
|
||||
|
||||
apr_thread_t *mAPRThreadp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
EThreadStatus mStatus;
|
||||
|
||||
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
|
||||
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
|
||||
// otherwise it will cause severe memory leaking!!! --bao
|
||||
LLVolatileAPRPool *mLocalAPRFilePoolp ;
|
||||
|
||||
void setQuitting();
|
||||
|
||||
// virtual function overridden by subclass -- this will be called when the thread runs
|
||||
virtual void run(void) = 0;
|
||||
|
||||
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
|
||||
virtual bool runCondition(void);
|
||||
|
||||
// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
|
||||
inline void lockData();
|
||||
inline void unlockData();
|
||||
|
||||
// This is the predicate that decides whether the thread should sleep.
|
||||
// It should only be called with mRunCondition locked, since the virtual runCondition() function may need to access
|
||||
// data structures that are thread-unsafe.
|
||||
bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
|
||||
|
||||
// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
|
||||
// mRunCondition->lock();
|
||||
// if(!shouldSleep())
|
||||
// mRunCondition->signal();
|
||||
// mRunCondition->unlock();
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
|
||||
|
||||
class LL_COMMON_API LLMutex
|
||||
{
|
||||
public:
|
||||
LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
|
||||
~LLMutex();
|
||||
|
||||
void lock(); // blocks
|
||||
void unlock();
|
||||
bool isLocked(); // non-blocking, but does do a lock/unlock so not free
|
||||
|
||||
protected:
|
||||
apr_thread_mutex_t *mAPRMutexp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
#if MUTEX_DEBUG
|
||||
std::map<U32, BOOL> mIsLocked;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
|
||||
class LL_COMMON_API LLCondition : public LLMutex
|
||||
{
|
||||
public:
|
||||
LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
|
||||
~LLCondition();
|
||||
|
||||
void wait(); // blocks
|
||||
void signal();
|
||||
void broadcast();
|
||||
|
||||
protected:
|
||||
apr_thread_cond_t *mAPRCondp;
|
||||
};
|
||||
|
||||
class LLMutexLock
|
||||
{
|
||||
public:
|
||||
LLMutexLock(LLMutex* mutex)
|
||||
{
|
||||
mMutex = mutex;
|
||||
mMutex->lock();
|
||||
}
|
||||
~LLMutexLock()
|
||||
{
|
||||
mMutex->unlock();
|
||||
}
|
||||
private:
|
||||
LLMutex* mMutex;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void LLThread::lockData()
|
||||
{
|
||||
mRunCondition->lock();
|
||||
}
|
||||
|
||||
void LLThread::unlockData()
|
||||
{
|
||||
mRunCondition->unlock();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
// see llmemory.h for LLPointer<> definition
|
||||
|
||||
class LL_COMMON_API LLThreadSafeRefCount
|
||||
{
|
||||
public:
|
||||
static void initThreadSafeRefCount(); // creates sMutex
|
||||
static void cleanupThreadSafeRefCount(); // destroys sMutex
|
||||
|
||||
private:
|
||||
static LLMutex* sMutex;
|
||||
|
||||
private:
|
||||
LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
|
||||
LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
|
||||
|
||||
protected:
|
||||
virtual ~LLThreadSafeRefCount(); // use unref()
|
||||
|
||||
public:
|
||||
LLThreadSafeRefCount();
|
||||
|
||||
void ref()
|
||||
{
|
||||
if (sMutex) sMutex->lock();
|
||||
mRef++;
|
||||
if (sMutex) sMutex->unlock();
|
||||
}
|
||||
|
||||
S32 unref()
|
||||
{
|
||||
llassert(mRef >= 1);
|
||||
if (sMutex) sMutex->lock();
|
||||
S32 res = --mRef;
|
||||
if (sMutex) sMutex->unlock();
|
||||
if (0 == res)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
S32 getNumRefs() const
|
||||
{
|
||||
return mRef;
|
||||
}
|
||||
|
||||
private:
|
||||
S32 mRef;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
// Simple responder for self destructing callbacks
|
||||
// Pure virtual class
|
||||
class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
|
||||
{
|
||||
protected:
|
||||
virtual ~LLResponder();
|
||||
public:
|
||||
virtual void completed(bool success) = 0;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
#endif // LL_LLTHREAD_H
|
||||
/**
|
||||
* @file llthread.h
|
||||
* @brief Base classes for thread, mutex and condition handling.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLTHREAD_H
|
||||
#define LL_LLTHREAD_H
|
||||
|
||||
#include "llapp.h"
|
||||
#include "llapr.h"
|
||||
#include "apr_thread_cond.h"
|
||||
|
||||
class LLThread;
|
||||
class LLMutex;
|
||||
class LLCondition;
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define ll_thread_local __declspec(thread)
|
||||
#else
|
||||
#define ll_thread_local __thread
|
||||
#endif
|
||||
|
||||
class LL_COMMON_API LLThread
|
||||
{
|
||||
private:
|
||||
static U32 sIDIter;
|
||||
|
||||
public:
|
||||
typedef enum e_thread_status
|
||||
{
|
||||
STOPPED = 0, // The thread is not running. Not started, or has exited its run function
|
||||
RUNNING = 1, // The thread is currently running
|
||||
QUITTING= 2 // Someone wants this thread to quit
|
||||
} EThreadStatus;
|
||||
|
||||
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
|
||||
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
|
||||
virtual void shutdown(); // stops the thread
|
||||
|
||||
bool isQuitting() const { return (QUITTING == mStatus); }
|
||||
bool isStopped() const { return (STOPPED == mStatus); }
|
||||
|
||||
static U32 currentID(); // Return ID of current thread
|
||||
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
|
||||
|
||||
public:
|
||||
// PAUSE / RESUME functionality. See source code for important usage notes.
|
||||
// Called from MAIN THREAD.
|
||||
void pause();
|
||||
void unpause();
|
||||
bool isPaused() { return isStopped() || mPaused == TRUE; }
|
||||
|
||||
// Cause the thread to wake up and check its condition
|
||||
void wake();
|
||||
|
||||
// Same as above, but to be used when the condition is already locked.
|
||||
void wakeLocked();
|
||||
|
||||
// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
|
||||
void checkPause();
|
||||
|
||||
// this kicks off the apr thread
|
||||
void start(void);
|
||||
|
||||
apr_pool_t *getAPRPool() { return mAPRPoolp; }
|
||||
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
|
||||
|
||||
U32 getID() const { return mID; }
|
||||
|
||||
private:
|
||||
BOOL mPaused;
|
||||
|
||||
// static function passed to APR thread creation routine
|
||||
static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
|
||||
|
||||
protected:
|
||||
std::string mName;
|
||||
LLCondition* mRunCondition;
|
||||
|
||||
apr_thread_t *mAPRThreadp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
EThreadStatus mStatus;
|
||||
U32 mID;
|
||||
|
||||
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
|
||||
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
|
||||
// otherwise it will cause severe memory leaking!!! --bao
|
||||
LLVolatileAPRPool *mLocalAPRFilePoolp ;
|
||||
|
||||
void setQuitting();
|
||||
|
||||
// virtual function overridden by subclass -- this will be called when the thread runs
|
||||
virtual void run(void) = 0;
|
||||
|
||||
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
|
||||
virtual bool runCondition(void);
|
||||
|
||||
// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
|
||||
inline void lockData();
|
||||
inline void unlockData();
|
||||
|
||||
// This is the predicate that decides whether the thread should sleep.
|
||||
// It should only be called with mRunCondition locked, since the virtual runCondition() function may need to access
|
||||
// data structures that are thread-unsafe.
|
||||
bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
|
||||
|
||||
// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
|
||||
// mRunCondition->lock();
|
||||
// if(!shouldSleep())
|
||||
// mRunCondition->signal();
|
||||
// mRunCondition->unlock();
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
|
||||
|
||||
class LL_COMMON_API LLMutex
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
NO_THREAD = 0xFFFFFFFF
|
||||
} e_locking_thread;
|
||||
|
||||
LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
|
||||
~LLMutex();
|
||||
|
||||
void lock(); // blocks
|
||||
void unlock();
|
||||
bool isLocked(); // non-blocking, but does do a lock/unlock so not free
|
||||
U32 lockingThread() const; //get ID of locking thread
|
||||
|
||||
protected:
|
||||
apr_thread_mutex_t *mAPRMutexp;
|
||||
mutable U32 mCount;
|
||||
mutable U32 mLockingThread;
|
||||
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
|
||||
#if MUTEX_DEBUG
|
||||
std::map<U32, BOOL> mIsLocked;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
|
||||
class LL_COMMON_API LLCondition : public LLMutex
|
||||
{
|
||||
public:
|
||||
LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
|
||||
~LLCondition();
|
||||
|
||||
void wait(); // blocks
|
||||
void signal();
|
||||
void broadcast();
|
||||
|
||||
protected:
|
||||
apr_thread_cond_t *mAPRCondp;
|
||||
};
|
||||
|
||||
class LLMutexLock
|
||||
{
|
||||
public:
|
||||
LLMutexLock(LLMutex* mutex)
|
||||
{
|
||||
mMutex = mutex;
|
||||
mMutex->lock();
|
||||
}
|
||||
~LLMutexLock()
|
||||
{
|
||||
mMutex->unlock();
|
||||
}
|
||||
private:
|
||||
LLMutex* mMutex;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
void LLThread::lockData()
|
||||
{
|
||||
mRunCondition->lock();
|
||||
}
|
||||
|
||||
void LLThread::unlockData()
|
||||
{
|
||||
mRunCondition->unlock();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
// see llmemory.h for LLPointer<> definition
|
||||
|
||||
class LL_COMMON_API LLThreadSafeRefCount
|
||||
{
|
||||
public:
|
||||
static void initThreadSafeRefCount(); // creates sMutex
|
||||
static void cleanupThreadSafeRefCount(); // destroys sMutex
|
||||
|
||||
private:
|
||||
static LLMutex* sMutex;
|
||||
|
||||
private:
|
||||
LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
|
||||
LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
|
||||
|
||||
protected:
|
||||
virtual ~LLThreadSafeRefCount(); // use unref()
|
||||
|
||||
public:
|
||||
LLThreadSafeRefCount();
|
||||
|
||||
void ref()
|
||||
{
|
||||
if (sMutex) sMutex->lock();
|
||||
mRef++;
|
||||
if (sMutex) sMutex->unlock();
|
||||
}
|
||||
|
||||
S32 unref()
|
||||
{
|
||||
llassert(mRef >= 1);
|
||||
if (sMutex) sMutex->lock();
|
||||
S32 res = --mRef;
|
||||
if (sMutex) sMutex->unlock();
|
||||
if (0 == res)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
S32 getNumRefs() const
|
||||
{
|
||||
return mRef;
|
||||
}
|
||||
|
||||
private:
|
||||
S32 mRef;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
// Simple responder for self destructing callbacks
|
||||
// Pure virtual class
|
||||
class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
|
||||
{
|
||||
protected:
|
||||
virtual ~LLResponder();
|
||||
public:
|
||||
virtual void completed(bool success) = 0;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
#endif // LL_LLTHREAD_H
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ enum EDragAndDropType
|
|||
DAD_ANIMATION = 12,
|
||||
DAD_GESTURE = 13,
|
||||
DAD_LINK = 14,
|
||||
DAD_COUNT = 15, // number of types in this enum
|
||||
DAD_MESH = 15,
|
||||
DAD_COUNT = 16, // number of types in this enum
|
||||
};
|
||||
|
||||
// Reasons for drags to be denied.
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ LLInventoryDictionary::LLInventoryDictionary()
|
|||
addEntry(LLInventoryType::IT_WEARABLE, new InventoryEntry("wearable", "wearable", 2, LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART));
|
||||
addEntry(LLInventoryType::IT_ANIMATION, new InventoryEntry("animation", "animation", 1, LLAssetType::AT_ANIMATION));
|
||||
addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE));
|
||||
addEntry(LLInventoryType::IT_MESH, new InventoryEntry("mesh", "mesh", 1, LLAssetType::AT_MESH));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -123,6 +125,33 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
|
|||
|
||||
LLInventoryType::IT_NONE, // AT_LINK
|
||||
LLInventoryType::IT_NONE, // AT_LINK_FOLDER
|
||||
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
LLInventoryType::IT_NONE, // AT_NONE
|
||||
|
||||
LLInventoryType::IT_MESH // AT_MESH
|
||||
};
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -67,7 +67,9 @@ public:
|
|||
IT_WEARABLE = 18,
|
||||
IT_ANIMATION = 19,
|
||||
IT_GESTURE = 20,
|
||||
IT_COUNT = 21,
|
||||
|
||||
IT_MESH = 22,
|
||||
IT_COUNT = 23,
|
||||
|
||||
IT_NONE = -1
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@
|
|||
#include "lldarray.h"
|
||||
#include "llvolume.h"
|
||||
#include "llstl.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
|
||||
#define DEBUG_SILHOUETTE_BINORMALS 0
|
||||
#define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette
|
||||
|
|
@ -1673,7 +1676,9 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge
|
|||
mFaceMask = 0x0;
|
||||
mDetail = detail;
|
||||
mSculptLevel = -2;
|
||||
|
||||
mIsTetrahedron = FALSE;
|
||||
mLODScaleBias.setVec(1,1,1);
|
||||
|
||||
// set defaults
|
||||
if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)
|
||||
{
|
||||
|
|
@ -1688,7 +1693,8 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge
|
|||
mGenerateSingleFace = generate_single_face;
|
||||
|
||||
generate();
|
||||
if (mParams.getSculptID().isNull())
|
||||
|
||||
if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE)
|
||||
{
|
||||
createVolumeFaces();
|
||||
}
|
||||
|
|
@ -1839,6 +1845,482 @@ BOOL LLVolume::generate()
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const
|
||||
{
|
||||
const U8* l = (const U8*) this;
|
||||
const U8* r = (const U8*) &rhs;
|
||||
|
||||
for (U32 i = 0; i < sizeof(VertexData); ++i)
|
||||
{
|
||||
if (l[i] != r[i])
|
||||
{
|
||||
return r[i] < l[i];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const
|
||||
{
|
||||
const U8* l = (const U8*) this;
|
||||
const U8* r = (const U8*) &rhs;
|
||||
|
||||
for (U32 i = 0; i < sizeof(VertexData); ++i)
|
||||
{
|
||||
if (l[i] != r[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const
|
||||
{
|
||||
bool retval = false;
|
||||
if (rhs.mPosition == mPosition && rhs.mTexCoord == mTexCoord)
|
||||
{
|
||||
if (angle_cutoff > 1.f)
|
||||
{
|
||||
retval = (mNormal == rhs.mNormal);
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 cur_angle = rhs.mNormal*mNormal;
|
||||
retval = cur_angle > angle_cutoff;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
BOOL LLVolume::createVolumeFacesFromFile(const std::string& file_name)
|
||||
{
|
||||
std::ifstream is;
|
||||
|
||||
is.open(file_name.c_str(), std::ifstream::in | std::ifstream::binary);
|
||||
|
||||
BOOL success = createVolumeFacesFromStream(is);
|
||||
|
||||
is.close();
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLVolume::createVolumeFacesFromStream(std::istream& is)
|
||||
{
|
||||
mSculptLevel = -1; // default is an error occured
|
||||
|
||||
LLSD header;
|
||||
{
|
||||
if (!LLSDSerialize::deserialize(header, is, 1024*1024*1024))
|
||||
{
|
||||
llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
std::string nm[] =
|
||||
{
|
||||
"lowest_lod",
|
||||
"low_lod",
|
||||
"medium_lod",
|
||||
"high_lod"
|
||||
};
|
||||
|
||||
S32 lod = llclamp((S32) mDetail, 0, 3);
|
||||
|
||||
while (lod < 4 &&
|
||||
(header[nm[lod]]["offset"].asInteger() == -1 ||
|
||||
header[nm[lod]]["size"].asInteger() == 0 ))
|
||||
{
|
||||
++lod;
|
||||
}
|
||||
|
||||
if (lod >= 4)
|
||||
{
|
||||
lod = llclamp((S32) mDetail, 0, 3);
|
||||
|
||||
while (lod >= 0 &&
|
||||
(header[nm[lod]]["offset"].asInteger() == -1 ||
|
||||
header[nm[lod]]["size"].asInteger() == 0) )
|
||||
{
|
||||
--lod;
|
||||
}
|
||||
|
||||
if (lod < 0)
|
||||
{
|
||||
llwarns << "Mesh header missing LOD offsets. Not a valid mesh asset!" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur);
|
||||
|
||||
return unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger());
|
||||
}
|
||||
|
||||
bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
|
||||
{
|
||||
U8* result = NULL;
|
||||
U32 cur_size = 0;
|
||||
|
||||
{
|
||||
//input stream is now pointing at a zlib compressed block of LLSD
|
||||
//decompress block
|
||||
z_stream strm;
|
||||
|
||||
const U32 CHUNK = 65536;
|
||||
|
||||
U8 *in = new U8[size];
|
||||
is.read((char*) in, size);
|
||||
|
||||
U8 out[CHUNK];
|
||||
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = size;
|
||||
strm.next_in = in;
|
||||
|
||||
S32 ret = inflateInit(&strm);
|
||||
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
llerrs << "WTF?" << llendl;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
strm.avail_out = CHUNK;
|
||||
strm.next_out = out;
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
if (ret == Z_STREAM_ERROR)
|
||||
{
|
||||
inflateEnd(&strm);
|
||||
free(result);
|
||||
delete [] in;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case Z_NEED_DICT:
|
||||
ret = Z_DATA_ERROR;
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
inflateEnd(&strm);
|
||||
free(result);
|
||||
delete [] in;
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
U32 have = CHUNK-strm.avail_out;
|
||||
|
||||
result = (U8*) realloc(result, cur_size + have);
|
||||
memcpy(result+cur_size, out, have);
|
||||
cur_size += have;
|
||||
|
||||
} while (strm.avail_out == 0);
|
||||
|
||||
inflateEnd(&strm);
|
||||
delete [] in;
|
||||
|
||||
if (ret != Z_STREAM_END)
|
||||
{
|
||||
free(result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//result now points to the decompressed LLSD block
|
||||
|
||||
LLSD mdl;
|
||||
|
||||
{
|
||||
std::string res_str((char*) result, cur_size);
|
||||
std::istringstream istr(res_str);
|
||||
|
||||
if (!LLSDSerialize::deserialize(mdl, istr, cur_size))
|
||||
{
|
||||
llwarns << "not a valid mesh asset!" << llendl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(result);
|
||||
|
||||
|
||||
{
|
||||
U32 face_count = mdl.size();
|
||||
|
||||
if (face_count == 0)
|
||||
{
|
||||
llerrs << "WTF?" << llendl;
|
||||
}
|
||||
|
||||
mVolumeFaces.resize(face_count);
|
||||
|
||||
for (U32 i = 0; i < face_count; ++i)
|
||||
{
|
||||
LLSD::Binary pos = mdl[i]["Position"];
|
||||
LLSD::Binary norm = mdl[i]["Normal"];
|
||||
LLSD::Binary tc = mdl[i]["TexCoord0"];
|
||||
LLSD::Binary idx = mdl[i]["TriangleList"];
|
||||
|
||||
LLVolumeFace& face = mVolumeFaces[i];
|
||||
|
||||
face.mHasBinormals = false;
|
||||
|
||||
//copy out indices
|
||||
face.mIndices.resize(idx.size()/2);
|
||||
if (idx.empty() || face.mIndices.size() < 3)
|
||||
{ //why is there an empty index list?
|
||||
llerrs <<"WTF?" << llendl;
|
||||
continue;
|
||||
}
|
||||
|
||||
U16* indices = (U16*) &(idx[0]);
|
||||
for (U32 j = 0; j < idx.size()/2; ++j)
|
||||
{
|
||||
face.mIndices[j] = indices[j];
|
||||
}
|
||||
|
||||
//copy out vertices
|
||||
U32 num_verts = pos.size()/(3*2);
|
||||
face.mVertices.resize(num_verts);
|
||||
|
||||
LLVector3 min_pos;
|
||||
LLVector3 max_pos;
|
||||
LLVector2 min_tc;
|
||||
LLVector2 max_tc;
|
||||
|
||||
min_pos.setValue(mdl[i]["PositionDomain"]["Min"]);
|
||||
max_pos.setValue(mdl[i]["PositionDomain"]["Max"]);
|
||||
min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]);
|
||||
max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]);
|
||||
|
||||
LLVector3 pos_range = max_pos - min_pos;
|
||||
LLVector2 tc_range = max_tc - min_tc;
|
||||
|
||||
LLVector3& min = face.mExtents[0];
|
||||
LLVector3& max = face.mExtents[1];
|
||||
|
||||
min = max = LLVector3(0,0,0);
|
||||
|
||||
for (U32 j = 0; j < num_verts; ++j)
|
||||
{
|
||||
U16* v = (U16*) &(pos[j*3*2]);
|
||||
|
||||
face.mVertices[j].mPosition.setVec(
|
||||
(F32) v[0] / 65535.f * pos_range.mV[0] + min_pos.mV[0],
|
||||
(F32) v[1] / 65535.f * pos_range.mV[1] + min_pos.mV[1],
|
||||
(F32) v[2] / 65535.f * pos_range.mV[2] + min_pos.mV[2]);
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
min = max = face.mVertices[j].mPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
update_min_max(min,max,face.mVertices[j].mPosition);
|
||||
}
|
||||
|
||||
U16* n = (U16*) &(norm[j*3*2]);
|
||||
|
||||
face.mVertices[j].mNormal.setVec(
|
||||
(F32) n[0] / 65535.f * 2.f - 1.f,
|
||||
(F32) n[1] / 65535.f * 2.f - 1.f,
|
||||
(F32) n[2] / 65535.f * 2.f - 1.f);
|
||||
|
||||
U16* t = (U16*) &(tc[j*2*2]);
|
||||
|
||||
face.mVertices[j].mTexCoord.setVec(
|
||||
(F32) t[0] / 65535.f * tc_range.mV[0] + min_tc.mV[0],
|
||||
(F32) t[1] / 65535.f * tc_range.mV[1] + min_tc.mV[1]);
|
||||
}
|
||||
|
||||
|
||||
// modifier flags?
|
||||
bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR);
|
||||
bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT);
|
||||
|
||||
|
||||
// translate to actions:
|
||||
bool do_reflect_x = false;
|
||||
bool do_reverse_triangles = false;
|
||||
bool do_invert_normals = false;
|
||||
|
||||
if (do_mirror)
|
||||
{
|
||||
do_reflect_x = true;
|
||||
do_reverse_triangles = !do_reverse_triangles;
|
||||
}
|
||||
|
||||
if (do_invert)
|
||||
{
|
||||
do_invert_normals = true;
|
||||
do_reverse_triangles = !do_reverse_triangles;
|
||||
}
|
||||
|
||||
// now do the work
|
||||
|
||||
if (do_reflect_x)
|
||||
{
|
||||
for (S32 i = 0; i < face.mVertices.size(); i++)
|
||||
{
|
||||
face.mVertices[i].mPosition.mV[VX] *= -1.0f;
|
||||
face.mVertices[i].mNormal.mV[VX] *= -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_invert_normals)
|
||||
{
|
||||
for (S32 i = 0; i < face.mVertices.size(); i++)
|
||||
{
|
||||
face.mVertices[i].mNormal *= -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_reverse_triangles)
|
||||
{
|
||||
for (U32 j = 0; j < face.mIndices.size(); j += 3)
|
||||
{
|
||||
// swap the 2nd and 3rd index
|
||||
S32 swap = face.mIndices[j+1];
|
||||
face.mIndices[j+1] = face.mIndices[j+2];
|
||||
face.mIndices[j+2] = swap;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
mSculptLevel = 0; // success!
|
||||
return true;
|
||||
}
|
||||
|
||||
void tetrahedron_set_normal(LLVolumeFace::VertexData* cv)
|
||||
{
|
||||
LLVector3 nrm = (cv[1].mPosition-cv[0].mPosition)%(cv[2].mPosition-cv[0].mPosition);
|
||||
|
||||
nrm.normVec();
|
||||
|
||||
cv[0].mNormal = nrm;
|
||||
cv[1].mNormal = nrm;
|
||||
cv[2].mNormal = nrm;
|
||||
}
|
||||
|
||||
BOOL LLVolume::isTetrahedron()
|
||||
{
|
||||
return mIsTetrahedron;
|
||||
}
|
||||
|
||||
void LLVolume::makeTetrahedron()
|
||||
{
|
||||
mVolumeFaces.clear();
|
||||
|
||||
LLVolumeFace face;
|
||||
|
||||
F32 x = 0.25f;
|
||||
LLVector3 p[] =
|
||||
{ //unit tetrahedron corners
|
||||
LLVector3(x,x,x),
|
||||
LLVector3(-x,-x,x),
|
||||
LLVector3(-x,x,-x),
|
||||
LLVector3(x,-x,-x)
|
||||
};
|
||||
|
||||
face.mExtents[0].setVec(-x,-x,-x);
|
||||
face.mExtents[1].setVec(x,x,x);
|
||||
|
||||
LLVolumeFace::VertexData cv[3];
|
||||
|
||||
//set texture coordinates
|
||||
cv[0].mTexCoord = LLVector2(0,0);
|
||||
cv[1].mTexCoord = LLVector2(1,0);
|
||||
cv[2].mTexCoord = LLVector2(0.5f, 0.5f*F_SQRT3);
|
||||
|
||||
|
||||
//side 1
|
||||
cv[0].mPosition = p[1];
|
||||
cv[1].mPosition = p[0];
|
||||
cv[2].mPosition = p[2];
|
||||
|
||||
tetrahedron_set_normal(cv);
|
||||
|
||||
face.mVertices.push_back(cv[0]);
|
||||
face.mVertices.push_back(cv[1]);
|
||||
face.mVertices.push_back(cv[2]);
|
||||
|
||||
//side 2
|
||||
cv[0].mPosition = p[3];
|
||||
cv[1].mPosition = p[0];
|
||||
cv[2].mPosition = p[1];
|
||||
|
||||
tetrahedron_set_normal(cv);
|
||||
|
||||
face.mVertices.push_back(cv[0]);
|
||||
face.mVertices.push_back(cv[1]);
|
||||
face.mVertices.push_back(cv[2]);
|
||||
|
||||
//side 3
|
||||
cv[0].mPosition = p[3];
|
||||
cv[1].mPosition = p[1];
|
||||
cv[2].mPosition = p[2];
|
||||
|
||||
tetrahedron_set_normal(cv);
|
||||
|
||||
face.mVertices.push_back(cv[0]);
|
||||
face.mVertices.push_back(cv[1]);
|
||||
face.mVertices.push_back(cv[2]);
|
||||
|
||||
//side 4
|
||||
cv[0].mPosition = p[2];
|
||||
cv[1].mPosition = p[0];
|
||||
cv[2].mPosition = p[3];
|
||||
|
||||
tetrahedron_set_normal(cv);
|
||||
|
||||
face.mVertices.push_back(cv[0]);
|
||||
face.mVertices.push_back(cv[1]);
|
||||
face.mVertices.push_back(cv[2]);
|
||||
|
||||
//set index buffer
|
||||
for (U32 i = 0; i < 12; i++)
|
||||
{
|
||||
face.mIndices.push_back(i);
|
||||
}
|
||||
|
||||
mVolumeFaces.push_back(face);
|
||||
mSculptLevel = 0;
|
||||
mIsTetrahedron = TRUE;
|
||||
}
|
||||
|
||||
void LLVolume::copyVolumeFaces(LLVolume* volume)
|
||||
{
|
||||
mVolumeFaces = volume->mVolumeFaces;
|
||||
mSculptLevel = 0;
|
||||
mIsTetrahedron = FALSE;
|
||||
}
|
||||
|
||||
|
||||
S32 LLVolume::getNumFaces() const
|
||||
{
|
||||
U8 sculpt_type = (mParams.getSculptType() & LL_SCULPT_TYPE_MASK);
|
||||
|
||||
if (sculpt_type == LL_SCULPT_TYPE_MESH)
|
||||
{
|
||||
return LL_SCULPT_MESH_MAX_FACES;
|
||||
}
|
||||
|
||||
return (S32)mProfilep->mFaces.size();
|
||||
}
|
||||
|
||||
|
||||
void LLVolume::createVolumeFaces()
|
||||
{
|
||||
|
|
@ -1864,6 +2346,11 @@ void LLVolume::createVolumeFaces()
|
|||
LLProfile::Face& face = mProfilep->mFaces[i];
|
||||
vf.mBeginS = face.mIndex;
|
||||
vf.mNumS = face.mCount;
|
||||
if (vf.mNumS < 0)
|
||||
{
|
||||
llerrs << "Volume face corruption detected." << llendl;
|
||||
}
|
||||
|
||||
vf.mBeginT = 0;
|
||||
vf.mNumT= getPath().mPath.size();
|
||||
vf.mID = i;
|
||||
|
|
@ -1907,6 +2394,10 @@ void LLVolume::createVolumeFaces()
|
|||
if (face.mFlat && vf.mNumS > 2)
|
||||
{ //flat inner faces have to copy vert normals
|
||||
vf.mNumS = vf.mNumS*2;
|
||||
if (vf.mNumS < 0)
|
||||
{
|
||||
llerrs << "Volume face corruption detected." << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -2198,6 +2689,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components,
|
|||
LLMemType m1(LLMemType::MTYPE_VOLUME);
|
||||
U8 sculpt_type = mParams.getSculptType();
|
||||
|
||||
if (sculpt_type & LL_SCULPT_TYPE_MASK == LL_SCULPT_TYPE_MESH)
|
||||
{
|
||||
llerrs << "WTF?" << llendl;
|
||||
}
|
||||
|
||||
BOOL data_is_empty = FALSE;
|
||||
|
||||
if (sculpt_width == 0 || sculpt_height == 0 || sculpt_components < 3 || sculpt_data == NULL)
|
||||
|
|
@ -2309,7 +2805,6 @@ bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const
|
|||
return mSculptID < params.mSculptID;
|
||||
}
|
||||
|
||||
|
||||
return mSculptType < params.mSculptType;
|
||||
|
||||
|
||||
|
|
@ -3367,6 +3862,20 @@ S32 LLVolume::getNumTriangleIndices() const
|
|||
return count;
|
||||
}
|
||||
|
||||
|
||||
S32 LLVolume::getNumTriangles() const
|
||||
{
|
||||
U32 triangle_count = 0;
|
||||
|
||||
for (S32 i = 0; i < getNumVolumeFaces(); ++i)
|
||||
{
|
||||
triangle_count += getVolumeFace(i).mIndices.size()/3;
|
||||
}
|
||||
|
||||
return triangle_count;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// generateSilhouetteVertices()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -3379,22 +3888,29 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
|||
S32 face_mask)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_VOLUME);
|
||||
|
||||
|
||||
vertices.clear();
|
||||
normals.clear();
|
||||
segments.clear();
|
||||
|
||||
if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
S32 cur_index = 0;
|
||||
//for each face
|
||||
for (face_list_t::iterator iter = mVolumeFaces.begin();
|
||||
iter != mVolumeFaces.end(); ++iter)
|
||||
{
|
||||
const LLVolumeFace& face = *iter;
|
||||
LLVolumeFace& face = *iter;
|
||||
|
||||
if (!(face_mask & (0x1 << cur_index++)))
|
||||
if (!(face_mask & (0x1 << cur_index++)) ||
|
||||
face.mIndices.empty() || face.mEdge.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) {
|
||||
|
||||
}
|
||||
|
|
@ -3594,6 +4110,8 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
|
|||
|
||||
F32 closest_t = 2.f; // must be larger than 1
|
||||
|
||||
end_face = llmin(end_face, getNumVolumeFaces()-1);
|
||||
|
||||
for (S32 i = start_face; i <= end_face; i++)
|
||||
{
|
||||
const LLVolumeFace &face = getVolumeFace((U32)i);
|
||||
|
|
@ -4104,11 +4622,28 @@ BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
LLSD LLVolumeParams::sculptAsLLSD() const
|
||||
{
|
||||
LLSD sd = LLSD();
|
||||
sd["id"] = getSculptID();
|
||||
sd["type"] = getSculptType();
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
bool LLVolumeParams::sculptFromLLSD(LLSD& sd)
|
||||
{
|
||||
setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger());
|
||||
return true;
|
||||
}
|
||||
|
||||
LLSD LLVolumeParams::asLLSD() const
|
||||
{
|
||||
LLSD sd = LLSD();
|
||||
sd["path"] = mPathParams;
|
||||
sd["profile"] = mProfileParams;
|
||||
sd["sculpt"] = sculptAsLLSD();
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
|
|
@ -4116,6 +4651,8 @@ bool LLVolumeParams::fromLLSD(LLSD& sd)
|
|||
{
|
||||
mPathParams.fromLLSD(sd["path"]);
|
||||
mProfileParams.fromLLSD(sd["profile"]);
|
||||
sculptFromLLSD(sd["sculpt"]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -4158,6 +4695,12 @@ const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity
|
|||
// for collison purposes
|
||||
BOOL LLVolumeParams::isConvex() const
|
||||
{
|
||||
if (!getSculptID().isNull())
|
||||
{
|
||||
// can't determine, be safe and say no:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
F32 path_length = mPathParams.getEnd() - mPathParams.getBegin();
|
||||
F32 hollow = mProfileParams.getHollow();
|
||||
|
||||
|
|
@ -4416,6 +4959,61 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)
|
|||
}
|
||||
}
|
||||
|
||||
void LLVolumeFace::optimize(F32 angle_cutoff)
|
||||
{
|
||||
LLVolumeFace new_face;
|
||||
|
||||
VertexMapData::PointMap point_map;
|
||||
|
||||
//remove redundant vertices
|
||||
for (U32 i = 0; i < mIndices.size(); ++i)
|
||||
{
|
||||
U16 index = mIndices[i];
|
||||
|
||||
LLVolumeFace::VertexData cv = mVertices[index];
|
||||
|
||||
BOOL found = FALSE;
|
||||
VertexMapData::PointMap::iterator point_iter = point_map.find(cv.mPosition);
|
||||
if (point_iter != point_map.end())
|
||||
{ //duplicate point might exist
|
||||
for (U32 j = 0; j < point_iter->second.size(); ++j)
|
||||
{
|
||||
LLVolumeFace::VertexData& tv = (point_iter->second)[j];
|
||||
if (tv.compareNormal(cv, angle_cutoff))
|
||||
{
|
||||
found = TRUE;
|
||||
new_face.mIndices.push_back((point_iter->second)[j].mIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
new_face.mVertices.push_back(cv);
|
||||
U16 index = (U16) new_face.mVertices.size()-1;
|
||||
new_face.mIndices.push_back(index);
|
||||
|
||||
VertexMapData d;
|
||||
d.mPosition = cv.mPosition;
|
||||
d.mTexCoord = cv.mTexCoord;
|
||||
d.mNormal = cv.mNormal;
|
||||
d.mIndex = index;
|
||||
if (point_iter != point_map.end())
|
||||
{
|
||||
point_iter->second.push_back(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
point_map[d.mPosition].push_back(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mVertices = new_face.mVertices;
|
||||
mIndices = new_face.mIndices;
|
||||
}
|
||||
|
||||
void LerpPlanarVertex(LLVolumeFace::VertexData& v0,
|
||||
LLVolumeFace::VertexData& v1,
|
||||
LLVolumeFace::VertexData& v2,
|
||||
|
|
@ -5074,6 +5672,42 @@ void LLVolumeFace::createBinormals()
|
|||
}
|
||||
}
|
||||
|
||||
void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat, LLMatrix4& norm_mat)
|
||||
{
|
||||
U16 offset = mVertices.size();
|
||||
|
||||
if (face.mVertices.size() + mVertices.size() > 65536)
|
||||
{
|
||||
llerrs << "Cannot append face -- 16-bit overflow will occur." << llendl;
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < face.mVertices.size(); ++i)
|
||||
{
|
||||
VertexData v = face.mVertices[i];
|
||||
v.mPosition = v.mPosition*mat;
|
||||
v.mNormal = v.mNormal * norm_mat;
|
||||
|
||||
v.mNormal.normalize();
|
||||
|
||||
mVertices.push_back(v);
|
||||
|
||||
if (offset == 0 && i == 0)
|
||||
{
|
||||
mExtents[0] = mExtents[1] = v.mPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
update_min_max(mExtents[0], mExtents[1], v.mPosition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (U32 i = 0; i < face.mIndices.size(); ++i)
|
||||
{
|
||||
mIndices.push_back(face.mIndices[i]+offset);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_VOLUME);
|
||||
|
|
@ -5105,7 +5739,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
|
|||
if (!partial_build)
|
||||
{
|
||||
mIndices.resize(num_indices);
|
||||
mEdge.resize(num_indices);
|
||||
|
||||
if ((volume->getParams().getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)
|
||||
{
|
||||
mEdge.resize(num_indices);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -183,12 +183,15 @@ const U8 LL_SCULPT_TYPE_SPHERE = 1;
|
|||
const U8 LL_SCULPT_TYPE_TORUS = 2;
|
||||
const U8 LL_SCULPT_TYPE_PLANE = 3;
|
||||
const U8 LL_SCULPT_TYPE_CYLINDER = 4;
|
||||
const U8 LL_SCULPT_TYPE_MESH = 5;
|
||||
|
||||
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER;
|
||||
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
|
||||
LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH;
|
||||
|
||||
const U8 LL_SCULPT_FLAG_INVERT = 64;
|
||||
const U8 LL_SCULPT_FLAG_MIRROR = 128;
|
||||
|
||||
const S32 LL_SCULPT_MESH_MAX_FACES = 8;
|
||||
|
||||
class LLProfileParams
|
||||
{
|
||||
|
|
@ -575,6 +578,9 @@ public:
|
|||
BOOL importLegacyStream(std::istream& input_stream);
|
||||
BOOL exportLegacyStream(std::ostream& output_stream) const;
|
||||
|
||||
LLSD sculptAsLLSD() const;
|
||||
bool sculptFromLLSD(LLSD& sd);
|
||||
|
||||
LLSD asLLSD() const;
|
||||
operator LLSD() const { return asLLSD(); }
|
||||
bool fromLLSD(LLSD& sd);
|
||||
|
|
@ -634,7 +640,6 @@ public:
|
|||
const F32& getSkew() const { return mPathParams.getSkew(); }
|
||||
const LLUUID& getSculptID() const { return mSculptID; }
|
||||
const U8& getSculptType() const { return mSculptType; }
|
||||
|
||||
BOOL isConvex() const;
|
||||
|
||||
// 'begin' and 'end' should be in range [0, 1] (they will be clamped)
|
||||
|
|
@ -800,6 +805,8 @@ public:
|
|||
void createBinormals();
|
||||
void makeTriStrip();
|
||||
|
||||
void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform);
|
||||
|
||||
class VertexData
|
||||
{
|
||||
public:
|
||||
|
|
@ -807,8 +814,45 @@ public:
|
|||
LLVector3 mNormal;
|
||||
LLVector3 mBinormal;
|
||||
LLVector2 mTexCoord;
|
||||
|
||||
bool operator<(const VertexData& rhs) const;
|
||||
bool operator==(const VertexData& rhs) const;
|
||||
bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const;
|
||||
};
|
||||
|
||||
class VertexMapData : public LLVolumeFace::VertexData
|
||||
{
|
||||
public:
|
||||
U16 mIndex;
|
||||
|
||||
bool operator==(const LLVolumeFace::VertexData& rhs) const
|
||||
{
|
||||
return mPosition == rhs.mPosition &&
|
||||
mTexCoord == rhs.mTexCoord &&
|
||||
mNormal == rhs.mNormal;
|
||||
}
|
||||
|
||||
struct ComparePosition
|
||||
{
|
||||
bool operator()(const LLVector3& a, const LLVector3& b) const
|
||||
{
|
||||
if (a.mV[0] != b.mV[0])
|
||||
{
|
||||
return a.mV[0] < b.mV[0];
|
||||
}
|
||||
if (a.mV[1] != b.mV[1])
|
||||
{
|
||||
return a.mV[1] < b.mV[1];
|
||||
}
|
||||
return a.mV[2] < b.mV[2];
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<LLVector3, std::vector<VertexMapData>, VertexMapData::ComparePosition > PointMap;
|
||||
};
|
||||
|
||||
void optimize(F32 angle_cutoff = 2.f);
|
||||
|
||||
enum
|
||||
{
|
||||
SINGLE_MASK = 0x0001,
|
||||
|
|
@ -853,8 +897,7 @@ class LLVolume : public LLRefCount
|
|||
{
|
||||
friend class LLVolumeLODGroup;
|
||||
|
||||
private:
|
||||
LLVolume(const LLVolume&); // Don't implement
|
||||
protected:
|
||||
~LLVolume(); // use unref
|
||||
|
||||
public:
|
||||
|
|
@ -876,7 +919,7 @@ public:
|
|||
|
||||
U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); }
|
||||
U8 getPathType() const { return mParams.getPathParams().getCurveType(); }
|
||||
S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); }
|
||||
S32 getNumFaces() const;
|
||||
S32 getNumVolumeFaces() const { return mVolumeFaces.size(); }
|
||||
F32 getDetail() const { return mDetail; }
|
||||
const LLVolumeParams& getParams() const { return mParams; }
|
||||
|
|
@ -898,12 +941,15 @@ public:
|
|||
BOOL isUnique() const { return mUnique; }
|
||||
|
||||
S32 getSculptLevel() const { return mSculptLevel; }
|
||||
|
||||
void setSculptLevel(S32 level) { mSculptLevel = level; }
|
||||
|
||||
S32 *getTriangleIndices(U32 &num_indices) const;
|
||||
|
||||
// returns number of triangle indeces required for path/profile mesh
|
||||
S32 getNumTriangleIndices() const;
|
||||
|
||||
S32 getNumTriangles() const;
|
||||
|
||||
void generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
||||
std::vector<LLVector3> &normals,
|
||||
std::vector<S32> &segments,
|
||||
|
|
@ -948,6 +994,8 @@ public:
|
|||
LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
|
||||
|
||||
void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
|
||||
void copyVolumeFaces(LLVolume* volume);
|
||||
|
||||
private:
|
||||
void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
|
||||
F32 sculptGetSurfaceArea();
|
||||
|
|
@ -958,11 +1006,19 @@ private:
|
|||
protected:
|
||||
BOOL generate();
|
||||
void createVolumeFaces();
|
||||
public:
|
||||
virtual BOOL createVolumeFacesFromFile(const std::string& file_name);
|
||||
virtual BOOL createVolumeFacesFromStream(std::istream& is);
|
||||
virtual bool unpackVolumeFaces(std::istream& is, S32 size);
|
||||
|
||||
virtual void makeTetrahedron();
|
||||
virtual BOOL isTetrahedron();
|
||||
|
||||
protected:
|
||||
BOOL mUnique;
|
||||
F32 mDetail;
|
||||
S32 mSculptLevel;
|
||||
BOOL mIsTetrahedron;
|
||||
|
||||
LLVolumeParams mParams;
|
||||
LLPath *mPathp;
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep)
|
|||
{
|
||||
llassert_always(mLODRefs[i] > 0);
|
||||
mLODRefs[i]--;
|
||||
#if 1 // SJB: Possible opt: keep other lods around
|
||||
#if 0 // SJB: Possible opt: keep other lods around
|
||||
if (!mLODRefs[i])
|
||||
{
|
||||
mVolumeLODs[i] = NULL;
|
||||
|
|
@ -375,6 +375,19 @@ F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail)
|
|||
return mDetailScales[detail];
|
||||
}
|
||||
|
||||
S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail)
|
||||
{
|
||||
for (S32 i = 1; i < 4; i++)
|
||||
{
|
||||
if (mDetailScales[i] > detail)
|
||||
{
|
||||
return i-1;
|
||||
}
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
F32 LLVolumeLODGroup::dump()
|
||||
{
|
||||
F32 usage = 0.f;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ public:
|
|||
static S32 getDetailFromTan(const F32 tan_angle);
|
||||
static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher);
|
||||
static F32 getVolumeScaleFromDetail(const S32 detail);
|
||||
static S32 getVolumeDetailFromScale(F32 scale);
|
||||
|
||||
LLVolume* refLOD(const S32 detail);
|
||||
BOOL derefLOD(LLVolume *volumep);
|
||||
|
|
|
|||
|
|
@ -221,8 +221,33 @@ const LLMatrix4& LLMatrix4::transpose()
|
|||
|
||||
F32 LLMatrix4::determinant() const
|
||||
{
|
||||
llerrs << "Not implemented!" << llendl;
|
||||
return 0.f;
|
||||
F32 value =
|
||||
mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][0] -
|
||||
mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][0] -
|
||||
mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][0] +
|
||||
mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][0] +
|
||||
mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][0] -
|
||||
mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][0] -
|
||||
mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][1] +
|
||||
mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][1] +
|
||||
mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][1] -
|
||||
mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][1] -
|
||||
mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][1] +
|
||||
mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][1] +
|
||||
mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][2] -
|
||||
mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][2] -
|
||||
mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][2] +
|
||||
mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][2] +
|
||||
mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][2] -
|
||||
mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][2] -
|
||||
mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][3] +
|
||||
mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][3] +
|
||||
mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][3] -
|
||||
mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][3] -
|
||||
mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][3] +
|
||||
mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][3];
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Only works for pure orthonormal, homogeneous transform matrices.
|
||||
|
|
@ -428,6 +453,17 @@ const LLMatrix4& LLMatrix4::initRotTrans(const LLQuaternion &q, const LLVector
|
|||
return (*this);
|
||||
}
|
||||
|
||||
const LLMatrix4& LLMatrix4::initScale(const LLVector3 &scale)
|
||||
{
|
||||
setIdentity();
|
||||
|
||||
mMatrix[VX][VX] = scale.mV[VX];
|
||||
mMatrix[VY][VY] = scale.mV[VY];
|
||||
mMatrix[VZ][VZ] = scale.mV[VZ];
|
||||
|
||||
return (*this);
|
||||
}
|
||||
|
||||
const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos)
|
||||
{
|
||||
F32 sx, sy, sz;
|
||||
|
|
@ -648,37 +684,6 @@ const LLMatrix4& LLMatrix4::initMatrix(const LLMatrix3 &mat, const LLVector4 &
|
|||
|
||||
// LLMatrix4 Operators
|
||||
|
||||
|
||||
/* Not implemented to help enforce code consistency with the syntax of
|
||||
row-major notation. This is a Good Thing.
|
||||
LLVector4 operator*(const LLMatrix4 &a, const LLVector4 &b)
|
||||
{
|
||||
// Operate "to the right" on column-vector b
|
||||
LLVector4 vec;
|
||||
vec.mV[VX] = a.mMatrix[VX][VX] * b.mV[VX] +
|
||||
a.mMatrix[VY][VX] * b.mV[VY] +
|
||||
a.mMatrix[VZ][VX] * b.mV[VZ] +
|
||||
a.mMatrix[VW][VX] * b.mV[VW];
|
||||
|
||||
vec.mV[VY] = a.mMatrix[VX][VY] * b.mV[VX] +
|
||||
a.mMatrix[VY][VY] * b.mV[VY] +
|
||||
a.mMatrix[VZ][VY] * b.mV[VZ] +
|
||||
a.mMatrix[VW][VY] * b.mV[VW];
|
||||
|
||||
vec.mV[VZ] = a.mMatrix[VX][VZ] * b.mV[VX] +
|
||||
a.mMatrix[VY][VZ] * b.mV[VY] +
|
||||
a.mMatrix[VZ][VZ] * b.mV[VZ] +
|
||||
a.mMatrix[VW][VZ] * b.mV[VW];
|
||||
|
||||
vec.mV[VW] = a.mMatrix[VX][VW] * b.mV[VX] +
|
||||
a.mMatrix[VY][VW] * b.mV[VY] +
|
||||
a.mMatrix[VZ][VW] * b.mV[VZ] +
|
||||
a.mMatrix[VW][VW] * b.mV[VW];
|
||||
return vec;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b)
|
||||
{
|
||||
// Operate "to the left" on row-vector a
|
||||
|
|
@ -774,6 +779,23 @@ bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool operator<(const LLMatrix4& a, const LLMatrix4 &b)
|
||||
{
|
||||
U32 i, j;
|
||||
for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
|
||||
{
|
||||
for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
|
||||
{
|
||||
if (a.mMatrix[i][j] != b.mMatrix[i][j])
|
||||
{
|
||||
return a.mMatrix[i][j] < b.mMatrix[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const LLMatrix4& operator*=(LLMatrix4 &a, F32 k)
|
||||
{
|
||||
U32 i, j;
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ public:
|
|||
const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation
|
||||
const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos); // Set with Quaternion and position
|
||||
|
||||
const LLMatrix4& initScale(const LLVector3 &scale);
|
||||
|
||||
// Set all
|
||||
const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos);
|
||||
|
|
@ -225,10 +226,7 @@ public:
|
|||
// Operators
|
||||
//
|
||||
|
||||
// Not implemented to enforce code that agrees with symbolic syntax
|
||||
// friend LLVector4 operator*(const LLMatrix4 &a, const LLVector4 &b); // Apply rotation a to vector b
|
||||
|
||||
// friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b
|
||||
// friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b); // Return a * b
|
||||
friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b); // Return transform of vector a by matrix b
|
||||
friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b); // Return full transform of a by matrix b
|
||||
friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b); // Rotates a but does not translate
|
||||
|
|
@ -236,6 +234,7 @@ public:
|
|||
|
||||
friend bool operator==(const LLMatrix4 &a, const LLMatrix4 &b); // Return a == b
|
||||
friend bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b); // Return a != b
|
||||
friend bool operator<(const LLMatrix4 &a, const LLMatrix4& b); // Return a < b
|
||||
|
||||
friend const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b); // Return a + b
|
||||
friend const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b); // Return a - b
|
||||
|
|
|
|||
|
|
@ -115,3 +115,18 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u)
|
|||
a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u,
|
||||
a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u );
|
||||
}
|
||||
|
||||
LLSD LLVector2::getValue() const
|
||||
{
|
||||
LLSD ret;
|
||||
ret[0] = mV[0];
|
||||
ret[1] = mV[1];
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LLVector2::setValue(LLSD& sd)
|
||||
{
|
||||
mV[0] = (F32) sd[0].asReal();
|
||||
mV[1] = (F32) sd[1].asReal();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,9 @@ class LLVector2
|
|||
void set(const LLVector2 &vec); // Sets LLVector2 to vec
|
||||
void set(const F32 *vec); // Sets LLVector2 to vec
|
||||
|
||||
LLSD getValue() const;
|
||||
void setValue(LLSD& sd);
|
||||
|
||||
void setVec(F32 x, F32 y); // deprecated
|
||||
void setVec(const LLVector2 &vec); // deprecated
|
||||
void setVec(const F32 *vec); // deprecated
|
||||
|
|
|
|||
|
|
@ -197,6 +197,28 @@ const LLVector3& LLVector3::rotVec(const LLQuaternion &q)
|
|||
return *this;
|
||||
}
|
||||
|
||||
const LLVector3& LLVector3::transVec(const LLMatrix4& mat)
|
||||
{
|
||||
setVec(
|
||||
mV[VX] * mat.mMatrix[VX][VX] +
|
||||
mV[VY] * mat.mMatrix[VX][VY] +
|
||||
mV[VZ] * mat.mMatrix[VX][VZ] +
|
||||
mat.mMatrix[VX][VW],
|
||||
|
||||
mV[VX] * mat.mMatrix[VY][VX] +
|
||||
mV[VY] * mat.mMatrix[VY][VY] +
|
||||
mV[VZ] * mat.mMatrix[VY][VZ] +
|
||||
mat.mMatrix[VY][VW],
|
||||
|
||||
mV[VX] * mat.mMatrix[VZ][VX] +
|
||||
mV[VY] * mat.mMatrix[VZ][VY] +
|
||||
mV[VZ] * mat.mMatrix[VZ][VZ] +
|
||||
mat.mMatrix[VZ][VW]);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec)
|
||||
{
|
||||
if ( !vec.isExactlyZero() && angle )
|
||||
|
|
|
|||
|
|
@ -36,10 +36,12 @@
|
|||
#include "llerror.h"
|
||||
#include "llmath.h"
|
||||
|
||||
|
||||
#include "llsd.h"
|
||||
class LLVector2;
|
||||
class LLVector4;
|
||||
class LLMatrix3;
|
||||
class LLMatrix4;
|
||||
class LLVector3d;
|
||||
class LLQuaternion;
|
||||
|
||||
|
|
@ -115,6 +117,7 @@ class LLVector3
|
|||
const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians
|
||||
const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
|
||||
const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
|
||||
const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v)
|
||||
|
||||
const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec
|
||||
LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ class LLColor4
|
|||
|
||||
const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4
|
||||
|
||||
bool operator<(const LLColor4& rhs) const;
|
||||
friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a
|
||||
friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b
|
||||
friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b
|
||||
|
|
@ -595,6 +596,23 @@ inline LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u)
|
|||
a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u);
|
||||
}
|
||||
|
||||
inline bool LLColor4::operator<(const LLColor4& rhs) const
|
||||
{
|
||||
if (mV[0] != rhs.mV[0])
|
||||
{
|
||||
return mV[0] < rhs.mV[0];
|
||||
}
|
||||
if (mV[1] != rhs.mV[1])
|
||||
{
|
||||
return mV[1] < rhs.mV[1];
|
||||
}
|
||||
if (mV[2] != rhs.mV[2])
|
||||
{
|
||||
return mV[2] < rhs.mV[2];
|
||||
}
|
||||
|
||||
return mV[3] < rhs.mV[3];
|
||||
}
|
||||
|
||||
void LLColor4::clamp()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -505,7 +505,7 @@ void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType at
|
|||
tpvf.setAsset(uuid, atype);
|
||||
tpvf.setCallback(downloadCompleteCallback, req);
|
||||
|
||||
llinfos << "Starting transfer for " << uuid << llendl;
|
||||
//llinfos << "Starting transfer for " << uuid << llendl;
|
||||
LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET);
|
||||
ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
#include "llstl.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llthread.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
|
|
@ -256,7 +257,12 @@ public:
|
|||
|
||||
void resetState();
|
||||
|
||||
static CURL* allocEasyHandle();
|
||||
static void releaseEasyHandle(CURL* handle);
|
||||
|
||||
private:
|
||||
friend class LLCurl;
|
||||
|
||||
CURL* mCurlEasyHandle;
|
||||
struct curl_slist* mHeaders;
|
||||
|
||||
|
|
@ -271,8 +277,62 @@ private:
|
|||
std::vector<char*> mStrings;
|
||||
|
||||
ResponderPtr mResponder;
|
||||
|
||||
static std::set<CURL*> sFreeHandles;
|
||||
static std::set<CURL*> sActiveHandles;
|
||||
static LLMutex* sHandleMutex;
|
||||
};
|
||||
|
||||
std::set<CURL*> LLCurl::Easy::sFreeHandles;
|
||||
std::set<CURL*> LLCurl::Easy::sActiveHandles;
|
||||
LLMutex* LLCurl::Easy::sHandleMutex = NULL;
|
||||
|
||||
|
||||
//static
|
||||
CURL* LLCurl::Easy::allocEasyHandle()
|
||||
{
|
||||
CURL* ret = NULL;
|
||||
LLMutexLock lock(sHandleMutex);
|
||||
if (sFreeHandles.empty())
|
||||
{
|
||||
ret = curl_easy_init();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = *(sFreeHandles.begin());
|
||||
sFreeHandles.erase(ret);
|
||||
curl_easy_reset(ret);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
{
|
||||
sActiveHandles.insert(ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLCurl::Easy::releaseEasyHandle(CURL* handle)
|
||||
{
|
||||
if (!handle)
|
||||
{
|
||||
llerrs << "handle cannot be NULL!" << llendl;
|
||||
}
|
||||
|
||||
LLMutexLock lock(sHandleMutex);
|
||||
|
||||
if (sActiveHandles.find(handle) != sActiveHandles.end())
|
||||
{
|
||||
sActiveHandles.erase(handle);
|
||||
sFreeHandles.insert(handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
llerrs << "Invalid handle." << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
LLCurl::Easy::Easy()
|
||||
: mHeaders(NULL),
|
||||
mCurlEasyHandle(NULL)
|
||||
|
|
@ -283,25 +343,27 @@ LLCurl::Easy::Easy()
|
|||
LLCurl::Easy* LLCurl::Easy::getEasy()
|
||||
{
|
||||
Easy* easy = new Easy();
|
||||
easy->mCurlEasyHandle = curl_easy_init();
|
||||
easy->mCurlEasyHandle = allocEasyHandle();
|
||||
|
||||
if (!easy->mCurlEasyHandle)
|
||||
{
|
||||
// this can happen if we have too many open files (fails in c-ares/ares_init.c)
|
||||
llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
|
||||
llwarns << "allocEasyHandle() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
|
||||
delete easy;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set no DMS caching as default for all easy handles. This prevents them adopting a
|
||||
// set no DNS caching as default for all easy handles. This prevents them adopting a
|
||||
// multi handles cache if they are added to one.
|
||||
curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
|
||||
|
||||
++gCurlEasyCount;
|
||||
return easy;
|
||||
}
|
||||
|
||||
LLCurl::Easy::~Easy()
|
||||
{
|
||||
curl_easy_cleanup(mCurlEasyHandle);
|
||||
releaseEasyHandle(mCurlEasyHandle);
|
||||
--gCurlEasyCount;
|
||||
curl_slist_free_all(mHeaders);
|
||||
for_each(mStrings.begin(), mStrings.end(), DeletePointerArray());
|
||||
|
|
@ -379,6 +441,7 @@ U32 LLCurl::Easy::report(CURLcode code)
|
|||
{
|
||||
responseCode = 499;
|
||||
responseReason = strerror(code) + " : " + mErrorBuffer;
|
||||
setopt(CURLOPT_FRESH_CONNECT, TRUE);
|
||||
}
|
||||
|
||||
if (mResponder)
|
||||
|
|
@ -465,7 +528,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,
|
|||
|
||||
if (post) setoptString(CURLOPT_ENCODING, "");
|
||||
|
||||
// setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
|
||||
//setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
|
||||
setopt(CURLOPT_NOSIGNAL, 1);
|
||||
|
||||
mOutput.reset(new LLBufferArray);
|
||||
|
|
@ -482,7 +545,10 @@ void LLCurl::Easy::prepRequest(const std::string& url,
|
|||
setCA();
|
||||
|
||||
setopt(CURLOPT_SSL_VERIFYPEER, LLCurl::getSSLVerify());
|
||||
setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify()? 2 : 0);
|
||||
//setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify()? 2 : 0);
|
||||
|
||||
//don't verify host name so urls with scrubbed host names will work (improves DNS performance)
|
||||
setopt(CURLOPT_SSL_VERIFYHOST, 0);
|
||||
setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
|
||||
|
||||
setoptString(CURLOPT_URL, url);
|
||||
|
|
@ -543,6 +609,7 @@ LLCurl::Multi::Multi()
|
|||
mErrorCount(0)
|
||||
{
|
||||
mCurlMultiHandle = curl_multi_init();
|
||||
|
||||
if (!mCurlMultiHandle)
|
||||
{
|
||||
llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl;
|
||||
|
|
@ -710,6 +777,7 @@ LLCurlRequest::LLCurlRequest() :
|
|||
mActiveRequestCount(0)
|
||||
{
|
||||
mThreadID = LLThread::currentID();
|
||||
mProcessing = FALSE;
|
||||
}
|
||||
|
||||
LLCurlRequest::~LLCurlRequest()
|
||||
|
|
@ -744,6 +812,11 @@ LLCurl::Easy* LLCurlRequest::allocEasy()
|
|||
bool LLCurlRequest::addEasy(LLCurl::Easy* easy)
|
||||
{
|
||||
llassert_always(mActiveMulti);
|
||||
|
||||
if (mProcessing)
|
||||
{
|
||||
llerrs << "Posting to a LLCurlRequest instance from within a responder is not allowed (causes DNS timeouts)." << llendl;
|
||||
}
|
||||
bool res = mActiveMulti->addEasy(easy);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -801,12 +874,41 @@ bool LLCurlRequest::post(const std::string& url,
|
|||
bool res = addEasy(easy);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool LLCurlRequest::post(const std::string& url,
|
||||
const headers_t& headers,
|
||||
const std::string& data,
|
||||
LLCurl::ResponderPtr responder)
|
||||
{
|
||||
LLCurl::Easy* easy = allocEasy();
|
||||
if (!easy)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
easy->prepRequest(url, headers, responder);
|
||||
|
||||
easy->getInput().write(data.data(), data.size());
|
||||
S32 bytes = easy->getInput().str().length();
|
||||
|
||||
easy->setopt(CURLOPT_POST, 1);
|
||||
easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL);
|
||||
easy->setopt(CURLOPT_POSTFIELDSIZE, bytes);
|
||||
|
||||
easy->slist_append("Content-Type: application/octet-stream");
|
||||
easy->setHeaders();
|
||||
|
||||
lldebugs << "POSTING: " << bytes << " bytes." << llendl;
|
||||
bool res = addEasy(easy);
|
||||
return res;
|
||||
}
|
||||
|
||||
// Note: call once per frame
|
||||
S32 LLCurlRequest::process()
|
||||
{
|
||||
llassert_always(mThreadID == LLThread::currentID());
|
||||
S32 res = 0;
|
||||
|
||||
mProcessing = TRUE;
|
||||
for (curlmulti_set_t::iterator iter = mMultiSet.begin();
|
||||
iter != mMultiSet.end(); )
|
||||
{
|
||||
|
|
@ -820,6 +922,7 @@ S32 LLCurlRequest::process()
|
|||
delete multi;
|
||||
}
|
||||
}
|
||||
mProcessing = FALSE;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -1042,6 +1145,8 @@ void LLCurl::initClass()
|
|||
// - http://curl.haxx.se/libcurl/c/curl_global_init.html
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
Easy::sHandleMutex = new LLMutex(NULL);
|
||||
|
||||
#if SAFE_SSL
|
||||
S32 mutex_count = CRYPTO_num_locks();
|
||||
for (S32 i=0; i<mutex_count; i++)
|
||||
|
|
@ -1059,5 +1164,22 @@ void LLCurl::cleanupClass()
|
|||
CRYPTO_set_locking_callback(NULL);
|
||||
for_each(sSSLMutex.begin(), sSSLMutex.end(), DeletePointer());
|
||||
#endif
|
||||
|
||||
delete Easy::sHandleMutex;
|
||||
Easy::sHandleMutex = NULL;
|
||||
|
||||
for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)
|
||||
{
|
||||
CURL* curl = *iter;
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
Easy::sFreeHandles.clear();
|
||||
|
||||
if (!Easy::sActiveHandles.empty())
|
||||
{
|
||||
llerrs << "CURL easy handles not cleaned up on shutdown!" << llendl;
|
||||
}
|
||||
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,6 +213,8 @@ public:
|
|||
void get(const std::string& url, LLCurl::ResponderPtr responder);
|
||||
bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder);
|
||||
bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder);
|
||||
bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder);
|
||||
|
||||
S32 process();
|
||||
S32 getQueued();
|
||||
|
||||
|
|
@ -226,6 +228,7 @@ private:
|
|||
curlmulti_set_t mMultiSet;
|
||||
LLCurl::Multi* mActiveMulti;
|
||||
S32 mActiveRequestCount;
|
||||
BOOL mProcessing;
|
||||
U32 mThreadID; // debug
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ namespace
|
|||
fileBuffer = new U8 [fileSize];
|
||||
vfile.read(fileBuffer, fileSize);
|
||||
ostream.write((char*)fileBuffer, fileSize);
|
||||
delete [] fileBuffer;
|
||||
eos = true;
|
||||
return STATUS_DONE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -444,13 +444,13 @@ void LLPumpIO::pump()
|
|||
pump(DEFAULT_POLL_TIMEOUT);
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
|
||||
static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO");
|
||||
|
||||
//timeout is in microseconds
|
||||
void LLPumpIO::pump(const S32& poll_timeout)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
LLFastTimer t1(FTM_PUMP);
|
||||
LLFastTimer t1(FTM_PUMP_IO);
|
||||
//llinfos << "LLPumpIO::pump()" << llendl;
|
||||
|
||||
// Run any pending runners.
|
||||
|
|
@ -778,6 +778,8 @@ bool LLPumpIO::respond(
|
|||
return true;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_PUMP_CALLBACK_CHAIN("Chain");
|
||||
|
||||
void LLPumpIO::callback()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
|
|
@ -799,6 +801,7 @@ void LLPumpIO::callback()
|
|||
callbacks_t::iterator end = mCallbacks.end();
|
||||
for(; it != end; ++it)
|
||||
{
|
||||
LLFastTimer t(FTM_PUMP_CALLBACK_CHAIN);
|
||||
// it's always the first and last time for respone chains
|
||||
(*it).mHead = (*it).mChainLinks.begin();
|
||||
(*it).mInit = true;
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **)
|
|||
}
|
||||
}
|
||||
|
||||
llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl;
|
||||
//llinfos << "Receiving " << transfer_id << ", size " << size << " bytes" << llendl;
|
||||
ttp->setSize(size);
|
||||
ttp->setGotInfo(TRUE);
|
||||
|
||||
|
|
|
|||
|
|
@ -273,6 +273,7 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
|
|||
case LLAssetType::AT_BODYPART:
|
||||
case LLAssetType::AT_ANIMATION:
|
||||
case LLAssetType::AT_GESTURE:
|
||||
case LLAssetType::AT_MESH:
|
||||
rv = true;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -297,6 +298,7 @@ bool is_asset_id_knowable(LLAssetType::EType type)
|
|||
case LLAssetType::AT_GESTURE:
|
||||
case LLAssetType::AT_LINK:
|
||||
case LLAssetType::AT_LINK_FOLDER:
|
||||
case LLAssetType::AT_MESH:
|
||||
rv = true;
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -13,11 +13,14 @@ include_directories(
|
|||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLMESSAGE_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
${LIBS_PREBUILT_DIR}/include/collada
|
||||
${LIBS_PREBUILT_DIR}/include/collada/1.4
|
||||
)
|
||||
|
||||
set(llprimitive_SOURCE_FILES
|
||||
llmaterialtable.cpp
|
||||
llmediaentry.cpp
|
||||
llmodel.cpp
|
||||
llprimitive.cpp
|
||||
llprimtexturelist.cpp
|
||||
lltextureanim.cpp
|
||||
|
|
@ -34,6 +37,7 @@ set(llprimitive_HEADER_FILES
|
|||
legacy_object_types.h
|
||||
llmaterialtable.h
|
||||
llmediaentry.h
|
||||
llmodel.h
|
||||
llprimitive.h
|
||||
llprimtexturelist.h
|
||||
lltextureanim.h
|
||||
|
|
|
|||
|
|
@ -744,7 +744,11 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
|
|||
setNumTEs(mVolumep->getNumFaces());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// #if 0'd out by davep
|
||||
// this is a lot of cruft to set texture entry values that just stay the same for LOD switch
|
||||
// or immediately get overridden by an object update message, also crashes occasionally
|
||||
U32 old_face_mask = mVolumep->mFaceMask;
|
||||
|
||||
S32 face_bit = 0;
|
||||
|
|
@ -942,6 +946,13 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai
|
|||
setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit])));
|
||||
}
|
||||
}
|
||||
#else
|
||||
// build the new object
|
||||
sVolumeManager->unrefVolume(mVolumep);
|
||||
mVolumep = volumep;
|
||||
|
||||
setNumTEs(mVolumep->getNumFaces());
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1084,7 +1095,7 @@ BOOL LLPrimitive::packTEMessage(LLMessageSystem *mesgsys) const
|
|||
U8 packed_buffer[MAX_TE_BUFFER];
|
||||
U8 *cur_ptr = packed_buffer;
|
||||
|
||||
S32 last_face_index = getNumTEs() - 1;
|
||||
S32 last_face_index = llmin((U32) getNumTEs(), MAX_TES) - 1;
|
||||
|
||||
if (last_face_index > -1)
|
||||
{
|
||||
|
|
@ -1365,7 +1376,7 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
|
|||
return retval;
|
||||
}
|
||||
|
||||
face_count = getNumTEs();
|
||||
face_count = llmin((U32) getNumTEs(), MAX_TES);
|
||||
U32 i;
|
||||
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID);
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ public:
|
|||
|
||||
void setLightTexture(const LLUUID& id) { mLightTexture = id; }
|
||||
LLUUID getLightTexture() const { return mLightTexture; }
|
||||
bool isLightSpotlight() const { return mLightTexture.notNull(); }
|
||||
void setParams(const LLVector3& params) { mParams = params; }
|
||||
LLVector3 getParams() const { return mParams; }
|
||||
|
||||
|
|
@ -328,7 +329,7 @@ public:
|
|||
const LLVolume *getVolumeConst() const { return mVolumep; } // HACK for Windoze confusion about ostream operator in LLVolume
|
||||
LLVolume *getVolume() const { return mVolumep; }
|
||||
virtual BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false);
|
||||
|
||||
|
||||
// Modify texture entry properties
|
||||
inline BOOL validTE(const U8 te_num) const;
|
||||
LLTextureEntry* getTE(const U8 te_num) const;
|
||||
|
|
|
|||
|
|
@ -247,7 +247,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
const LLFontGlyphInfo* next_glyph = NULL;
|
||||
|
||||
for (i = begin_offset; i < begin_offset + length; i++)
|
||||
|
|
|
|||
|
|
@ -185,6 +185,9 @@ PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT =
|
|||
// GL_EXT_framebuffer_blit
|
||||
PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL;
|
||||
|
||||
// GL_EXT_blend_func_separate
|
||||
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
|
||||
|
||||
// GL_ARB_draw_buffers
|
||||
PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL;
|
||||
|
||||
|
|
@ -324,6 +327,7 @@ LLGLManager::LLGLManager() :
|
|||
mHasCompressedTextures(FALSE),
|
||||
mHasFramebufferObject(FALSE),
|
||||
mHasFramebufferMultisample(FALSE),
|
||||
mHasBlendFuncSeparate(FALSE),
|
||||
|
||||
mHasVertexBufferObject(FALSE),
|
||||
mHasPBuffer(FALSE),
|
||||
|
|
@ -632,6 +636,11 @@ void LLGLManager::initExtensions()
|
|||
mHasDrawBuffers = TRUE;
|
||||
#else
|
||||
mHasDrawBuffers = FALSE;
|
||||
# endif
|
||||
# if GL_EXT_blend_func_separate
|
||||
mHasBlendFuncSeparate = TRUE;
|
||||
#else
|
||||
mHasBlendFuncSeparate = FALSE;
|
||||
# endif
|
||||
mHasMipMapGeneration = FALSE;
|
||||
mHasSeparateSpecularColor = FALSE;
|
||||
|
|
@ -659,6 +668,7 @@ void LLGLManager::initExtensions()
|
|||
&& ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
|
||||
mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts);
|
||||
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
|
||||
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
|
||||
mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
|
||||
#if !LL_DARWIN
|
||||
mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
|
||||
|
|
@ -682,6 +692,7 @@ void LLGLManager::initExtensions()
|
|||
mHasFramebufferObject = FALSE;
|
||||
mHasFramebufferMultisample = FALSE;
|
||||
mHasDrawBuffers = FALSE;
|
||||
mHasBlendFuncSeparate = FALSE;
|
||||
mHasMipMapGeneration = FALSE;
|
||||
mHasSeparateSpecularColor = FALSE;
|
||||
mHasAnisotropic = FALSE;
|
||||
|
|
@ -706,6 +717,7 @@ void LLGLManager::initExtensions()
|
|||
mHasShaderObjects = FALSE;
|
||||
mHasVertexShader = FALSE;
|
||||
mHasFragmentShader = FALSE;
|
||||
mHasBlendFuncSeparate = FALSE;
|
||||
LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL;
|
||||
}
|
||||
if (getenv("LL_GL_BLACKLIST")) /* Flawfinder: ignore */
|
||||
|
|
@ -734,7 +746,8 @@ void LLGLManager::initExtensions()
|
|||
if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S
|
||||
if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE;
|
||||
if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE;
|
||||
|
||||
if (strchr(blacklist,'u')) mHasBlendFuncSeparate = FALSE;//S
|
||||
|
||||
}
|
||||
#endif // LL_LINUX || LL_SOLARIS
|
||||
|
||||
|
|
@ -782,6 +795,14 @@ void LLGLManager::initExtensions()
|
|||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_fragment_shader" << LL_ENDL;
|
||||
}
|
||||
if (!mHasBlendFuncSeparate)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_blend_func_separate" << LL_ENDL;
|
||||
}
|
||||
if (!mHasDrawBuffers)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_draw_buffers" << LL_ENDL;
|
||||
}
|
||||
|
||||
// Disable certain things due to known bugs
|
||||
if (mIsIntel && mHasMipMapGeneration)
|
||||
|
|
@ -852,6 +873,10 @@ void LLGLManager::initExtensions()
|
|||
{
|
||||
glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB");
|
||||
}
|
||||
if (mHasBlendFuncSeparate)
|
||||
{
|
||||
glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT");
|
||||
}
|
||||
#if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS
|
||||
// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
|
||||
glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ public:
|
|||
BOOL mHasCompressedTextures;
|
||||
BOOL mHasFramebufferObject;
|
||||
BOOL mHasFramebufferMultisample;
|
||||
BOOL mHasBlendFuncSeparate;
|
||||
|
||||
// ARB Extensions
|
||||
BOOL mHasVertexBufferObject;
|
||||
|
|
|
|||
|
|
@ -216,6 +216,9 @@ extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;
|
|||
|
||||
extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
|
||||
|
||||
//GL_EXT_blend_func_separate
|
||||
extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
|
||||
|
||||
//GL_EXT_framebuffer_object
|
||||
extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
|
||||
extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
|
||||
|
|
@ -249,7 +252,10 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
|
|||
# include "GL/glh_extensions.h"
|
||||
# undef __APPLE__
|
||||
|
||||
#elif LL_LINUX
|
||||
#elif LL_LINUX
|
||||
//----------------------------------------------------------------------------
|
||||
// LL_LINUX
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linux, MESA headers, but not necessarily assuming MESA runtime.
|
||||
// quotes so we get libraries/.../GL/ version
|
||||
|
|
@ -285,6 +291,7 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
|
|||
# define LL_LINUX_NV_GL_HEADERS 0
|
||||
#endif // LL_LINUX && defined(WINGDIAPI)
|
||||
|
||||
|
||||
#if LL_LINUX_NV_GL_HEADERS
|
||||
// Missing functions when using nvidia headers:
|
||||
extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
|
||||
|
|
@ -445,6 +452,9 @@ extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
|
|||
extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
|
||||
extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;
|
||||
|
||||
//GL_EXT_blend_func_separate
|
||||
extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
|
||||
|
||||
//GL_EXT_framebuffer_object
|
||||
extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
|
||||
extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
|
||||
|
|
@ -473,7 +483,10 @@ extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT;
|
|||
//GL_ARB_draw_buffers
|
||||
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
|
||||
|
||||
|
||||
#elif LL_WINDOWS
|
||||
//----------------------------------------------------------------------------
|
||||
// LL_WINDOWS
|
||||
|
||||
// windows gl headers depend on things like APIENTRY, so include windows.
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
|
@ -641,6 +654,9 @@ extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
|
|||
extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
|
||||
extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
|
||||
|
||||
//GL_EXT_blend_func_separate
|
||||
extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
|
||||
|
||||
//GL_EXT_framebuffer_object
|
||||
extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
|
||||
extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
|
||||
|
|
@ -669,6 +685,7 @@ extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT;
|
|||
//GL_ARB_draw_buffers
|
||||
extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
|
||||
|
||||
|
||||
#elif LL_DARWIN
|
||||
//----------------------------------------------------------------------------
|
||||
// LL_DARWIN
|
||||
|
|
@ -685,6 +702,9 @@ extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;
|
|||
// Note that they also must not be called on 10.3.9. This should be taken care of by a runtime check for the existence of the GL extension.
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
//GL_EXT_blend_func_separate
|
||||
extern void glBlendFuncSeparateEXT(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
|
||||
|
||||
// GL_EXT_framebuffer_object
|
||||
extern GLboolean glIsRenderbufferEXT(GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
|
||||
extern void glBindRenderbufferEXT(GLenum target, GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
|
||||
|
|
|
|||
|
|
@ -1639,7 +1639,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
|
|||
}
|
||||
}
|
||||
|
||||
void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
|
||||
void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
|
||||
{
|
||||
if(!mNeedsAlphaAndPickMask)
|
||||
{
|
||||
|
|
@ -1647,24 +1647,64 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)
|
|||
}
|
||||
|
||||
U32 length = w * h;
|
||||
const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset ;
|
||||
|
||||
S32 sample[16];
|
||||
memset(sample, 0, sizeof(S32)*16);
|
||||
U32 sample[16];
|
||||
memset(sample, 0, sizeof(U32)*16);
|
||||
|
||||
for (U32 i = 0; i < length; i++)
|
||||
// generate histogram of quantized alpha.
|
||||
// also add-in the histogram of a 2x2 box-sampled version. The idea is
|
||||
// this will mid-skew the data (and thus increase the chances of not
|
||||
// being used as a mask) from high-frequency alpha maps which
|
||||
// suffer the worst from aliasing when used as alpha masks.
|
||||
if (w >= 2 && h >= 2)
|
||||
{
|
||||
++sample[*current/16];
|
||||
current += mAlphaStride ;
|
||||
}
|
||||
llassert(w%2 == 0);
|
||||
llassert(h%2 == 0);
|
||||
const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset;
|
||||
for (U32 y = 0; y < h; y+=2)
|
||||
{
|
||||
const GLubyte* current = rowstart;
|
||||
for (U32 x = 0; x < w; x+=2)
|
||||
{
|
||||
U32 s1 = current[0];
|
||||
U32 s2 = current[w * mAlphaStride];
|
||||
current += mAlphaStride;
|
||||
U32 s3 = current[0];
|
||||
U32 s4 = current[w * mAlphaStride];
|
||||
current += mAlphaStride;
|
||||
|
||||
U32 total = 0;
|
||||
++sample[s1/16];
|
||||
++sample[s2/16];
|
||||
++sample[s3/16];
|
||||
++sample[s4/16];
|
||||
|
||||
sample[(s1+s2+s3+s4)/(16 * 4)] += 4;
|
||||
}
|
||||
|
||||
rowstart += 2 * w * mAlphaStride;
|
||||
}
|
||||
length += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset;
|
||||
for (U32 i = 0; i < length; i++)
|
||||
{
|
||||
++sample[*current/16];
|
||||
current += mAlphaStride;
|
||||
}
|
||||
}
|
||||
|
||||
// if more than 1/16th of alpha samples are mid-range, this
|
||||
// shouldn't be treated as a 1-bit mask
|
||||
|
||||
U32 midrangetotal = 0;
|
||||
for (U32 i = 4; i < 11; i++)
|
||||
{
|
||||
total += sample[i];
|
||||
midrangetotal += sample[i];
|
||||
}
|
||||
|
||||
if (total > length/16)
|
||||
if (midrangetotal > length/16)
|
||||
{
|
||||
mIsMask = FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ public:
|
|||
protected:
|
||||
virtual ~LLImageGL();
|
||||
|
||||
void analyzeAlpha(const void* data_in, S32 w, S32 h);
|
||||
void analyzeAlpha(const void* data_in, U32 w, U32 h);
|
||||
void calcAlphaChannelOffsetAndStride();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -778,8 +778,11 @@ LLRender::LLRender()
|
|||
|
||||
mCurrAlphaFunc = CF_DEFAULT;
|
||||
mCurrAlphaFuncVal = 0.01f;
|
||||
mCurrBlendSFactor = BF_UNDEF;
|
||||
mCurrBlendDFactor = BF_UNDEF;
|
||||
|
||||
mCurrBlendColorSFactor = BF_UNDEF;
|
||||
mCurrBlendAlphaSFactor = BF_UNDEF;
|
||||
mCurrBlendColorDFactor = BF_UNDEF;
|
||||
mCurrBlendAlphaDFactor = BF_UNDEF;
|
||||
}
|
||||
|
||||
LLRender::~LLRender()
|
||||
|
|
@ -995,15 +998,44 @@ void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)
|
|||
{
|
||||
llassert(sfactor < BF_UNDEF);
|
||||
llassert(dfactor < BF_UNDEF);
|
||||
if (mCurrBlendSFactor != sfactor || mCurrBlendDFactor != dfactor)
|
||||
if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor ||
|
||||
mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor)
|
||||
{
|
||||
mCurrBlendSFactor = sfactor;
|
||||
mCurrBlendDFactor = dfactor;
|
||||
mCurrBlendColorSFactor = sfactor;
|
||||
mCurrBlendAlphaSFactor = sfactor;
|
||||
mCurrBlendColorDFactor = dfactor;
|
||||
mCurrBlendAlphaDFactor = dfactor;
|
||||
flush();
|
||||
glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);
|
||||
}
|
||||
}
|
||||
|
||||
void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
|
||||
eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor)
|
||||
{
|
||||
llassert(color_sfactor < BF_UNDEF);
|
||||
llassert(color_dfactor < BF_UNDEF);
|
||||
llassert(alpha_sfactor < BF_UNDEF);
|
||||
llassert(alpha_dfactor < BF_UNDEF);
|
||||
if (!gGLManager.mHasBlendFuncSeparate)
|
||||
{
|
||||
LL_WARNS_ONCE("render") << "no glBlendFuncSeparateEXT(), using color-only blend func" << llendl;
|
||||
blendFunc(color_sfactor, color_dfactor);
|
||||
return;
|
||||
}
|
||||
if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor ||
|
||||
mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor)
|
||||
{
|
||||
mCurrBlendColorSFactor = color_sfactor;
|
||||
mCurrBlendAlphaSFactor = alpha_sfactor;
|
||||
mCurrBlendColorDFactor = color_dfactor;
|
||||
mCurrBlendAlphaDFactor = alpha_dfactor;
|
||||
flush();
|
||||
glBlendFuncSeparateEXT(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor],
|
||||
sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
|
||||
}
|
||||
}
|
||||
|
||||
LLTexUnit* LLRender::getTexUnit(U32 index)
|
||||
{
|
||||
if (index < mTexUnits.size())
|
||||
|
|
|
|||
|
|
@ -323,7 +323,11 @@ public:
|
|||
|
||||
void setAlphaRejectSettings(eCompareFunc func, F32 value = 0.01f);
|
||||
|
||||
// applies blend func to both color and alpha
|
||||
void blendFunc(eBlendFactor sfactor, eBlendFactor dfactor);
|
||||
// applies separate blend functions to color and alpha
|
||||
void blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
|
||||
eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor);
|
||||
|
||||
LLTexUnit* getTexUnit(U32 index);
|
||||
|
||||
|
|
@ -362,9 +366,10 @@ private:
|
|||
std::vector<LLTexUnit*> mTexUnits;
|
||||
LLTexUnit* mDummyTexUnit;
|
||||
|
||||
eBlendFactor mCurrBlendSFactor;
|
||||
eBlendFactor mCurrBlendDFactor;
|
||||
|
||||
eBlendFactor mCurrBlendColorSFactor;
|
||||
eBlendFactor mCurrBlendColorDFactor;
|
||||
eBlendFactor mCurrBlendAlphaSFactor;
|
||||
eBlendFactor mCurrBlendAlphaDFactor;
|
||||
F32 mMaxAnisotropy;
|
||||
|
||||
std::list<LLVector3> mUIOffset;
|
||||
|
|
|
|||
|
|
@ -390,8 +390,6 @@ void LLRenderTarget::flush(BOOL fetch_depth)
|
|||
}
|
||||
else
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
|
||||
stop_glerror();
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
|
|
@ -435,7 +433,6 @@ void LLRenderTarget::flush(BOOL fetch_depth)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
|
@ -444,7 +441,6 @@ void LLRenderTarget::flush(BOOL fetch_depth)
|
|||
void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
|
||||
S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
gGL.flush();
|
||||
if (!source.mFBO || !mFBO)
|
||||
{
|
||||
|
|
@ -483,14 +479,12 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0,
|
|||
stop_glerror();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//static
|
||||
void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1,
|
||||
S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
if (!source.mFBO)
|
||||
{
|
||||
llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl;
|
||||
|
|
@ -507,7 +501,6 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0
|
|||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
stop_glerror();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL LLRenderTarget::isComplete() const
|
||||
|
|
@ -652,7 +645,6 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth
|
|||
|
||||
void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
if (color_fmt == 0)
|
||||
{
|
||||
return;
|
||||
|
|
@ -693,12 +685,10 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt)
|
|||
}
|
||||
|
||||
mTex.push_back(tex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLMultisampleBuffer::allocateDepth()
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
glGenRenderbuffersEXT(1, (GLuint* ) &mDepth);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth);
|
||||
if (mStencil)
|
||||
|
|
@ -709,6 +699,5 @@ void LLMultisampleBuffer::allocateDepth()
|
|||
{
|
||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ BOOL LLVertexBuffer::sVBOActive = FALSE;
|
|||
BOOL LLVertexBuffer::sIBOActive = FALSE;
|
||||
U32 LLVertexBuffer::sAllocatedBytes = 0;
|
||||
BOOL LLVertexBuffer::sMapped = FALSE;
|
||||
BOOL LLVertexBuffer::sUseStreamDraw = TRUE;
|
||||
|
||||
std::vector<U32> LLVertexBuffer::sDeleteList;
|
||||
|
||||
|
|
@ -381,6 +382,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
|
|||
{
|
||||
mUsage = 0 ;
|
||||
}
|
||||
|
||||
if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
|
||||
{
|
||||
mUsage = 0;
|
||||
}
|
||||
|
||||
S32 stride = calcStride(typemask, mOffsets);
|
||||
|
||||
|
|
@ -579,7 +585,7 @@ void LLVertexBuffer::destroyGLBuffer()
|
|||
}
|
||||
|
||||
mGLBuffer = 0;
|
||||
unbind();
|
||||
//unbind();
|
||||
}
|
||||
|
||||
void LLVertexBuffer::destroyGLIndices()
|
||||
|
|
@ -606,7 +612,7 @@ void LLVertexBuffer::destroyGLIndices()
|
|||
}
|
||||
|
||||
mGLIndices = 0;
|
||||
unbind();
|
||||
//unbind();
|
||||
}
|
||||
|
||||
void LLVertexBuffer::updateNumVerts(S32 nverts)
|
||||
|
|
@ -668,6 +674,12 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
|
|||
{
|
||||
LLMemType mt2(LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER);
|
||||
|
||||
if (nverts < 0 || nindices < 0 ||
|
||||
nverts > 65536)
|
||||
{
|
||||
llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl;
|
||||
}
|
||||
|
||||
updateNumVerts(nverts);
|
||||
updateNumIndices(nindices);
|
||||
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ public:
|
|||
static LLVBOPool sDynamicVBOPool;
|
||||
static LLVBOPool sStreamIBOPool;
|
||||
static LLVBOPool sDynamicIBOPool;
|
||||
|
||||
static BOOL sUseStreamDraw;
|
||||
|
||||
static void initClass(bool use_vbo);
|
||||
static void cleanupClass();
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ BOOL LLVFile::setMaxSize(S32 size)
|
|||
|
||||
if (!mVFS->checkAvailable(size))
|
||||
{
|
||||
LLFastTimer t(FTM_VFILE_WAIT);
|
||||
//LLFastTimer t(FTM_VFILE_WAIT);
|
||||
S32 count = 0;
|
||||
while (sVFSThread->getPending() > 1000)
|
||||
{
|
||||
|
|
@ -428,7 +428,7 @@ bool LLVFile::isLocked(EVFSLock lock)
|
|||
|
||||
void LLVFile::waitForLock(EVFSLock lock)
|
||||
{
|
||||
LLFastTimer t(FTM_VFILE_WAIT);
|
||||
//LLFastTimer t(FTM_VFILE_WAIT);
|
||||
// spin until the lock clears
|
||||
while (isLocked(lock))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2041,6 +2041,9 @@ std::string get_extension(LLAssetType::EType type)
|
|||
case LLAssetType::AT_ANIMATION:
|
||||
extension = ".lla";
|
||||
break;
|
||||
case LLAssetType::AT_MESH:
|
||||
extension = ".slm";
|
||||
break;
|
||||
default:
|
||||
// Just use the asset server filename extension in most cases
|
||||
extension += ".";
|
||||
|
|
|
|||
|
|
@ -38,11 +38,13 @@ include(UnixInstall)
|
|||
include(LLKDU)
|
||||
include(ViewerMiscLibs)
|
||||
include(LLLogin)
|
||||
include(GLOD)
|
||||
include(CMakeCopyIfDifferent)
|
||||
|
||||
include_directories(
|
||||
${DBUSGLIB_INCLUDE_DIRS}
|
||||
${ELFIO_INCLUDE_DIR}
|
||||
${GLOD_INCLUDE_DIR}
|
||||
${LLAUDIO_INCLUDE_DIRS}
|
||||
${LLCHARACTER_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
|
|
@ -61,6 +63,8 @@ include_directories(
|
|||
${LSCRIPT_INCLUDE_DIRS}
|
||||
${LSCRIPT_INCLUDE_DIRS}/lscript_compile
|
||||
${LLLOGIN_INCLUDE_DIRS}
|
||||
${LIBS_PREBUILT_DIR}/include/collada
|
||||
${LIBS_PREBUILT_DIR}/include/collada/1.4
|
||||
)
|
||||
|
||||
set(viewer_SOURCE_FILES
|
||||
|
|
@ -172,6 +176,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloaterhelpbrowser.cpp
|
||||
llfloaterhud.cpp
|
||||
llfloaterimagepreview.cpp
|
||||
llfloaterimportcollada.cpp
|
||||
llfloaterinspect.cpp
|
||||
llfloaterinventory.cpp
|
||||
llfloaterjoystick.cpp
|
||||
|
|
@ -182,6 +187,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloatermediabrowser.cpp
|
||||
llfloatermediasettings.cpp
|
||||
llfloatermemleak.cpp
|
||||
llfloatermodelpreview.cpp
|
||||
llfloaternamedesc.cpp
|
||||
llfloaternotificationsconsole.cpp
|
||||
llfloateropenobject.cpp
|
||||
|
|
@ -273,6 +279,8 @@ set(viewer_SOURCE_FILES
|
|||
llmediadataclient.cpp
|
||||
llmemoryview.cpp
|
||||
llmenucommands.cpp
|
||||
llmeshrepository.cpp
|
||||
llmeshreduction.cpp
|
||||
llmetricperformancetester.cpp
|
||||
llmimetypes.cpp
|
||||
llmorphview.cpp
|
||||
|
|
@ -673,6 +681,7 @@ set(viewer_HEADER_FILES
|
|||
llfloaterhelpbrowser.h
|
||||
llfloaterhud.h
|
||||
llfloaterimagepreview.h
|
||||
llfloaterimportcollada.h
|
||||
llfloaterinspect.h
|
||||
llfloaterinventory.h
|
||||
llfloaterjoystick.h
|
||||
|
|
@ -683,6 +692,7 @@ set(viewer_HEADER_FILES
|
|||
llfloatermediabrowser.h
|
||||
llfloatermediasettings.h
|
||||
llfloatermemleak.h
|
||||
llfloatermodelpreview.h
|
||||
llfloaternamedesc.h
|
||||
llfloaternotificationsconsole.h
|
||||
llfloateropenobject.h
|
||||
|
|
@ -774,6 +784,8 @@ set(viewer_HEADER_FILES
|
|||
llmediadataclient.h
|
||||
llmemoryview.h
|
||||
llmenucommands.h
|
||||
llmeshrepository.h
|
||||
llmeshreduction.h
|
||||
llmetricperformancetester.h
|
||||
llmimetypes.h
|
||||
llmorphview.h
|
||||
|
|
@ -1185,6 +1197,7 @@ if (WINDOWS)
|
|||
${DINPUT_LIBRARY}
|
||||
${DXGUID_LIBRARY}
|
||||
kernel32
|
||||
libboost_system
|
||||
odbc32
|
||||
odbccp32
|
||||
ole32
|
||||
|
|
@ -1608,6 +1621,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
|||
${DBUSGLIB_LIBRARIES}
|
||||
${OPENGL_LIBRARIES}
|
||||
${FMODWRAPPER_LIBRARY} # must come after LLAudio
|
||||
${GLOD_LIBRARIES}
|
||||
${OPENGL_LIBRARIES}
|
||||
${SDL_LIBRARY}
|
||||
${SMARTHEAP_LIBRARY}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
<RenderFlexTimeFactor value="1"/>
|
||||
<!--256... but they don't use this-->
|
||||
<RenderGlowResolutionPow value="9"/>
|
||||
<!--Sun/Moon only-->
|
||||
<RenderLightingDetail value="1"/>
|
||||
<!--Low number-->
|
||||
<RenderMaxPartCount value="4096"/>
|
||||
<!--bump okay-->
|
||||
|
|
@ -31,9 +29,14 @@
|
|||
<!--Default for now-->
|
||||
<RenderVolumeLODFactor value="1.125"/>
|
||||
<!--NO SHADERS-->
|
||||
<RenderWaterReflections value="FALSE"/>
|
||||
<!--NO SHADERS-->
|
||||
<VertexShaderEnable value="TRUE"/>
|
||||
<!--NO SHADERS-->
|
||||
<WindLightUseAtmosShaders value="TRUE"/>
|
||||
<!--Deferred Shading-->
|
||||
<RenderDeferred value="TRUE"/>
|
||||
<!--SSAO Disabled-->
|
||||
<RenderDeferredSSAO value="FALSE"/>
|
||||
<!--Sun Shadows-->
|
||||
<RenderShadowDetail value="1"/>
|
||||
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
<RenderFlexTimeFactor value="0.5"/>
|
||||
<!--256... but they don't use this-->
|
||||
<RenderGlowResolutionPow value="8"/>
|
||||
<!--Sun/Moon only-->
|
||||
<RenderLightingDetail value="0"/>
|
||||
<!--Low number-->
|
||||
<RenderMaxPartCount value="1024"/>
|
||||
<!--bump okay-->
|
||||
|
|
@ -31,9 +29,14 @@
|
|||
<!--Default for now-->
|
||||
<RenderVolumeLODFactor value="1.125"/>
|
||||
<!--NO SHADERS-->
|
||||
<RenderWaterReflections value="FALSE"/>
|
||||
<!--NO SHADERS-->
|
||||
<VertexShaderEnable value="FALSE"/>
|
||||
<!--NO SHADERS-->
|
||||
<WindLightUseAtmosShaders value="FALSE"/>
|
||||
<!--No Deferred Shading-->
|
||||
<RenderDeferred value="FALSE"/>
|
||||
<!--SSAO Disabled-->
|
||||
<RenderDeferredSSAO value="FALSE"/>
|
||||
<!--No Shadows-->
|
||||
<RenderShadowDetail value="0"/>
|
||||
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@
|
|||
<RenderFlexTimeFactor value="1"/>
|
||||
<!--256... but they don't use this-->
|
||||
<RenderGlowResolutionPow value="8"/>
|
||||
<!--Sun/Moon only-->
|
||||
<RenderLightingDetail value="1"/>
|
||||
<!--Low number-->
|
||||
<RenderMaxPartCount value="2048"/>
|
||||
<!--bump okay-->
|
||||
|
|
@ -31,9 +29,14 @@
|
|||
<!--Default for now-->
|
||||
<RenderVolumeLODFactor value="1.125"/>
|
||||
<!--NO SHADERS-->
|
||||
<RenderWaterReflections value="FALSE"/>
|
||||
<!--NO SHADERS-->
|
||||
<VertexShaderEnable value="TRUE"/>
|
||||
<!--NO SHADERS-->
|
||||
<WindLightUseAtmosShaders value="FALSE"/>
|
||||
<!--No Deferred Shading-->
|
||||
<RenderDeferred value="FALSE"/>
|
||||
<!--SSAO Disabled-->
|
||||
<RenderDeferredSSAO value="FALSE"/>
|
||||
<!--No Shadows-->
|
||||
<RenderShadowDetail value="0"/>
|
||||
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -1709,7 +1709,7 @@
|
|||
<key>DebugShowRenderInfo</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show depth buffer contents</string>
|
||||
<string>Show stats about current scene</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -1717,6 +1717,17 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DebugShowUploadCost</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show what it would cost to upload assets in current scene</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DebugShowRenderMatrices</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -6083,7 +6094,7 @@
|
|||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>60</integer>
|
||||
<integer>200</integer>
|
||||
</map>
|
||||
<key>RenderSSAOFactor</key>
|
||||
<map>
|
||||
|
|
@ -6607,19 +6618,7 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderDeferredShadow</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable shadows in deferred renderer.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
|
||||
|
||||
<key>RenderDeferredGI</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -6632,18 +6631,6 @@
|
|||
<integer>0</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderDeferredSunShadow</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Generate shadows from the sun.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderDeferredSun</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -6668,6 +6655,18 @@
|
|||
<integer>1</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderDeferredSSAO</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Execute screen space ambient occlusion shader in deferred renderer.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderDeferredBlurLight</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -6921,7 +6920,7 @@
|
|||
<key>RenderFastAlpha</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use lossy alpha rendering optimization (opaque/nonexistent small alpha faces).</string>
|
||||
<string>Use alpha masks where appropriate.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -7190,17 +7189,6 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderLightingDetail</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Amount of detail for lighting objects/avatars/terrain (0=sun/moon only, 1=enable local lights)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderMaxPartCount</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -7300,7 +7288,19 @@
|
|||
<key>Value</key>
|
||||
<integer>2</integer>
|
||||
</map>
|
||||
<key>RenderReflectionRes</key>
|
||||
<key>RenderShadowDetail</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Detail of shadows.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>2</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderReflectionRes</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Reflection map resolution.</string>
|
||||
|
|
@ -7463,9 +7463,20 @@
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderUseTriStrips</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use triangle strips for rendering prims.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderUseTriStrips</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use triangle strips for rendering prims.</string>
|
||||
|
|
@ -7531,6 +7542,17 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderUseStreamVBO</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use VBO's for stream buffers</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RenderVolumeLODFactor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -7575,17 +7597,6 @@
|
|||
<key>Value</key>
|
||||
<integer>512</integer>
|
||||
</map>
|
||||
<key>RenderWaterReflections</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Reflect the environment in the water.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RotateRight</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -7619,7 +7630,30 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SafeMode</key>
|
||||
<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>SafeMode</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Reset preferences, run in safe mode.</string>
|
||||
|
|
@ -10180,7 +10214,7 @@
|
|||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SpeakerParticipantRemoveDelay</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,6 @@ varying vec3 vary_fragcoord;
|
|||
varying vec3 vary_position;
|
||||
varying vec3 vary_light;
|
||||
|
||||
uniform float alpha_soften;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
|
|
@ -57,15 +55,6 @@ void main()
|
|||
|
||||
color.rgb = scaleSoftClip(color.rgb);
|
||||
|
||||
if (samp_pos.z != 0.0 && gl_Color.a < 1.0)
|
||||
{
|
||||
float dist_factor = alpha_soften;
|
||||
float a = gl_Color.a;
|
||||
a *= a;
|
||||
dist_factor *= 1.0/(1.0-a);
|
||||
color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0);
|
||||
}
|
||||
|
||||
//gl_FragColor = gl_Color;
|
||||
gl_FragColor = color;
|
||||
//gl_FragColor = vec4(1,0,1,1);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
|
|||
void calcAtmospherics(vec3 inPositionEye);
|
||||
|
||||
float calcDirectionalLight(vec3 n, vec3 l);
|
||||
float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
|
||||
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
|
||||
|
||||
vec3 atmosAmbient(vec3 light);
|
||||
vec3 atmosAffectDirectionalLight(float lightIntensity);
|
||||
|
|
@ -41,23 +41,22 @@ void main()
|
|||
calcAtmospherics(pos.xyz);
|
||||
|
||||
//vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
|
||||
vec4 col;
|
||||
col.a = gl_Color.a;
|
||||
|
||||
// Add windlight lights
|
||||
col.rgb = atmosAmbient(vec3(0.));
|
||||
col.rgb = scaleUpLight(col.rgb);
|
||||
|
||||
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
|
||||
|
||||
// Collect normal lights (need to be divided by two, as we later multiply by 2)
|
||||
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
|
||||
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
|
||||
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
|
||||
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
|
||||
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
|
||||
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
|
||||
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].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].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].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].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].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].specular.a);
|
||||
col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
|
||||
col.rgb = scaleDownLight(col.rgb);
|
||||
|
||||
// Add windlight lights
|
||||
col.rgb += atmosAmbient(vec3(0.));
|
||||
|
||||
vary_light = gl_LightSource[0].position.xyz;
|
||||
|
||||
vary_ambient = col.rgb*gl_Color.rgb;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ mat4 getSkinnedTransform();
|
|||
void calcAtmospherics(vec3 inPositionEye);
|
||||
|
||||
float calcDirectionalLight(vec3 n, vec3 l);
|
||||
float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
|
||||
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
|
||||
|
||||
vec3 atmosAmbient(vec3 light);
|
||||
vec3 atmosAffectDirectionalLight(float lightIntensity);
|
||||
|
|
@ -47,23 +47,22 @@ void main()
|
|||
calcAtmospherics(pos.xyz);
|
||||
|
||||
//vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
|
||||
vec4 col;
|
||||
col.a = gl_Color.a;
|
||||
|
||||
// Add windlight lights
|
||||
col.rgb = atmosAmbient(vec3(0.));
|
||||
col.rgb = scaleUpLight(col.rgb);
|
||||
|
||||
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
|
||||
|
||||
// Collect normal lights (need to be divided by two, as we later multiply by 2)
|
||||
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
|
||||
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
|
||||
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
|
||||
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
|
||||
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
|
||||
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
|
||||
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].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].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].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].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].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].specular.a);
|
||||
col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
|
||||
col.rgb = scaleDownLight(col.rgb);
|
||||
|
||||
// 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)));
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,11 @@
|
|||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2DRect normalMap;
|
||||
uniform sampler2DRect lightMap;
|
||||
uniform sampler2DRect giLightMap;
|
||||
|
||||
uniform float dist_factor;
|
||||
uniform float blur_size;
|
||||
uniform vec2 delta;
|
||||
uniform vec3 kern[32];
|
||||
uniform int kern_length;
|
||||
uniform vec3 kern[4];
|
||||
uniform float kern_scale;
|
||||
|
||||
varying vec2 vary_fragcoord;
|
||||
|
|
@ -50,7 +48,7 @@ void main()
|
|||
vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
|
||||
vec4 col = defined_weight.xyxx * ccol;
|
||||
|
||||
for (int i = 1; i < kern_length; i++)
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
|
||||
vec3 samppos = getPosition(tc).xyz;
|
||||
|
|
@ -61,12 +59,22 @@ void main()
|
|||
defined_weight += kern[i].xy;
|
||||
}
|
||||
}
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
|
||||
vec3 samppos = getPosition(tc).xyz;
|
||||
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
|
||||
if (d*d <= 0.003)
|
||||
{
|
||||
col += texture2DRect(lightMap, tc)*kern[i].xyxx;
|
||||
defined_weight += kern[i].xy;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
col /= defined_weight.xyxx;
|
||||
|
||||
gl_FragColor = col;
|
||||
|
||||
//gl_FragColor = ccol;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@ varying vec4 vary_position;
|
|||
varying vec3 vary_normal;
|
||||
varying vec3 vary_fragcoord;
|
||||
|
||||
uniform float alpha_soften;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
|
|
@ -56,15 +54,6 @@ void main()
|
|||
|
||||
color.rgb = fullbrightScaleSoftClip(color.rgb);
|
||||
|
||||
if (samp_pos.z != 0.0 && color.a < 1.0)
|
||||
{
|
||||
float dist_factor = alpha_soften;
|
||||
float a = color.a;
|
||||
a *= a;
|
||||
dist_factor *= 1.0/(1.0-a);
|
||||
color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0);
|
||||
}
|
||||
|
||||
//gl_FragColor = gl_Color;
|
||||
gl_FragColor = color;
|
||||
//gl_FragColor = vec4(1,0,1,1);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ uniform sampler2D specularMap;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_FragData[0] = texture2D(diffuseMap, gl_TexCoord[0].xy);
|
||||
vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy);
|
||||
gl_FragData[0] = vec4(col.rgb, col.a <= 0.5 ? 0.0 : 0.005);
|
||||
gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy);
|
||||
gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, 0.0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@
|
|||
* $License$
|
||||
*/
|
||||
|
||||
|
||||
#version 120
|
||||
|
||||
//class 1 -- no shadows
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
uniform sampler2DRect diffuseRect;
|
||||
|
|
@ -26,12 +27,15 @@ uniform vec3 proj_n;
|
|||
uniform float proj_focus; //distance from plane to begin blurring
|
||||
uniform float proj_lod; //(number of mips in proj map)
|
||||
uniform float proj_range; //range between near clip and far clip plane of projection
|
||||
uniform float proj_ambient_lod;
|
||||
uniform float proj_ambiance;
|
||||
uniform float near_clip;
|
||||
uniform float far_clip;
|
||||
|
||||
uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
|
||||
uniform float sun_wash;
|
||||
uniform int proj_shadow_idx;
|
||||
uniform float shadow_fade;
|
||||
|
||||
varying vec4 vary_light;
|
||||
|
||||
|
|
@ -40,6 +44,52 @@ uniform vec2 screen_res;
|
|||
|
||||
uniform mat4 inv_proj;
|
||||
|
||||
vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = tc-vec2(0.5);
|
||||
|
||||
float det = max(1.0-lod/(proj_lod*0.5), 0.0);
|
||||
|
||||
float d = dot(dist,dist);
|
||||
|
||||
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
|
||||
|
||||
float det = min(lod/(proj_lod*0.5), 1.0);
|
||||
|
||||
float d = min(dist.x, dist.y);
|
||||
|
||||
float edge = 0.25*det;
|
||||
|
||||
ret *= clamp(d/edge, 0.0, 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = tc-vec2(0.5);
|
||||
|
||||
float d = dot(dist,dist);
|
||||
|
||||
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
{
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).a;
|
||||
|
|
@ -68,7 +118,7 @@ void main()
|
|||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
|
||||
vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0;
|
||||
|
||||
norm = normalize(norm);
|
||||
|
|
@ -83,7 +133,11 @@ void main()
|
|||
proj_tc.xyz /= proj_tc.w;
|
||||
|
||||
float fa = gl_Color.a+1.0;
|
||||
float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
|
||||
float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0);
|
||||
if (dist_atten <= 0.0)
|
||||
{
|
||||
discard;
|
||||
}
|
||||
|
||||
lv = proj_origin-pos.xyz;
|
||||
lv = normalize(lv);
|
||||
|
|
@ -101,32 +155,32 @@ void main()
|
|||
proj_tc.y > 0.0)
|
||||
{
|
||||
float lit = 0.0;
|
||||
float amb_da = proj_ambiance;
|
||||
|
||||
if (da > 0.0)
|
||||
{
|
||||
float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
|
||||
float lod = diff * proj_lod;
|
||||
|
||||
vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
|
||||
vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
|
||||
|
||||
vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
|
||||
|
||||
lit = da * dist_atten * noise;
|
||||
|
||||
col = lcol*lit*diff_tex;
|
||||
amb_da += (da*0.5)*proj_ambiance;
|
||||
}
|
||||
|
||||
float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
|
||||
float lod = diff * proj_lod;
|
||||
vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
|
||||
//float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0));
|
||||
float amb_da = proj_ambiance;
|
||||
|
||||
//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
|
||||
vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
|
||||
|
||||
amb_da += (da*da*0.5+0.5)*proj_ambiance;
|
||||
|
||||
|
||||
amb_da *= dist_atten * noise;
|
||||
|
||||
|
||||
amb_da = min(amb_da, 1.0-lit);
|
||||
|
||||
|
||||
col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
|
||||
}
|
||||
|
||||
|
|
@ -144,35 +198,28 @@ void main()
|
|||
{
|
||||
vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
|
||||
|
||||
vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz;
|
||||
vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
|
||||
|
||||
if (stc.z > 0.0)
|
||||
{
|
||||
stc.xy /= stc.z+proj_near;
|
||||
|
||||
stc.xy /= stc.w;
|
||||
|
||||
float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
|
||||
|
||||
stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
|
||||
|
||||
if (stc.x < 1.0 &&
|
||||
stc.y < 1.0 &&
|
||||
stc.x > 0.0 &&
|
||||
stc.y > 0.0)
|
||||
{
|
||||
vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
|
||||
vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
|
||||
col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if (spec.a > 0.0)
|
||||
{
|
||||
//vec3 ref = reflect(normalize(pos), norm);
|
||||
float sa = dot(normalize(lv-normalize(pos)),norm);;
|
||||
//sa = max(sa, 0.0);
|
||||
//sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
|
||||
sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
|
||||
sa *= noise;
|
||||
col += da*sa*lcol*spec.rgb;
|
||||
}*/
|
||||
|
||||
gl_FragColor.rgb = col;
|
||||
gl_FragColor.a = 0.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ uniform sampler2DRect diffuseRect;
|
|||
uniform sampler2DRect specularRect;
|
||||
uniform sampler2DRect positionMap;
|
||||
uniform sampler2DRect normalMap;
|
||||
uniform sampler2DRect lightMap;
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2D noiseMap;
|
||||
uniform samplerCube environmentMap;
|
||||
|
|
@ -40,7 +41,7 @@ uniform float scene_light_strength;
|
|||
uniform vec3 env_mat[3];
|
||||
//uniform mat4 shadow_matrix[3];
|
||||
//uniform vec4 shadow_clip;
|
||||
//uniform mat3 ssao_effect_mat;
|
||||
uniform mat3 ssao_effect_mat;
|
||||
|
||||
varying vec4 vary_light;
|
||||
varying vec2 vary_fragcoord;
|
||||
|
|
@ -178,7 +179,17 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
|
|||
temp2.x += .25;
|
||||
|
||||
//increase ambient when there are more clouds
|
||||
vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5;
|
||||
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(
|
||||
|
|
@ -250,10 +261,14 @@ void main()
|
|||
vec4 diffuse = texture2DRect(diffuseRect, tc);
|
||||
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
|
||||
|
||||
calcAtmospherics(pos.xyz, 0.0);
|
||||
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(clamp(da, diffuse.a, 1.0));
|
||||
col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
|
||||
|
||||
col *= diffuse.rgb;
|
||||
|
||||
|
|
@ -261,12 +276,12 @@ void main()
|
|||
{
|
||||
vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
|
||||
float sa = dot(ref, vary_light.xyz);
|
||||
col.rgb += vary_SunlitColor*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
|
||||
col.rgb += vary_SunlitColor*scol_ambocc.r*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
|
||||
}
|
||||
|
||||
col = atmosLighting(col);
|
||||
col = scaleSoftClip(col);
|
||||
|
||||
|
||||
gl_FragColor.rgb = col;
|
||||
gl_FragColor.a = 0.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,17 +161,6 @@ void main()
|
|||
}
|
||||
}
|
||||
|
||||
/*if (spec.a > 0.0)
|
||||
{
|
||||
//vec3 ref = reflect(normalize(pos), norm);
|
||||
float sa = dot(normalize(lv-normalize(pos)),norm);;
|
||||
//sa = max(sa, 0.0);
|
||||
//sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
|
||||
sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
|
||||
sa *= noise;
|
||||
col += da*sa*lcol*spec.rgb;
|
||||
}*/
|
||||
|
||||
gl_FragColor.rgb = col;
|
||||
gl_FragColor.a = 0.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,196 +5,11 @@
|
|||
* $License$
|
||||
*/
|
||||
|
||||
//class 1, no shadow, no SSAO, should never be called
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2DRect normalMap;
|
||||
uniform sampler2DRectShadow shadowMap0;
|
||||
uniform sampler2DRectShadow shadowMap1;
|
||||
uniform sampler2DRectShadow shadowMap2;
|
||||
uniform sampler2DRectShadow shadowMap3;
|
||||
uniform sampler2DRectShadow shadowMap4;
|
||||
uniform sampler2DRectShadow shadowMap5;
|
||||
uniform sampler2D noiseMap;
|
||||
|
||||
uniform sampler2D lightFunc;
|
||||
|
||||
|
||||
// Inputs
|
||||
uniform mat4 shadow_matrix[6];
|
||||
uniform vec4 shadow_clip;
|
||||
uniform float ssao_radius;
|
||||
uniform float ssao_max_radius;
|
||||
uniform float ssao_factor;
|
||||
uniform float ssao_factor_inv;
|
||||
|
||||
varying vec2 vary_fragcoord;
|
||||
varying vec4 vary_light;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
uniform vec2 screen_res;
|
||||
|
||||
uniform float shadow_bias;
|
||||
uniform float shadow_offset;
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
{
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).a;
|
||||
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;
|
||||
}
|
||||
|
||||
//calculate decreases in ambient lighting when crowded out (SSAO)
|
||||
float calcAmbientOcclusion(vec4 pos, vec3 norm)
|
||||
{
|
||||
vec2 kern[8];
|
||||
// exponentially (^2) distant occlusion samples spread around origin
|
||||
kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
|
||||
kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
|
||||
kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
|
||||
kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
|
||||
kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
|
||||
kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
|
||||
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
|
||||
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
|
||||
|
||||
vec2 pos_screen = vary_fragcoord.xy;
|
||||
vec3 pos_world = pos.xyz;
|
||||
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
|
||||
|
||||
float angle_hidden = 0.0;
|
||||
int points = 0;
|
||||
|
||||
float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
|
||||
|
||||
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
|
||||
vec3 samppos_world = getPosition(samppos_screen).xyz;
|
||||
|
||||
vec3 diff = pos_world - samppos_world;
|
||||
float dist2 = dot(diff, diff);
|
||||
|
||||
// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
|
||||
// --> solid angle shrinking by the square of distance
|
||||
//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
|
||||
//(k should vary inversely with # of samples, but this is taken care of later)
|
||||
|
||||
//if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces
|
||||
// angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor)
|
||||
angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
|
||||
|
||||
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
|
||||
points = points + int(diff.z > -1.0);
|
||||
}
|
||||
|
||||
angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
|
||||
|
||||
return (1.0 - (float(points != 0) * angle_hidden));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pos_screen = vary_fragcoord.xy;
|
||||
|
||||
//try doing an unproject here
|
||||
|
||||
vec4 pos = getPosition(pos_screen);
|
||||
|
||||
vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
|
||||
|
||||
/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
|
||||
{
|
||||
gl_FragColor = vec4(0.0); // doesn't matter
|
||||
return;
|
||||
}*/
|
||||
|
||||
float shadow = 1.0;
|
||||
float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
|
||||
|
||||
vec4 spos = vec4(pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias), 1.0);
|
||||
|
||||
//vec3 debug = vec3(0,0,0);
|
||||
|
||||
if (dp_directional_light == 0.0)
|
||||
{
|
||||
// if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
|
||||
shadow = 0.0;
|
||||
}
|
||||
else if (spos.z > -shadow_clip.w)
|
||||
{
|
||||
vec4 lpos;
|
||||
|
||||
if (spos.z < -shadow_clip.z)
|
||||
{
|
||||
lpos = shadow_matrix[3]*spos;
|
||||
lpos.xy *= screen_res;
|
||||
shadow = shadow2DRectProj(shadowMap3, lpos).x;
|
||||
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
|
||||
}
|
||||
else if (spos.z < -shadow_clip.y)
|
||||
{
|
||||
lpos = shadow_matrix[2]*spos;
|
||||
lpos.xy *= screen_res;
|
||||
shadow = shadow2DRectProj(shadowMap2, lpos).x;
|
||||
}
|
||||
else if (spos.z < -shadow_clip.x)
|
||||
{
|
||||
lpos = shadow_matrix[1]*spos;
|
||||
lpos.xy *= screen_res;
|
||||
shadow = shadow2DRectProj(shadowMap1, lpos).x;
|
||||
}
|
||||
else
|
||||
{
|
||||
lpos = shadow_matrix[0]*spos;
|
||||
lpos.xy *= screen_res;
|
||||
shadow = shadow2DRectProj(shadowMap0, lpos).x;
|
||||
}
|
||||
|
||||
// take the most-shadowed value out of these two:
|
||||
// * the blurred sun shadow in the light (shadow) map
|
||||
// * an unblurred dot product between the sun and this norm
|
||||
// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
|
||||
shadow = min(shadow, dp_directional_light);
|
||||
|
||||
/*debug.r = lpos.y / (lpos.w*screen_res.y);
|
||||
|
||||
lpos.xy /= lpos.w*32.0;
|
||||
if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
|
||||
{
|
||||
debug.gb = vec2(0.5, 0.5);
|
||||
}
|
||||
|
||||
debug += (1.0-shadow)*0.5;*/
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// more distant than the shadow map covers - just use directional shading as shadow
|
||||
shadow = dp_directional_light;
|
||||
}
|
||||
|
||||
gl_FragColor[0] = shadow;
|
||||
gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
|
||||
|
||||
//spotlight shadow 1
|
||||
vec4 lpos = shadow_matrix[4]*spos;
|
||||
lpos.xy *= screen_res;
|
||||
gl_FragColor[2] = shadow2DRectProj(shadowMap4, lpos).x;
|
||||
|
||||
//spotlight shadow 2
|
||||
lpos = shadow_matrix[5]*spos;
|
||||
lpos.xy *= screen_res;
|
||||
gl_FragColor[3] = shadow2DRectProj(shadowMap5, lpos).x;
|
||||
|
||||
//gl_FragColor.rgb = pos.xyz;
|
||||
//gl_FragColor.b = shadow;
|
||||
//gl_FragColor.rgb = debug;
|
||||
gl_FragColor = vec4(0,0,0,0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* @file sunLightSSAOF.glsl
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
//class 1 -- no shadow, SSAO only
|
||||
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2DRect normalMap;
|
||||
uniform sampler2D noiseMap;
|
||||
|
||||
uniform sampler2D lightFunc;
|
||||
|
||||
|
||||
// Inputs
|
||||
uniform mat4 shadow_matrix[6];
|
||||
uniform vec4 shadow_clip;
|
||||
uniform float ssao_radius;
|
||||
uniform float ssao_max_radius;
|
||||
uniform float ssao_factor;
|
||||
uniform float ssao_factor_inv;
|
||||
|
||||
varying vec2 vary_fragcoord;
|
||||
varying vec4 vary_light;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
uniform vec2 screen_res;
|
||||
|
||||
uniform float shadow_bias;
|
||||
uniform float shadow_offset;
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
{
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).a;
|
||||
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;
|
||||
}
|
||||
|
||||
//calculate decreases in ambient lighting when crowded out (SSAO)
|
||||
float calcAmbientOcclusion(vec4 pos, vec3 norm)
|
||||
{
|
||||
float ret = 1.0;
|
||||
|
||||
float dist = dot(pos.xyz,pos.xyz);
|
||||
|
||||
if (dist < 64.0*64.0)
|
||||
{
|
||||
vec2 kern[8];
|
||||
// exponentially (^2) distant occlusion samples spread around origin
|
||||
kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
|
||||
kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
|
||||
kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
|
||||
kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
|
||||
kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
|
||||
kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
|
||||
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
|
||||
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
|
||||
|
||||
vec2 pos_screen = vary_fragcoord.xy;
|
||||
vec3 pos_world = pos.xyz;
|
||||
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
|
||||
|
||||
float angle_hidden = 0.0;
|
||||
int points = 0;
|
||||
|
||||
float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
|
||||
|
||||
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
|
||||
vec3 samppos_world = getPosition(samppos_screen).xyz;
|
||||
|
||||
vec3 diff = pos_world - samppos_world;
|
||||
float dist2 = dot(diff, diff);
|
||||
|
||||
// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
|
||||
// --> solid angle shrinking by the square of distance
|
||||
//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
|
||||
//(k should vary inversely with # of samples, but this is taken care of later)
|
||||
|
||||
//if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces
|
||||
// angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor)
|
||||
angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
|
||||
|
||||
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
|
||||
points = points + int(diff.z > -1.0);
|
||||
}
|
||||
|
||||
angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
|
||||
|
||||
ret = (1.0 - (float(points != 0) * angle_hidden));
|
||||
ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0);
|
||||
}
|
||||
|
||||
return min(ret, 1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pos_screen = vary_fragcoord.xy;
|
||||
|
||||
//try doing an unproject here
|
||||
|
||||
vec4 pos = getPosition(pos_screen);
|
||||
|
||||
vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
|
||||
|
||||
gl_FragColor[0] = 1.0;
|
||||
gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
|
||||
gl_FragColor[2] = 1.0;
|
||||
gl_FragColor[3] = 1.0;
|
||||
}
|
||||
|
|
@ -115,7 +115,7 @@ void main()
|
|||
vec4 fb = texture2D(screenTex, distort2);
|
||||
|
||||
//mix with reflection
|
||||
// Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug
|
||||
// Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
|
||||
color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
|
||||
|
||||
float shadow = 1.0;
|
||||
|
|
@ -131,11 +131,11 @@ void main()
|
|||
//color.rgb = scaleSoftClip(color.rgb);
|
||||
//color.a = spec * sunAngle2;
|
||||
|
||||
//wavef.z = -0.25f;
|
||||
wavef = normalize(wavef);
|
||||
wavef = (norm_mat*vec4(wavef, 1.0)).xyz;
|
||||
//wavef.z *= 0.1f;
|
||||
//wavef = normalize(wavef);
|
||||
vec3 screenspacewavef = (norm_mat*vec4(wavef, 1.0)).xyz;
|
||||
|
||||
gl_FragData[0] = vec4(color.rgb, 0.75);
|
||||
gl_FragData[1] = vec4(1,1,1, 0.8);
|
||||
gl_FragData[2] = vec4(wavef*0.5+0.5, 0.0);
|
||||
gl_FragData[0] = vec4(color.rgb, 0.5); // diffuse
|
||||
gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
|
||||
gl_FragData[2] = vec4(screenspacewavef*0.5+0.5, screenspacewavef.z*0.5); // normal, displace
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ float calcDirectionalLight(vec3 n, vec3 l)
|
|||
return a;
|
||||
}
|
||||
|
||||
float calcPointLight(vec3 v, vec3 n, vec4 lp, float la)
|
||||
|
||||
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight)
|
||||
{
|
||||
//get light vector
|
||||
vec3 lv = lp.xyz-v;
|
||||
|
|
@ -26,9 +27,13 @@ float calcPointLight(vec3 v, vec3 n, vec4 lp, float la)
|
|||
//distance attenuation
|
||||
float da = clamp(1.0/(la * d), 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ varying vec3 vary_fragcoord;
|
|||
varying vec3 vary_position;
|
||||
varying vec3 vary_light;
|
||||
|
||||
uniform float alpha_soften;
|
||||
|
||||
uniform float shadow_bias;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
|
|
@ -115,15 +113,6 @@ void main()
|
|||
|
||||
color.rgb = scaleSoftClip(color.rgb);
|
||||
|
||||
if (samp_pos.z != 0.0 && gl_Color.a < 1.0)
|
||||
{
|
||||
float dist_factor = alpha_soften;
|
||||
float a = gl_Color.a;
|
||||
a *= a;
|
||||
dist_factor *= 1.0/(1.0-a);
|
||||
color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0);
|
||||
}
|
||||
|
||||
//gl_FragColor = gl_Color;
|
||||
gl_FragColor = color;
|
||||
//gl_FragColor = vec4(1,0,1,1)*shadow;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
|
|||
void calcAtmospherics(vec3 inPositionEye);
|
||||
|
||||
float calcDirectionalLight(vec3 n, vec3 l);
|
||||
float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
|
||||
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
|
||||
|
||||
vec3 atmosAmbient(vec3 light);
|
||||
vec3 atmosAffectDirectionalLight(float lightIntensity);
|
||||
|
|
@ -42,23 +42,21 @@ void main()
|
|||
calcAtmospherics(pos.xyz);
|
||||
|
||||
//vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
|
||||
vec4 col;
|
||||
col.a = gl_Color.a;
|
||||
|
||||
// Add windlight lights
|
||||
col.rgb = atmosAmbient(vec3(0.));
|
||||
col.rgb = scaleUpLight(col.rgb);
|
||||
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
|
||||
|
||||
// Collect normal lights (need to be divided by two, as we later multiply by 2)
|
||||
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
|
||||
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
|
||||
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
|
||||
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
|
||||
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
|
||||
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
|
||||
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].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].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].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].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].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].specular.a);
|
||||
col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
|
||||
col.rgb = scaleDownLight(col.rgb);
|
||||
|
||||
// Add windlight lights
|
||||
col.rgb += atmosAmbient(vec3(0.));
|
||||
|
||||
vary_light = gl_LightSource[0].position.xyz;
|
||||
|
||||
vary_ambient = col.rgb*gl_Color.rgb;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ mat4 getSkinnedTransform();
|
|||
void calcAtmospherics(vec3 inPositionEye);
|
||||
|
||||
float calcDirectionalLight(vec3 n, vec3 l);
|
||||
float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
|
||||
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
|
||||
|
||||
vec3 atmosAmbient(vec3 light);
|
||||
vec3 atmosAffectDirectionalLight(float lightIntensity);
|
||||
|
|
@ -53,23 +53,22 @@ void main()
|
|||
calcAtmospherics(pos.xyz);
|
||||
|
||||
//vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.));
|
||||
vec4 col;
|
||||
col.a = gl_Color.a;
|
||||
|
||||
// Add windlight lights
|
||||
col.rgb = atmosAmbient(vec3(0.));
|
||||
col.rgb = scaleUpLight(col.rgb);
|
||||
|
||||
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
|
||||
|
||||
// Collect normal lights (need to be divided by two, as we later multiply by 2)
|
||||
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
|
||||
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
|
||||
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
|
||||
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
|
||||
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
|
||||
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
|
||||
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].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].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].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].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].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].specular.a);
|
||||
col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
|
||||
col.rgb = scaleDownLight(col.rgb);
|
||||
|
||||
// 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)));
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,52 @@ uniform vec2 screen_res;
|
|||
|
||||
uniform mat4 inv_proj;
|
||||
|
||||
vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = tc-vec2(0.5);
|
||||
|
||||
float det = max(1.0-lod/(proj_lod*0.5), 0.0);
|
||||
|
||||
float d = dot(dist,dist);
|
||||
|
||||
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
|
||||
|
||||
float det = min(lod/(proj_lod*0.5), 1.0);
|
||||
|
||||
float d = min(dist.x, dist.y);
|
||||
|
||||
float edge = 0.25*det;
|
||||
|
||||
ret *= clamp(d/edge, 0.0, 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
|
||||
{
|
||||
vec4 ret = texture2DLod(projectionMap, tc, lod);
|
||||
|
||||
vec2 dist = tc-vec2(0.5);
|
||||
|
||||
float d = dot(dist,dist);
|
||||
|
||||
ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
{
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).a;
|
||||
|
|
@ -126,7 +172,7 @@ void main()
|
|||
float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
|
||||
float lod = diff * proj_lod;
|
||||
|
||||
vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod);
|
||||
vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
|
||||
|
||||
vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a;
|
||||
|
||||
|
|
@ -137,7 +183,7 @@ void main()
|
|||
}
|
||||
|
||||
//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
|
||||
vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod);
|
||||
vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
|
||||
|
||||
amb_da += (da*da*0.5+0.5)*proj_ambiance;
|
||||
|
||||
|
|
@ -167,22 +213,23 @@ void main()
|
|||
if (stc.z > 0.0)
|
||||
{
|
||||
stc.xy /= stc.w;
|
||||
|
||||
|
||||
float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0);
|
||||
|
||||
stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5);
|
||||
|
||||
if (stc.x < 1.0 &&
|
||||
stc.y < 1.0 &&
|
||||
stc.x > 0.0 &&
|
||||
stc.y > 0.0)
|
||||
{
|
||||
vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
|
||||
vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod);
|
||||
col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//attenuate point light contribution by SSAO component
|
||||
col *= texture2DRect(lightMap, frag.xy).g;
|
||||
|
||||
gl_FragColor.rgb = col;
|
||||
gl_FragColor.a = 0.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ uniform sampler2DRect diffuseRect;
|
|||
uniform sampler2DRect specularRect;
|
||||
uniform sampler2DRect normalMap;
|
||||
uniform sampler2DRect lightMap;
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2D noiseMap;
|
||||
uniform samplerCube environmentMap;
|
||||
uniform sampler2D lightFunc;
|
||||
|
|
@ -41,7 +42,6 @@ uniform vec3 env_mat[3];
|
|||
uniform vec4 shadow_clip;
|
||||
uniform mat3 ssao_effect_mat;
|
||||
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform mat4 inv_proj;
|
||||
uniform vec2 screen_res;
|
||||
|
||||
|
|
@ -275,20 +275,12 @@ void main()
|
|||
{
|
||||
vec3 ref = normalize(reflect(pos.xyz, norm.xyz));
|
||||
float sa = dot(ref, vary_light.xyz);
|
||||
col.rgb += vary_SunlitColor*scol*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
|
||||
col.rgb += vary_SunlitColor*scol_ambocc.r*spec.rgb*texture2D(lightFunc, vec2(sa, spec.a)).a;
|
||||
}
|
||||
|
||||
col = atmosLighting(col);
|
||||
col = scaleSoftClip(col);
|
||||
|
||||
gl_FragColor.rgb = col;
|
||||
|
||||
//gl_FragColor.rgb = gi_col.rgb;
|
||||
gl_FragColor.a = 0.0;
|
||||
|
||||
//gl_FragColor.rg = scol_ambocc.rg;
|
||||
//gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb;
|
||||
//gl_FragColor.rgb = norm.rgb*0.5+0.5;
|
||||
//gl_FragColor.rgb = vec3(ambocc);
|
||||
//gl_FragColor.rgb = vec3(scol);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,21 +179,6 @@ void main()
|
|||
}
|
||||
}
|
||||
|
||||
/*if (spec.a > 0.0)
|
||||
{
|
||||
//vec3 ref = reflect(normalize(pos), norm);
|
||||
float sa = dot(normalize(lv-normalize(pos)),norm);;
|
||||
//sa = max(sa, 0.0);
|
||||
//sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0);
|
||||
sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
|
||||
sa *= noise;
|
||||
col += da*sa*lcol*spec.rgb;
|
||||
}*/
|
||||
|
||||
//attenuate point light contribution by SSAO component
|
||||
col *= texture2DRect(lightMap, frag.xy).g;
|
||||
|
||||
|
||||
gl_FragColor.rgb = col;
|
||||
gl_FragColor.a = 0.0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
//class 2, shadows, no SSAO
|
||||
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2DRect normalMap;
|
||||
uniform sampler2DRectShadow shadowMap0;
|
||||
|
|
@ -52,56 +54,6 @@ vec4 getPosition(vec2 pos_screen)
|
|||
return pos;
|
||||
}
|
||||
|
||||
//calculate decreases in ambient lighting when crowded out (SSAO)
|
||||
float calcAmbientOcclusion(vec4 pos, vec3 norm)
|
||||
{
|
||||
vec2 kern[8];
|
||||
// exponentially (^2) distant occlusion samples spread around origin
|
||||
kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
|
||||
kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
|
||||
kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
|
||||
kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
|
||||
kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
|
||||
kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
|
||||
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
|
||||
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
|
||||
|
||||
vec2 pos_screen = vary_fragcoord.xy;
|
||||
vec3 pos_world = pos.xyz;
|
||||
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
|
||||
|
||||
float angle_hidden = 0.0;
|
||||
int points = 0;
|
||||
|
||||
float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
|
||||
|
||||
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
|
||||
vec3 samppos_world = getPosition(samppos_screen).xyz;
|
||||
|
||||
vec3 diff = pos_world - samppos_world;
|
||||
float dist2 = dot(diff, diff);
|
||||
|
||||
// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
|
||||
// --> solid angle shrinking by the square of distance
|
||||
//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
|
||||
//(k should vary inversely with # of samples, but this is taken care of later)
|
||||
|
||||
//if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces
|
||||
// angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor)
|
||||
angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
|
||||
|
||||
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
|
||||
points = points + int(diff.z > -1.0);
|
||||
}
|
||||
|
||||
angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
|
||||
|
||||
return (1.0 - (float(points != 0) * angle_hidden));
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
|
|
@ -149,7 +101,9 @@ void main()
|
|||
|
||||
vec4 pos = getPosition(pos_screen);
|
||||
|
||||
vec3 norm = texture2DRect(normalMap, pos_screen).xyz*2.0-1.0;
|
||||
vec4 nmap4 = texture2DRect(normalMap, pos_screen);
|
||||
float displace = nmap4.w;
|
||||
vec3 norm = nmap4.xyz*2.0-1.0;
|
||||
|
||||
/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
|
||||
{
|
||||
|
|
@ -158,9 +112,9 @@ void main()
|
|||
}*/
|
||||
|
||||
float shadow = 1.0;
|
||||
float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
|
||||
float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
|
||||
|
||||
vec4 spos = vec4(pos.xyz + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0);
|
||||
vec4 spos = vec4(pos.xyz + displace*norm + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0);
|
||||
|
||||
if (spos.z > -shadow_clip.w)
|
||||
{
|
||||
|
|
@ -220,15 +174,15 @@ void main()
|
|||
}
|
||||
|
||||
gl_FragColor[0] = shadow;
|
||||
gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
|
||||
gl_FragColor[1] = 1.0;
|
||||
|
||||
//spotlight shadow 1
|
||||
vec4 lpos = shadow_matrix[4]*spos;
|
||||
gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.1).x;
|
||||
gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x;
|
||||
|
||||
//spotlight shadow 2
|
||||
lpos = shadow_matrix[5]*spos;
|
||||
gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.1).x;
|
||||
gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x;
|
||||
|
||||
//gl_FragColor.rgb = pos.xyz;
|
||||
//gl_FragColor.b = shadow;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,248 @@
|
|||
/**
|
||||
* @file sunLightSSAOF.glsl
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
//class 2 -- shadows and SSAO
|
||||
|
||||
uniform sampler2DRect depthMap;
|
||||
uniform sampler2DRect normalMap;
|
||||
uniform sampler2DRectShadow shadowMap0;
|
||||
uniform sampler2DRectShadow shadowMap1;
|
||||
uniform sampler2DRectShadow shadowMap2;
|
||||
uniform sampler2DRectShadow shadowMap3;
|
||||
uniform sampler2DShadow shadowMap4;
|
||||
uniform sampler2DShadow shadowMap5;
|
||||
uniform sampler2D noiseMap;
|
||||
|
||||
uniform sampler2D lightFunc;
|
||||
|
||||
// Inputs
|
||||
uniform mat4 shadow_matrix[6];
|
||||
uniform vec4 shadow_clip;
|
||||
uniform float ssao_radius;
|
||||
uniform float ssao_max_radius;
|
||||
uniform float ssao_factor;
|
||||
uniform float ssao_factor_inv;
|
||||
|
||||
varying vec2 vary_fragcoord;
|
||||
varying vec4 vary_light;
|
||||
|
||||
uniform mat4 inv_proj;
|
||||
uniform vec2 screen_res;
|
||||
uniform vec2 shadow_res;
|
||||
uniform vec2 proj_shadow_res;
|
||||
|
||||
uniform float shadow_bias;
|
||||
uniform float shadow_offset;
|
||||
|
||||
vec4 getPosition(vec2 pos_screen)
|
||||
{
|
||||
float depth = texture2DRect(depthMap, pos_screen.xy).a;
|
||||
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;
|
||||
}
|
||||
|
||||
//calculate decreases in ambient lighting when crowded out (SSAO)
|
||||
float calcAmbientOcclusion(vec4 pos, vec3 norm)
|
||||
{
|
||||
float ret = 1.0;
|
||||
|
||||
float dist = dot(pos.xyz,pos.xyz);
|
||||
|
||||
if (dist < 64.0*64.0)
|
||||
{
|
||||
vec2 kern[8];
|
||||
// exponentially (^2) distant occlusion samples spread around origin
|
||||
kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
|
||||
kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
|
||||
kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
|
||||
kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
|
||||
kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
|
||||
kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
|
||||
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
|
||||
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
|
||||
|
||||
vec2 pos_screen = vary_fragcoord.xy;
|
||||
vec3 pos_world = pos.xyz;
|
||||
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
|
||||
|
||||
float angle_hidden = 0.0;
|
||||
int points = 0;
|
||||
|
||||
float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
|
||||
|
||||
// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
|
||||
vec3 samppos_world = getPosition(samppos_screen).xyz;
|
||||
|
||||
vec3 diff = pos_world - samppos_world;
|
||||
float dist2 = dot(diff, diff);
|
||||
|
||||
// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
|
||||
// --> solid angle shrinking by the square of distance
|
||||
//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
|
||||
//(k should vary inversely with # of samples, but this is taken care of later)
|
||||
|
||||
//if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces
|
||||
// angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor)
|
||||
angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
|
||||
|
||||
// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
|
||||
points = points + int(diff.z > -1.0);
|
||||
}
|
||||
|
||||
angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
|
||||
|
||||
ret = (1.0 - (float(points != 0) * angle_hidden));
|
||||
ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0);
|
||||
}
|
||||
|
||||
return min(ret, 1.0);
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += shadow_bias*scl;
|
||||
|
||||
float cs = shadow2DRect(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs);
|
||||
shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs);
|
||||
|
||||
return shadow/5.0;
|
||||
|
||||
//return shadow;
|
||||
}
|
||||
|
||||
float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl)
|
||||
{
|
||||
stc.xyz /= stc.w;
|
||||
stc.z += shadow_bias*scl;
|
||||
|
||||
float cs = shadow2D(shadowMap, stc.xyz).x;
|
||||
float shadow = cs;
|
||||
|
||||
vec2 off = 1.5/proj_shadow_res;
|
||||
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs);
|
||||
shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs);
|
||||
|
||||
|
||||
return shadow/5.0;
|
||||
|
||||
//return shadow;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 pos_screen = vary_fragcoord.xy;
|
||||
|
||||
//try doing an unproject here
|
||||
|
||||
vec4 pos = getPosition(pos_screen);
|
||||
|
||||
vec4 nmap4 = texture2DRect(normalMap, pos_screen);
|
||||
float displace = nmap4.w;
|
||||
vec3 norm = nmap4.xyz*2.0-1.0;
|
||||
|
||||
/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
|
||||
{
|
||||
gl_FragColor = vec4(0.0); // doesn't matter
|
||||
return;
|
||||
}*/
|
||||
|
||||
float shadow = 1.0;
|
||||
float dp_directional_light = max(0.0, dot(norm, vary_light.xyz));
|
||||
|
||||
vec4 spos = vec4(pos.xyz + displace*norm + vary_light.xyz * (1.0-dp_directional_light)*shadow_offset, 1.0);
|
||||
|
||||
if (spos.z > -shadow_clip.w)
|
||||
{
|
||||
if (dp_directional_light == 0.0)
|
||||
{
|
||||
// if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
|
||||
shadow = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vec4 lpos;
|
||||
|
||||
if (spos.z < -shadow_clip.z)
|
||||
{
|
||||
lpos = shadow_matrix[3]*spos;
|
||||
lpos.xy *= shadow_res;
|
||||
shadow = pcfShadow(shadowMap3, lpos, 0.25);
|
||||
shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
|
||||
}
|
||||
else if (spos.z < -shadow_clip.y)
|
||||
{
|
||||
lpos = shadow_matrix[2]*spos;
|
||||
lpos.xy *= shadow_res;
|
||||
shadow = pcfShadow(shadowMap2, lpos, 0.5);
|
||||
}
|
||||
else if (spos.z < -shadow_clip.x)
|
||||
{
|
||||
lpos = shadow_matrix[1]*spos;
|
||||
lpos.xy *= shadow_res;
|
||||
shadow = pcfShadow(shadowMap1, lpos, 0.75);
|
||||
}
|
||||
else
|
||||
{
|
||||
lpos = shadow_matrix[0]*spos;
|
||||
lpos.xy *= shadow_res;
|
||||
shadow = pcfShadow(shadowMap0, lpos, 1.0);
|
||||
}
|
||||
|
||||
// take the most-shadowed value out of these two:
|
||||
// * the blurred sun shadow in the light (shadow) map
|
||||
// * an unblurred dot product between the sun and this norm
|
||||
// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
|
||||
shadow = min(shadow, dp_directional_light);
|
||||
|
||||
//lpos.xy /= lpos.w*32.0;
|
||||
//if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
|
||||
//{
|
||||
// shadow = 0.0;
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// more distant than the shadow map covers
|
||||
shadow = 1.0;
|
||||
}
|
||||
|
||||
gl_FragColor[0] = shadow;
|
||||
gl_FragColor[1] = calcAmbientOcclusion(pos, norm);
|
||||
|
||||
//spotlight shadow 1
|
||||
vec4 lpos = shadow_matrix[4]*spos;
|
||||
gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x;
|
||||
|
||||
//spotlight shadow 2
|
||||
lpos = shadow_matrix[5]*spos;
|
||||
gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x;
|
||||
|
||||
//gl_FragColor.rgb = pos.xyz;
|
||||
//gl_FragColor.b = shadow;
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
float calcDirectionalLight(vec3 n, vec3 l);
|
||||
float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
|
||||
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
|
||||
|
||||
vec3 atmosAmbient(vec3 light);
|
||||
vec3 atmosAffectDirectionalLight(float lightIntensity);
|
||||
|
|
@ -18,9 +18,10 @@ vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
|
|||
|
||||
// Collect normal lights (need to be divided by two, as we later multiply by 2)
|
||||
col.rgb += gl_LightSource[1].diffuse.rgb * calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
|
||||
col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
|
||||
col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
|
||||
//col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
|
||||
|
||||
col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a);
|
||||
col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a);
|
||||
//col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a);
|
||||
col.rgb = scaleDownLight(col.rgb);
|
||||
|
||||
// Add windlight lights
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
float calcDirectionalLight(vec3 n, vec3 l);
|
||||
float calcPointLight(vec3 v, vec3 n, vec4 lp, float la);
|
||||
float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
|
||||
|
||||
vec3 atmosAmbient(vec3 light);
|
||||
vec3 atmosAffectDirectionalLight(float lightIntensity);
|
||||
|
|
@ -15,24 +15,21 @@ vec3 scaleUpLight(vec3 light);
|
|||
|
||||
vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
|
||||
{
|
||||
vec4 col;
|
||||
col.a = color.a;
|
||||
vec4 col = vec4(0.0, 0.0, 0.0, color.a);
|
||||
|
||||
// Add windlight lights
|
||||
col.rgb = atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz));
|
||||
col.rgb += atmosAmbient(baseLight.rgb);
|
||||
col.rgb = scaleUpLight(col.rgb);
|
||||
|
||||
// Collect normal lights (need to be divided by two, as we later multiply by 2)
|
||||
col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation);
|
||||
col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation);
|
||||
col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation);
|
||||
col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation);
|
||||
col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation);
|
||||
col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation);
|
||||
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].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].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].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].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].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].specular.a);
|
||||
col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
|
||||
col.rgb = scaleDownLight(col.rgb);
|
||||
|
||||
|
||||
// Add windlight lights
|
||||
col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz));
|
||||
col.rgb += atmosAmbient(baseLight.rgb);
|
||||
|
||||
col.rgb = min(col.rgb*color.rgb, 1.0);
|
||||
|
||||
|
|
|
|||
|
|
@ -12,14 +12,12 @@
|
|||
<RenderFlexTimeFactor value="1"/>
|
||||
<!--256... but they don't use this-->
|
||||
<RenderGlowResolutionPow value="9"/>
|
||||
<!--Sun/Moon only-->
|
||||
<RenderLightingDetail value="1"/>
|
||||
<!--Low number-->
|
||||
<RenderMaxPartCount value="4096"/>
|
||||
<!--bump okay-->
|
||||
<RenderObjectBump value="TRUE"/>
|
||||
<!--NO SHADERS-->
|
||||
<RenderReflectionDetail value="3"/>
|
||||
<RenderReflectionDetail value="4"/>
|
||||
<!--Simple-->
|
||||
<RenderTerrainDetail value="1"/>
|
||||
<!--Default for now-->
|
||||
|
|
@ -31,9 +29,14 @@
|
|||
<!--Default for now-->
|
||||
<RenderVolumeLODFactor value="2.0"/>
|
||||
<!--NO SHADERS-->
|
||||
<RenderWaterReflections value="TRUE"/>
|
||||
<!--NO SHADERS-->
|
||||
<VertexShaderEnable value="TRUE"/>
|
||||
<!--NO SHADERS-->
|
||||
<WindLightUseAtmosShaders value="TRUE"/>
|
||||
<!--Deferred Shading-->
|
||||
<RenderDeferred value="TRUE"/>
|
||||
<!--SSAO Enabled-->
|
||||
<RenderDeferredSSAO value="TRUE"/>
|
||||
<!--Full Shadows-->
|
||||
<RenderShadowDetail value="2"/>
|
||||
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ version 21
|
|||
// NOTE: All settings are set to the MIN of applied values, including 'all'!
|
||||
//
|
||||
list all
|
||||
RenderAnisotropic 1 0
|
||||
RenderAnisotropic 1 1
|
||||
RenderAvatarCloth 1 1
|
||||
RenderAvatarLODFactor 1 1.0
|
||||
RenderAvatarVP 1 1
|
||||
|
|
@ -35,18 +35,16 @@ RenderFogRatio 1 4.0
|
|||
RenderGamma 1 0
|
||||
RenderGlowResolutionPow 1 9
|
||||
RenderGround 1 1
|
||||
RenderLightingDetail 1 1
|
||||
RenderMaxPartCount 1 8192
|
||||
RenderNightBrightness 1 1.0
|
||||
RenderObjectBump 1 1
|
||||
RenderReflectionDetail 1 3
|
||||
RenderReflectionDetail 1 4
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTreeLODFactor 1 1.0
|
||||
RenderUseImpostors 1 1
|
||||
RenderVBOEnable 1 1
|
||||
RenderVolumeLODFactor 1 2.0
|
||||
RenderWaterReflections 1 1
|
||||
UseStartScreen 1 1
|
||||
UseOcclusion 1 1
|
||||
VertexShaderEnable 1 1
|
||||
|
|
@ -56,6 +54,9 @@ Disregard128DefaultDrawDistance 1 1
|
|||
Disregard96DefaultDrawDistance 1 1
|
||||
RenderTextureMemoryMultiple 1 1.0
|
||||
RenderShaderLightingMaxLevel 1 3
|
||||
RenderDeferred 1 1
|
||||
RenderDeferredSSAO 1 1
|
||||
RenderShadowDetail 1 2
|
||||
|
||||
|
||||
//
|
||||
|
|
@ -69,7 +70,6 @@ RenderAvatarVP 1 0
|
|||
RenderFarClip 1 64
|
||||
RenderFlexTimeFactor 1 0.5
|
||||
RenderGlowResolutionPow 1 8
|
||||
RenderLightingDetail 1 0
|
||||
RenderMaxPartCount 1 1024
|
||||
RenderObjectBump 1 0
|
||||
RenderReflectionDetail 1 0
|
||||
|
|
@ -78,10 +78,13 @@ RenderTerrainLODFactor 1 1
|
|||
RenderTreeLODFactor 1 0.5
|
||||
RenderUseImpostors 1 1
|
||||
RenderVolumeLODFactor 1 1.125
|
||||
RenderWaterReflections 1 0
|
||||
VertexShaderEnable 1 0
|
||||
WindLightUseAtmosShaders 1 0
|
||||
WLSkyDetail 1 48
|
||||
RenderDeferred 1 0
|
||||
RenderDeferredSSAO 1 0
|
||||
RenderShadowDetail 1 0
|
||||
|
||||
|
||||
//
|
||||
// Mid Graphics Settings
|
||||
|
|
@ -94,7 +97,6 @@ RenderAvatarVP 1 1
|
|||
RenderFarClip 1 96
|
||||
RenderFlexTimeFactor 1 1.0
|
||||
RenderGlowResolutionPow 1 8
|
||||
RenderLightingDetail 1 1
|
||||
RenderMaxPartCount 1 2048
|
||||
RenderObjectBump 1 1
|
||||
RenderReflectionDetail 1 0
|
||||
|
|
@ -103,10 +105,13 @@ RenderTerrainLODFactor 1 1.0
|
|||
RenderTreeLODFactor 1 0.5
|
||||
RenderUseImpostors 1 1
|
||||
RenderVolumeLODFactor 1 1.125
|
||||
RenderWaterReflections 1 0
|
||||
VertexShaderEnable 1 1
|
||||
WindLightUseAtmosShaders 1 0
|
||||
WLSkyDetail 1 48
|
||||
RenderDeferred 1 0
|
||||
RenderDeferredSSAO 1 0
|
||||
RenderShadowDetail 1 0
|
||||
|
||||
|
||||
//
|
||||
// High Graphics Settings (purty)
|
||||
|
|
@ -119,7 +124,6 @@ RenderAvatarVP 1 1
|
|||
RenderFarClip 1 128
|
||||
RenderFlexTimeFactor 1 1.0
|
||||
RenderGlowResolutionPow 1 9
|
||||
RenderLightingDetail 1 1
|
||||
RenderMaxPartCount 1 4096
|
||||
RenderObjectBump 1 1
|
||||
RenderReflectionDetail 1 2
|
||||
|
|
@ -128,10 +132,13 @@ RenderTerrainLODFactor 1 2.0
|
|||
RenderTreeLODFactor 1 0.5
|
||||
RenderUseImpostors 1 1
|
||||
RenderVolumeLODFactor 1 1.125
|
||||
RenderWaterReflections 1 0
|
||||
VertexShaderEnable 1 1
|
||||
WindLightUseAtmosShaders 1 1
|
||||
WLSkyDetail 1 48
|
||||
RenderDeferred 1 1
|
||||
RenderDeferredSSAO 1 0
|
||||
RenderShadowDetail 1 1
|
||||
|
||||
|
||||
//
|
||||
// Ultra graphics (REALLY PURTY!)
|
||||
|
|
@ -144,19 +151,21 @@ RenderAvatarVP 1 1
|
|||
RenderFarClip 1 256
|
||||
RenderFlexTimeFactor 1 1.0
|
||||
RenderGlowResolutionPow 1 9
|
||||
RenderLightingDetail 1 1
|
||||
RenderMaxPartCount 1 8192
|
||||
RenderObjectBump 1 1
|
||||
RenderReflectionDetail 1 3
|
||||
RenderReflectionDetail 1 4
|
||||
RenderTerrainDetail 1 1
|
||||
RenderTerrainLODFactor 1 2.0
|
||||
RenderTreeLODFactor 1 1.0
|
||||
RenderUseImpostors 1 1
|
||||
RenderVolumeLODFactor 1 2.0
|
||||
RenderWaterReflections 1 1
|
||||
VertexShaderEnable 1 1
|
||||
WindLightUseAtmosShaders 1 1
|
||||
WLSkyDetail 1 128
|
||||
RenderDeferred 1 1
|
||||
RenderDeferredSSAO 1 1
|
||||
RenderShadowDetail 1 2
|
||||
|
||||
|
||||
//
|
||||
// Class Unknown Hardware (unknown)
|
||||
|
|
@ -194,9 +203,12 @@ RenderVBOEnable 1 1
|
|||
list NoPixelShaders
|
||||
RenderAvatarVP 0 0
|
||||
RenderAvatarCloth 0 0
|
||||
RenderWaterReflections 0 0
|
||||
RenderReflectionDetail 0 0
|
||||
VertexShaderEnable 0 0
|
||||
WindLightUseAtmosShaders 0 0
|
||||
RenderDeferred 0 0
|
||||
RenderDeferredSSAO 0 0
|
||||
RenderShadowDetail 0 0
|
||||
|
||||
//
|
||||
// No Vertex Shaders available
|
||||
|
|
@ -204,9 +216,13 @@ WindLightUseAtmosShaders 0 0
|
|||
list NoVertexShaders
|
||||
RenderAvatarVP 0 0
|
||||
RenderAvatarCloth 0 0
|
||||
RenderWaterReflections 0 0
|
||||
RenderReflectionDetail 0 0
|
||||
VertexShaderEnable 0 0
|
||||
WindLightUseAtmosShaders 0 0
|
||||
RenderDeferred 0 0
|
||||
RenderDeferredSSAO 0 0
|
||||
RenderShadowDetail 0 0
|
||||
|
||||
|
||||
// "Default" setups for safe, low, medium, high
|
||||
//
|
||||
|
|
@ -214,14 +230,17 @@ list safe
|
|||
RenderAnisotropic 1 0
|
||||
RenderAvatarCloth 0 0
|
||||
RenderAvatarVP 0 0
|
||||
RenderLightingDetail 1 0
|
||||
RenderObjectBump 0 0
|
||||
RenderMaxPartCount 1 1024
|
||||
RenderTerrainDetail 1 0
|
||||
RenderUseImpostors 0 0
|
||||
RenderVBOEnable 1 0
|
||||
RenderWaterReflections 0 0
|
||||
RenderReflectionDetail 0 0
|
||||
WindLightUseAtmosShaders 0 0
|
||||
RenderDeferred 0 0
|
||||
RenderDeferredSSAO 0 0
|
||||
RenderShadowDetail 0 0
|
||||
|
||||
|
||||
//
|
||||
// CPU based feature masks
|
||||
|
|
@ -245,11 +264,9 @@ RenderVBOEnable 1 0
|
|||
|
||||
list Intel
|
||||
RenderAnisotropic 1 0
|
||||
RenderLightingDetail 1 0
|
||||
|
||||
list GeForce2
|
||||
RenderAnisotropic 1 0
|
||||
RenderLightingDetail 1 0
|
||||
RenderMaxPartCount 1 2048
|
||||
RenderTerrainDetail 1 0
|
||||
RenderVBOEnable 1 1
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ list ATI_Radeon_X1500
|
|||
Disregard128DefaultDrawDistance 1 0
|
||||
list ATI_Radeon_X1600
|
||||
Disregard128DefaultDrawDistance 1 0
|
||||
RenderUseFBO 0 0
|
||||
list ATI_Radeon_X1700
|
||||
Disregard128DefaultDrawDistance 1 0
|
||||
list ATI_Mobility_Radeon_X1xxx
|
||||
|
|
|
|||
|
|
@ -769,3 +769,72 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
=============
|
||||
GLOD license
|
||||
=============
|
||||
The GLOD Open-Source License Version 1.0 June 16, 2004
|
||||
|
||||
Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns
|
||||
Hopkins University and David Luebke, Brenden Schubert, University of
|
||||
Virginia. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, is permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer and
|
||||
request.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer and
|
||||
request in the documentation and/or other materials provided with
|
||||
the distribution.
|
||||
|
||||
3. The name "GLOD" must not be used to endorse or promote products
|
||||
derived from this software without prior written permission.
|
||||
|
||||
4. Redistributions of any modified version of this source, whether in
|
||||
source or binary form , must include a form of the following
|
||||
acknowledgment: "This product is derived from the GLOD library,
|
||||
which is available from http://www.cs.jhu.edu/~graphics/GLOD."
|
||||
|
||||
5. Redistributions of any modified version of this source in binary
|
||||
form must provide, free of charge, access to the modified version
|
||||
of the code.
|
||||
|
||||
6. This license shall be governed by and construed and enforced in
|
||||
accordance with the laws of the State of Maryland, without
|
||||
reference to its conflicts of law provisions. The exclusive
|
||||
jurisdiction and venue for all legal actions relating to this
|
||||
license shall be in courts of competent subject matter jurisdiction
|
||||
located in the State of Maryland.
|
||||
|
||||
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, GLOD IS PROVIDED
|
||||
UNDER THIS LICENSE ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND,
|
||||
EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
THAT GLOD IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
|
||||
PURPOSE OR NON-INFRINGING. ALL WARRANTIES ARE DISCLAIMED AND THE
|
||||
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE CODE IS WITH
|
||||
YOU. SHOULD ANY CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
|
||||
COPYRIGHT HOLDER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
|
||||
NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY
|
||||
CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY CODE IS
|
||||
AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
|
||||
|
||||
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
|
||||
THE COPYRIGHT HOLDER OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
|
||||
SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES FOR LOSS OF
|
||||
PROFITS, REVENUE, OR FOR LOSS OF INFORMATION OR ANY OTHER LOSS.
|
||||
|
||||
YOU EXPRESSLY AGREE TO FOREVER INDEMNIFY, DEFEND AND HOLD HARMLESS THE
|
||||
COPYRIGHT HOLDERS AND CONTRIBUTORS OF GLOD AGAINST ALL CLAIMS,
|
||||
DEMANDS, SUITS OR OTHER ACTIONS ARISING DIRECTLY OR INDIRECTLY FROM
|
||||
YOUR ACCEPTANCE AND USE OF GLOD.
|
||||
|
||||
Although NOT REQUIRED, we would appreciate it if active users of GLOD
|
||||
put a link on their web site to the GLOD web site when possible.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "llwindow.h"
|
||||
#include "llviewerstats.h"
|
||||
#include "llmd5.h"
|
||||
#include "llmeshrepository.h"
|
||||
#include "llpumpio.h"
|
||||
#include "llmimetypes.h"
|
||||
#include "llslurl.h"
|
||||
|
|
@ -77,6 +78,7 @@
|
|||
#include "llteleporthistory.h"
|
||||
#include "lllocationhistory.h"
|
||||
#include "llfasttimerview.h"
|
||||
#include "llviewermenufile.h"
|
||||
#include "llvoicechannel.h"
|
||||
#include "llsidetray.h"
|
||||
|
||||
|
|
@ -920,6 +922,9 @@ static LLFastTimer::DeclareTimer FTM_LFS("LFS Thread");
|
|||
static LLFastTimer::DeclareTimer FTM_PAUSE_THREADS("Pause Threads");
|
||||
static LLFastTimer::DeclareTimer FTM_IDLE("Idle");
|
||||
static LLFastTimer::DeclareTimer FTM_PUMP("Pump");
|
||||
static LLFastTimer::DeclareTimer FTM_PUMP_ARES("Ares");
|
||||
static LLFastTimer::DeclareTimer FTM_PUMP_SERVICE("Service");
|
||||
static LLFastTimer::DeclareTimer FTM_SERVICE_CALLBACK("Callback");
|
||||
|
||||
bool LLAppViewer::mainLoop()
|
||||
{
|
||||
|
|
@ -1031,10 +1036,20 @@ bool LLAppViewer::mainLoop()
|
|||
LLMemType mt_ip(LLMemType::MTYPE_IDLE_PUMP);
|
||||
pingMainloopTimeout("Main:ServicePump");
|
||||
LLFastTimer t4(FTM_PUMP);
|
||||
gAres->process();
|
||||
// this pump is necessary to make the login screen show up
|
||||
gServicePump->pump();
|
||||
gServicePump->callback();
|
||||
{
|
||||
LLFastTimer t(FTM_PUMP_ARES);
|
||||
gAres->process();
|
||||
}
|
||||
{
|
||||
LLFastTimer t(FTM_PUMP_SERVICE);
|
||||
// this pump is necessary to make the login screen show up
|
||||
gServicePump->pump();
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_SERVICE_CALLBACK);
|
||||
gServicePump->callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resumeMainloopTimeout();
|
||||
|
|
@ -1273,6 +1288,9 @@ bool LLAppViewer::cleanup()
|
|||
|
||||
llinfos << "Cleaning Up" << llendflush;
|
||||
|
||||
// shut down mesh streamer
|
||||
gMeshRepo.shutdown();
|
||||
|
||||
// Must clean up texture references before viewer window is destroyed.
|
||||
LLHUDManager::getInstance()->updateEffects();
|
||||
LLHUDObject::updateAll();
|
||||
|
|
@ -1549,6 +1567,8 @@ bool LLAppViewer::cleanup()
|
|||
sTextureFetch->shutDownTextureCacheThread() ;
|
||||
sTextureFetch->shutDownImageDecodeThread() ;
|
||||
|
||||
LLFilePickerThread::cleanupClass();
|
||||
|
||||
delete sTextureCache;
|
||||
sTextureCache = NULL;
|
||||
delete sTextureFetch;
|
||||
|
|
@ -1696,6 +1716,11 @@ bool LLAppViewer::initThreads()
|
|||
mFastTimerLogThread->start();
|
||||
}
|
||||
|
||||
// Mesh streaming and caching
|
||||
gMeshRepo.init();
|
||||
|
||||
LLFilePickerThread::initClass();
|
||||
|
||||
// *FIX: no error handling here!
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2409,6 +2434,7 @@ bool LLAppViewer::initWindow()
|
|||
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
|
||||
|
||||
gPipeline.init();
|
||||
|
||||
stop_glerror();
|
||||
gViewerWindow->initGLDefaults();
|
||||
|
||||
|
|
@ -3394,6 +3420,10 @@ static LLFastTimer::DeclareTimer FTM_OBJECTLIST_UPDATE("Update Objectlist");
|
|||
static LLFastTimer::DeclareTimer FTM_REGION_UPDATE("Update Region");
|
||||
static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World");
|
||||
static LLFastTimer::DeclareTimer FTM_NETWORK("Network");
|
||||
static LLFastTimer::DeclareTimer FTM_AGENT_NETWORK("Agent Network");
|
||||
static LLFastTimer::DeclareTimer FTM_AGENT_AUTOPILOT("Autopilot");
|
||||
static LLFastTimer::DeclareTimer FTM_AGENT_UPDATE("Update");
|
||||
static LLFastTimer::DeclareTimer FTM_VLMANAGER("VL Manager");
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// idle()
|
||||
|
|
@ -3414,6 +3444,8 @@ void LLAppViewer::idle()
|
|||
LLEventTimer::updateClass();
|
||||
LLCriticalDamp::updateInterpolants();
|
||||
LLMortician::updateClass();
|
||||
LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify()
|
||||
|
||||
F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
|
||||
|
||||
// Cap out-of-control frame times
|
||||
|
|
@ -3464,7 +3496,7 @@ void LLAppViewer::idle()
|
|||
|
||||
if (!gDisconnected)
|
||||
{
|
||||
LLFastTimer t(FTM_NETWORK);
|
||||
LLFastTimer t(FTM_AGENT_NETWORK);
|
||||
// Update spaceserver timeinfo
|
||||
LLWorld::getInstance()->setSpaceTimeUSec(LLWorld::getInstance()->getSpaceTimeUSec() + (U32)(dt_raw * SEC_TO_MICROSEC));
|
||||
|
||||
|
|
@ -3479,9 +3511,12 @@ void LLAppViewer::idle()
|
|||
gAgent.moveYaw(-1.f);
|
||||
}
|
||||
|
||||
// Handle automatic walking towards points
|
||||
gAgentPilot.updateTarget();
|
||||
gAgent.autoPilot(&yaw);
|
||||
{
|
||||
LLFastTimer t(FTM_AGENT_AUTOPILOT);
|
||||
// Handle automatic walking towards points
|
||||
gAgentPilot.updateTarget();
|
||||
gAgent.autoPilot(&yaw);
|
||||
}
|
||||
|
||||
static LLFrameTimer agent_update_timer;
|
||||
static U32 last_control_flags;
|
||||
|
|
@ -3492,6 +3527,7 @@ void LLAppViewer::idle()
|
|||
|
||||
if (flags_changed || (agent_update_time > (1.0f / (F32) AGENT_UPDATES_PER_SECOND)))
|
||||
{
|
||||
LLFastTimer t(FTM_AGENT_UPDATE);
|
||||
// Send avatar and camera info
|
||||
last_control_flags = gAgent.getControlFlags();
|
||||
send_agent_update(TRUE);
|
||||
|
|
@ -3657,7 +3693,7 @@ void LLAppViewer::idle()
|
|||
//
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_NETWORK);
|
||||
LLFastTimer t(FTM_VLMANAGER);
|
||||
gVLManager.unpackData();
|
||||
}
|
||||
|
||||
|
|
@ -3903,6 +3939,11 @@ static F32 CheckMessagesMaxTime = CHECK_MESSAGES_DEFAULT_MAX_TIME;
|
|||
#endif
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_IDLE_NETWORK("Idle Network");
|
||||
static LLFastTimer::DeclareTimer FTM_MESSAGE_ACKS("Message Acks");
|
||||
static LLFastTimer::DeclareTimer FTM_RETRANSMIT("Retransmit");
|
||||
static LLFastTimer::DeclareTimer FTM_TIMEOUT_CHECK("Timeout Check");
|
||||
static LLFastTimer::DeclareTimer FTM_DYNAMIC_THROTTLE("Dynamic Throttle");
|
||||
static LLFastTimer::DeclareTimer FTM_CHECK_REGION_CIRCUIT("Check Region Circuit");
|
||||
|
||||
void LLAppViewer::idleNetwork()
|
||||
{
|
||||
|
|
@ -3956,7 +3997,10 @@ void LLAppViewer::idleNetwork()
|
|||
}
|
||||
|
||||
// Handle per-frame message system processing.
|
||||
gMessageSystem->processAcks();
|
||||
{
|
||||
LLFastTimer ftm(FTM_MESSAGE_ACKS);
|
||||
gMessageSystem->processAcks();
|
||||
}
|
||||
|
||||
#ifdef TIME_THROTTLE_MESSAGES
|
||||
if (total_time >= CheckMessagesMaxTime)
|
||||
|
|
@ -3994,26 +4038,41 @@ void LLAppViewer::idleNetwork()
|
|||
LLViewerStats::getInstance()->mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects);
|
||||
|
||||
// Retransmit unacknowledged packets.
|
||||
gXferManager->retransmitUnackedPackets();
|
||||
gAssetStorage->checkForTimeouts();
|
||||
{
|
||||
LLFastTimer ftm(FTM_RETRANSMIT);
|
||||
gXferManager->retransmitUnackedPackets();
|
||||
}
|
||||
|
||||
{
|
||||
LLFastTimer ftm(FTM_TIMEOUT_CHECK);
|
||||
gAssetStorage->checkForTimeouts();
|
||||
}
|
||||
|
||||
llpushcallstacks ;
|
||||
gViewerThrottle.updateDynamicThrottle();
|
||||
|
||||
{
|
||||
LLFastTimer ftm(FTM_DYNAMIC_THROTTLE);
|
||||
gViewerThrottle.updateDynamicThrottle();
|
||||
}
|
||||
|
||||
llpushcallstacks ;
|
||||
// Check that the circuit between the viewer and the agent's current
|
||||
// region is still alive
|
||||
LLViewerRegion *agent_region = gAgent.getRegion();
|
||||
if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED))
|
||||
{
|
||||
LLUUID this_region_id = agent_region->getRegionID();
|
||||
bool this_region_alive = agent_region->isAlive();
|
||||
if ((mAgentRegionLastAlive && !this_region_alive) // newly dead
|
||||
&& (mAgentRegionLastID == this_region_id)) // same region
|
||||
LLFastTimer ftm(FTM_CHECK_REGION_CIRCUIT);
|
||||
LLViewerRegion *agent_region = gAgent.getRegion();
|
||||
if (agent_region && (LLStartUp::getStartupState()==STATE_STARTED))
|
||||
{
|
||||
forceDisconnect(LLTrans::getString("AgentLostConnection"));
|
||||
LLUUID this_region_id = agent_region->getRegionID();
|
||||
bool this_region_alive = agent_region->isAlive();
|
||||
if ((mAgentRegionLastAlive && !this_region_alive) // newly dead
|
||||
&& (mAgentRegionLastID == this_region_id)) // same region
|
||||
{
|
||||
forceDisconnect(LLTrans::getString("AgentLostConnection"));
|
||||
}
|
||||
mAgentRegionLastID = this_region_id;
|
||||
mAgentRegionLastAlive = this_region_alive;
|
||||
}
|
||||
mAgentRegionLastID = this_region_id;
|
||||
mAgentRegionLastAlive = this_region_alive;
|
||||
}
|
||||
llpushcallstacks ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "llfilepicker.h"
|
||||
#include "llinventoryobserver.h"
|
||||
#include "llinventorypanel.h"
|
||||
#include "llfloaterimportcollada.h"
|
||||
#include "llpermissionsflags.h"
|
||||
#include "llpreviewnotecard.h"
|
||||
#include "llpreviewscript.h"
|
||||
|
|
@ -65,6 +66,7 @@
|
|||
#include "llnotificationsutil.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llvfs.h"
|
||||
|
||||
// When uploading multiple files, don't display any of them when uploading more than this number.
|
||||
|
|
@ -72,6 +74,106 @@ static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5;
|
|||
|
||||
void dialog_refresh_all();
|
||||
|
||||
void on_new_single_inventory_upload_complete(
|
||||
LLAssetType::EType asset_type,
|
||||
LLInventoryType::EType inventory_type,
|
||||
const std::string inventory_type_string,
|
||||
const LLUUID& item_folder_id,
|
||||
const std::string& item_name,
|
||||
const std::string& item_description,
|
||||
const LLSD& server_response,
|
||||
S32 upload_price)
|
||||
{
|
||||
if ( upload_price > 0 )
|
||||
{
|
||||
// this upload costed us L$, update our balance
|
||||
// and display something saying that it cost L$
|
||||
LLStatusBar::sendMoneyBalanceRequest();
|
||||
|
||||
LLSD args;
|
||||
args["AMOUNT"] = llformat("%d", upload_price);
|
||||
LLNotificationsUtil::add("UploadPayment", args);
|
||||
}
|
||||
|
||||
if( item_folder_id.notNull() )
|
||||
{
|
||||
U32 everyone_perms = PERM_NONE;
|
||||
U32 group_perms = PERM_NONE;
|
||||
U32 next_owner_perms = PERM_ALL;
|
||||
if( server_response.has("new_next_owner_mask") )
|
||||
{
|
||||
// The server provided creation perms so use them.
|
||||
// Do not assume we got the perms we asked for in
|
||||
// since the server may not have granted them all.
|
||||
everyone_perms = server_response["new_everyone_mask"].asInteger();
|
||||
group_perms = server_response["new_group_mask"].asInteger();
|
||||
next_owner_perms = server_response["new_next_owner_mask"].asInteger();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The server doesn't provide creation perms
|
||||
// so use old assumption-based perms.
|
||||
if( inventory_type_string != "snapshot")
|
||||
{
|
||||
next_owner_perms = PERM_MOVE | PERM_TRANSFER;
|
||||
}
|
||||
}
|
||||
|
||||
LLPermissions new_perms;
|
||||
new_perms.init(
|
||||
gAgent.getID(),
|
||||
gAgent.getID(),
|
||||
LLUUID::null,
|
||||
LLUUID::null);
|
||||
|
||||
new_perms.initMasks(
|
||||
PERM_ALL,
|
||||
PERM_ALL,
|
||||
everyone_perms,
|
||||
group_perms,
|
||||
next_owner_perms);
|
||||
|
||||
S32 creation_date_now = time_corrected();
|
||||
LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
|
||||
server_response["new_inventory_item"].asUUID(),
|
||||
item_folder_id,
|
||||
new_perms,
|
||||
server_response["new_asset"].asUUID(),
|
||||
asset_type,
|
||||
inventory_type,
|
||||
item_name,
|
||||
item_description,
|
||||
LLSaleInfo::DEFAULT,
|
||||
LLInventoryItem::II_FLAGS_NONE,
|
||||
creation_date_now);
|
||||
|
||||
gInventory.updateItem(item);
|
||||
gInventory.notifyObservers();
|
||||
|
||||
// Show the preview panel for textures and sounds to let
|
||||
// user know that the image (or snapshot) arrived intact.
|
||||
LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel();
|
||||
if ( panel )
|
||||
{
|
||||
LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
|
||||
|
||||
panel->setSelection(
|
||||
server_response["new_inventory_item"].asUUID(),
|
||||
TAKE_FOCUS_NO);
|
||||
|
||||
// restore keyboard focus
|
||||
gFocusMgr.setKeyboardFocus(focus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Can't find a folder to put it in" << llendl;
|
||||
}
|
||||
|
||||
// remove the "Uploading..." message
|
||||
LLUploadDialog::modalUploadFinished();
|
||||
}
|
||||
|
||||
LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type)
|
||||
|
|
@ -89,9 +191,10 @@ LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
|
|||
}
|
||||
}
|
||||
|
||||
LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type)
|
||||
LLAssetUploadResponder::LLAssetUploadResponder(
|
||||
const LLSD &post_data,
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type)
|
||||
: LLHTTPClient::Responder(),
|
||||
mPostData(post_data),
|
||||
mFileName(file_name),
|
||||
|
|
@ -139,6 +242,7 @@ void LLAssetUploadResponder::result(const LLSD& content)
|
|||
lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl;
|
||||
|
||||
std::string state = content["state"];
|
||||
|
||||
if (state == "upload")
|
||||
{
|
||||
uploadUpload(content);
|
||||
|
|
@ -200,18 +304,38 @@ void LLAssetUploadResponder::uploadComplete(const LLSD& content)
|
|||
{
|
||||
}
|
||||
|
||||
LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data,
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type)
|
||||
: LLAssetUploadResponder(post_data, vfile_id, asset_type)
|
||||
LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(
|
||||
const LLSD& post_data,
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type)
|
||||
: LLAssetUploadResponder(post_data, vfile_id, asset_type)
|
||||
{
|
||||
}
|
||||
|
||||
LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type)
|
||||
: LLAssetUploadResponder(post_data, file_name, asset_type)
|
||||
LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(
|
||||
const LLSD& post_data,
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type)
|
||||
: LLAssetUploadResponder(post_data, file_name, asset_type)
|
||||
{
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLNewAgentInventoryResponder::error(U32 statusNum, const std::string& reason)
|
||||
{
|
||||
LLAssetUploadResponder::error(statusNum, reason);
|
||||
LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE);
|
||||
}
|
||||
|
||||
|
||||
//virtual
|
||||
void LLNewAgentInventoryResponder::uploadFailure(const LLSD& content)
|
||||
{
|
||||
LLAssetUploadResponder::uploadFailure(content);
|
||||
|
||||
LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], FALSE);
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
|
||||
{
|
||||
|
|
@ -223,95 +347,31 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
|
|||
|
||||
LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString());
|
||||
LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString());
|
||||
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
|
||||
S32 expected_upload_cost = 0;
|
||||
|
||||
// Update L$ and ownership credit information
|
||||
// since it probably changed on the server
|
||||
if (asset_type == LLAssetType::AT_TEXTURE ||
|
||||
asset_type == LLAssetType::AT_SOUND ||
|
||||
asset_type == LLAssetType::AT_ANIMATION)
|
||||
asset_type == LLAssetType::AT_ANIMATION ||
|
||||
asset_type == LLAssetType::AT_MESH)
|
||||
{
|
||||
LLStatusBar::sendMoneyBalanceRequest();
|
||||
|
||||
LLSD args;
|
||||
args["AMOUNT"] = llformat("%d", expected_upload_cost);
|
||||
LLNotificationsUtil::add("UploadPayment", args);
|
||||
expected_upload_cost =
|
||||
LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
|
||||
}
|
||||
|
||||
// Actually add the upload to viewer inventory
|
||||
llinfos << "Adding " << content["new_inventory_item"].asUUID() << " "
|
||||
<< content["new_asset"].asUUID() << " to inventory." << llendl;
|
||||
if(mPostData["folder_id"].asUUID().notNull())
|
||||
{
|
||||
//std::ostringstream out;
|
||||
//LLSDXMLFormatter *formatter = new LLSDXMLFormatter;
|
||||
//formatter->format(mPostData, out, LLSDFormatter::OPTIONS_PRETTY);
|
||||
//llinfos << "Post Data: " << out.str() << llendl;
|
||||
on_new_single_inventory_upload_complete(
|
||||
asset_type,
|
||||
inventory_type,
|
||||
mPostData["asset_type"].asString(),
|
||||
mPostData["folder_id"].asUUID(),
|
||||
mPostData["name"],
|
||||
mPostData["description"],
|
||||
content,
|
||||
expected_upload_cost);
|
||||
|
||||
U32 everyone_perms = PERM_NONE;
|
||||
U32 group_perms = PERM_NONE;
|
||||
U32 next_owner_perms = PERM_ALL;
|
||||
if(content.has("new_next_owner_mask"))
|
||||
{
|
||||
// This is a new sim that provides creation perms so use them.
|
||||
// Do not assume we got the perms we asked for in mPostData
|
||||
// since the sim may not have granted them all.
|
||||
everyone_perms = content["new_everyone_mask"].asInteger();
|
||||
group_perms = content["new_group_mask"].asInteger();
|
||||
next_owner_perms = content["new_next_owner_mask"].asInteger();
|
||||
}
|
||||
else
|
||||
{
|
||||
// This old sim doesn't provide creation perms so use old assumption-based perms.
|
||||
if(mPostData["inventory_type"].asString() != "snapshot")
|
||||
{
|
||||
next_owner_perms = PERM_MOVE | PERM_TRANSFER;
|
||||
}
|
||||
}
|
||||
LLPermissions new_perms;
|
||||
new_perms.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
|
||||
new_perms.initMasks(PERM_ALL, PERM_ALL, everyone_perms, group_perms, next_owner_perms);
|
||||
S32 creation_date_now = time_corrected();
|
||||
LLPointer<LLViewerInventoryItem> item
|
||||
= new LLViewerInventoryItem(content["new_inventory_item"].asUUID(),
|
||||
mPostData["folder_id"].asUUID(),
|
||||
new_perms,
|
||||
content["new_asset"].asUUID(),
|
||||
asset_type,
|
||||
inventory_type,
|
||||
mPostData["name"].asString(),
|
||||
mPostData["description"].asString(),
|
||||
LLSaleInfo::DEFAULT,
|
||||
LLInventoryItem::II_FLAGS_NONE,
|
||||
creation_date_now);
|
||||
gInventory.updateItem(item);
|
||||
gInventory.notifyObservers();
|
||||
// continue uploading for bulk uploads
|
||||
|
||||
// Show the preview panel for textures and sounds to let
|
||||
// user know that the image (or snapshot) arrived intact.
|
||||
LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel();
|
||||
if (active_panel)
|
||||
{
|
||||
active_panel->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO);
|
||||
if((LLAssetType::AT_TEXTURE == asset_type || LLAssetType::AT_SOUND == asset_type)
|
||||
&& LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD)
|
||||
{
|
||||
active_panel->openSelected();
|
||||
}
|
||||
//LLFloaterInventory::dumpSelectionInformation((void*)view);
|
||||
// restore keyboard focus
|
||||
LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
|
||||
gFocusMgr.setKeyboardFocus(focus);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Can't find a folder to put it in" << llendl;
|
||||
}
|
||||
|
||||
// remove the "Uploading..." message
|
||||
LLUploadDialog::modalUploadFinished();
|
||||
|
||||
// *FIX: This is a pretty big hack. What this does is check the
|
||||
// file picker if there are any more pending uploads. If so,
|
||||
// upload that file.
|
||||
|
|
@ -328,19 +388,42 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
|
|||
|
||||
// Continuing the horrible hack above, we need to extract the originally requested permissions data, if any,
|
||||
// and use them for each next file to be uploaded. Note the requested perms are not the same as the
|
||||
// granted ones found in the given "content" structure but can still be found in mPostData. -MG
|
||||
U32 everyone_perms = mPostData.has("everyone_mask") ? mPostData.get("everyone_mask" ).asInteger() : PERM_NONE;
|
||||
U32 group_perms = mPostData.has("group_mask") ? mPostData.get("group_mask" ).asInteger() : PERM_NONE;
|
||||
U32 next_owner_perms = mPostData.has("next_owner_mask") ? mPostData.get("next_owner_mask").asInteger() : PERM_NONE;
|
||||
U32 everyone_perms =
|
||||
content.has("everyone_mask") ?
|
||||
content["everyone_mask"].asInteger() :
|
||||
PERM_NONE;
|
||||
|
||||
U32 group_perms =
|
||||
content.has("group_mask") ?
|
||||
content["group_mask"].asInteger() :
|
||||
PERM_NONE;
|
||||
|
||||
U32 next_owner_perms =
|
||||
content.has("next_owner_mask") ?
|
||||
content["next_owner_mask"].asInteger() :
|
||||
PERM_NONE;
|
||||
|
||||
std::string display_name = LLStringUtil::null;
|
||||
LLAssetStorage::LLStoreAssetCallback callback = NULL;
|
||||
void *userdata = NULL;
|
||||
upload_new_resource(next_file, asset_name, asset_name,
|
||||
0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
|
||||
next_owner_perms, group_perms,
|
||||
everyone_perms, display_name,
|
||||
callback, expected_upload_cost, userdata);
|
||||
|
||||
upload_new_resource(
|
||||
next_file,
|
||||
asset_name,
|
||||
asset_name,
|
||||
0,
|
||||
LLFolderType::FT_NONE,
|
||||
LLInventoryType::IT_NONE,
|
||||
next_owner_perms,
|
||||
group_perms,
|
||||
everyone_perms,
|
||||
display_name,
|
||||
callback,
|
||||
LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(),
|
||||
userdata);
|
||||
}
|
||||
|
||||
LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE);
|
||||
}
|
||||
|
||||
LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data,
|
||||
|
|
@ -394,17 +477,19 @@ void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason)
|
|||
mBakedUploadData = NULL; // deleted in onTextureUploadComplete()
|
||||
}
|
||||
|
||||
LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data,
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type)
|
||||
: LLAssetUploadResponder(post_data, vfile_id, asset_type)
|
||||
LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
|
||||
const LLSD& post_data,
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type)
|
||||
: LLAssetUploadResponder(post_data, vfile_id, asset_type)
|
||||
{
|
||||
}
|
||||
|
||||
LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data,
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type)
|
||||
: LLAssetUploadResponder(post_data, file_name, asset_type)
|
||||
LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
|
||||
const LLSD& post_data,
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type)
|
||||
: LLAssetUploadResponder(post_data, file_name, asset_type)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -587,3 +672,472 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// LLNewAgentInventoryVariablePriceResponder::Impl //
|
||||
/////////////////////////////////////////////////////
|
||||
class LLNewAgentInventoryVariablePriceResponder::Impl
|
||||
{
|
||||
public:
|
||||
Impl(
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLSD& inventory_data) :
|
||||
mVFileID(vfile_id),
|
||||
mAssetType(asset_type),
|
||||
mInventoryData(inventory_data),
|
||||
mFileName("")
|
||||
{
|
||||
if (!gVFS->getExists(vfile_id, asset_type))
|
||||
{
|
||||
llwarns
|
||||
<< "LLAssetUploadResponder called with nonexistant "
|
||||
<< "vfile_id " << vfile_id << llendl;
|
||||
mVFileID.setNull();
|
||||
mAssetType = LLAssetType::AT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
Impl(
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLSD& inventory_data) :
|
||||
mFileName(file_name),
|
||||
mAssetType(asset_type),
|
||||
mInventoryData(inventory_data)
|
||||
{
|
||||
mVFileID.setNull();
|
||||
}
|
||||
|
||||
std::string getFilenameOrIDString() const
|
||||
{
|
||||
return (mFileName.empty() ? mVFileID.asString() : mFileName);
|
||||
}
|
||||
|
||||
LLUUID getVFileID() const
|
||||
{
|
||||
return mVFileID;
|
||||
}
|
||||
|
||||
std::string getFilename() const
|
||||
{
|
||||
return mFileName;
|
||||
}
|
||||
|
||||
LLAssetType::EType getAssetType() const
|
||||
{
|
||||
return mAssetType;
|
||||
}
|
||||
|
||||
LLInventoryType::EType getInventoryType() const
|
||||
{
|
||||
return LLInventoryType::lookup(
|
||||
mInventoryData["inventory_type"].asString());
|
||||
}
|
||||
|
||||
std::string getInventoryTypeString() const
|
||||
{
|
||||
return mInventoryData["inventory_type"].asString();
|
||||
}
|
||||
|
||||
LLUUID getFolderID() const
|
||||
{
|
||||
return mInventoryData["folder_id"].asUUID();
|
||||
}
|
||||
|
||||
std::string getItemName() const
|
||||
{
|
||||
return mInventoryData["name"].asString();
|
||||
}
|
||||
|
||||
std::string getItemDescription() const
|
||||
{
|
||||
return mInventoryData["description"].asString();
|
||||
}
|
||||
|
||||
void displayCannotUploadReason(const std::string& reason)
|
||||
{
|
||||
LLSD args;
|
||||
args["FILE"] = getFilenameOrIDString();
|
||||
args["REASON"] = reason;
|
||||
|
||||
|
||||
LLNotificationsUtil::add("CannotUploadReason", args);
|
||||
LLUploadDialog::modalUploadFinished();
|
||||
}
|
||||
|
||||
void onApplicationLevelError(const LLSD& error)
|
||||
{
|
||||
static const std::string _IDENTIFIER = "identifier";
|
||||
|
||||
static const std::string _INSUFFICIENT_FUNDS =
|
||||
"NewAgentInventory_InsufficientLindenDollarBalance";
|
||||
static const std::string _MISSING_REQUIRED_PARAMETER =
|
||||
"NewAgentInventory_MissingRequiredParamater";
|
||||
static const std::string _INVALID_REQUEST_BODY =
|
||||
"NewAgentInventory_InvalidRequestBody";
|
||||
static const std::string _RESOURCE_COST_DIFFERS =
|
||||
"NewAgentInventory_ResourceCostDiffers";
|
||||
|
||||
static const std::string _MISSING_PARAMETER = "missing_parameter";
|
||||
static const std::string _INVALID_PARAMETER = "invalid_parameter";
|
||||
static const std::string _MISSING_RESOURCE = "missing_resource";
|
||||
static const std::string _INVALID_RESOURCE = "invalid_resource";
|
||||
|
||||
// TODO* Add the other error_identifiers
|
||||
|
||||
std::string error_identifier = error[_IDENTIFIER].asString();
|
||||
|
||||
// TODO*: Pull these user visible strings from an xml file
|
||||
// to be localized
|
||||
if ( _INSUFFICIENT_FUNDS == error_identifier )
|
||||
{
|
||||
displayCannotUploadReason("You do not have a sufficient L$ balance to complete this upload.");
|
||||
}
|
||||
else if ( _MISSING_REQUIRED_PARAMETER == error_identifier )
|
||||
{
|
||||
// Missing parameters
|
||||
if (error.has(_MISSING_PARAMETER) )
|
||||
{
|
||||
std::string message =
|
||||
"Upload request was missing required parameter '[P]'";
|
||||
LLStringUtil::replaceString(
|
||||
message,
|
||||
"[P]",
|
||||
error[_MISSING_PARAMETER].asString());
|
||||
|
||||
displayCannotUploadReason(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string message =
|
||||
"Upload request was missing a required parameter";
|
||||
displayCannotUploadReason(message);
|
||||
}
|
||||
}
|
||||
else if ( _INVALID_REQUEST_BODY == error_identifier )
|
||||
{
|
||||
// Invalid request body, check to see if
|
||||
// a particular parameter was invalid
|
||||
if ( error.has(_INVALID_PARAMETER) )
|
||||
{
|
||||
std::string message = "Upload parameter '[P]' is invalid.";
|
||||
LLStringUtil::replaceString(
|
||||
message,
|
||||
"[P]",
|
||||
error[_INVALID_PARAMETER].asString());
|
||||
|
||||
// See if the server also responds with what resource
|
||||
// is missing.
|
||||
if ( error.has(_MISSING_RESOURCE) )
|
||||
{
|
||||
message += "\nMissing resource '[R]'.";
|
||||
|
||||
LLStringUtil::replaceString(
|
||||
message,
|
||||
"[R]",
|
||||
error[_MISSING_RESOURCE].asString());
|
||||
}
|
||||
else if ( error.has(_INVALID_RESOURCE) )
|
||||
{
|
||||
message += "\nInvalid resource '[R]'.";
|
||||
|
||||
LLStringUtil::replaceString(
|
||||
message,
|
||||
"[R]",
|
||||
error[_INVALID_RESOURCE].asString());
|
||||
}
|
||||
|
||||
displayCannotUploadReason(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string message = "Upload request was malformed";
|
||||
displayCannotUploadReason(message);
|
||||
}
|
||||
}
|
||||
else if ( _RESOURCE_COST_DIFFERS == error_identifier )
|
||||
{
|
||||
displayCannotUploadReason("The resource cost associated with this upload is not consistent with the server.");
|
||||
}
|
||||
else
|
||||
{
|
||||
displayCannotUploadReason("Unknown Error");
|
||||
}
|
||||
}
|
||||
|
||||
void onTransportError()
|
||||
{
|
||||
displayCannotUploadReason(
|
||||
"The server is experiencing unexpected difficulties.");
|
||||
}
|
||||
|
||||
void onTransportError(const LLSD& error)
|
||||
{
|
||||
static const std::string _IDENTIFIER = "identifier";
|
||||
|
||||
static const std::string _SERVER_ERROR_AFTER_CHARGE =
|
||||
"NewAgentInventory_ServerErrorAfterCharge";
|
||||
|
||||
std::string error_identifier = error[_IDENTIFIER].asString();
|
||||
|
||||
// TODO*: Pull the user visible strings from an xml file
|
||||
// to be localized
|
||||
|
||||
if ( _SERVER_ERROR_AFTER_CHARGE == error_identifier )
|
||||
{
|
||||
displayCannotUploadReason(
|
||||
"The server is experiencing unexpected difficulties. You may have been charged for the upload.");
|
||||
}
|
||||
else
|
||||
{
|
||||
displayCannotUploadReason(
|
||||
"The server is experiencing unexpected difficulties.");
|
||||
}
|
||||
}
|
||||
|
||||
bool uploadConfirmationCallback(
|
||||
const LLSD& notification,
|
||||
const LLSD& response,
|
||||
boost::intrusive_ptr<LLNewAgentInventoryVariablePriceResponder> responder)
|
||||
{
|
||||
S32 option;
|
||||
std::string confirmation_url;
|
||||
|
||||
option = LLNotificationsUtil::getSelectedOption(
|
||||
notification,
|
||||
response);
|
||||
|
||||
confirmation_url =
|
||||
notification["payload"]["confirmation_url"].asString();
|
||||
|
||||
// Yay! We are confirming or cancelling our upload
|
||||
switch(option)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
confirmUpload(confirmation_url, responder);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void confirmUpload(
|
||||
const std::string& confirmation_url,
|
||||
boost::intrusive_ptr<LLNewAgentInventoryVariablePriceResponder> responder)
|
||||
{
|
||||
if ( getFilename().empty() )
|
||||
{
|
||||
// we have no filename, use virtual file ID instead
|
||||
LLHTTPClient::postFile(
|
||||
confirmation_url,
|
||||
getVFileID(),
|
||||
getAssetType(),
|
||||
responder);
|
||||
}
|
||||
else
|
||||
{
|
||||
LLHTTPClient::postFile(
|
||||
confirmation_url,
|
||||
getFilename(),
|
||||
responder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::string mFileName;
|
||||
|
||||
LLSD mInventoryData;
|
||||
LLAssetType::EType mAssetType;
|
||||
LLUUID mVFileID;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// LLNewAgentInventoryVariablePriceResponder //
|
||||
///////////////////////////////////////////////
|
||||
LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder(
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLSD& inventory_info)
|
||||
{
|
||||
mImpl = new Impl(
|
||||
vfile_id,
|
||||
asset_type,
|
||||
inventory_info);
|
||||
}
|
||||
|
||||
LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder(
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLSD& inventory_info)
|
||||
{
|
||||
mImpl = new Impl(
|
||||
file_name,
|
||||
asset_type,
|
||||
inventory_info);
|
||||
}
|
||||
|
||||
LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResponder()
|
||||
{
|
||||
delete mImpl;
|
||||
}
|
||||
|
||||
void LLNewAgentInventoryVariablePriceResponder::errorWithContent(
|
||||
U32 statusNum,
|
||||
const std::string& reason,
|
||||
const LLSD& content)
|
||||
{
|
||||
lldebugs
|
||||
<< "LLNewAgentInventoryVariablePrice::error " << statusNum
|
||||
<< " reason: " << reason << llendl;
|
||||
|
||||
if ( content.has("error") )
|
||||
{
|
||||
static const std::string _ERROR = "error";
|
||||
|
||||
mImpl->onTransportError(content[_ERROR]);
|
||||
}
|
||||
else
|
||||
{
|
||||
mImpl->onTransportError();
|
||||
}
|
||||
}
|
||||
|
||||
void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content)
|
||||
{
|
||||
// Parse out application level errors and the appropriate
|
||||
// responses for them
|
||||
static const std::string _ERROR = "error";
|
||||
static const std::string _STATE = "state";
|
||||
|
||||
static const std::string _COMPLETE = "complete";
|
||||
static const std::string _CONFIRM_UPLOAD = "confirm_upload";
|
||||
|
||||
static const std::string _UPLOAD_PRICE = "upload_price";
|
||||
static const std::string _RESOURCE_COST = "resource_cost";
|
||||
static const std::string _RSVP = "rsvp";
|
||||
|
||||
// Check for application level errors
|
||||
if ( content.has(_ERROR) )
|
||||
{
|
||||
onApplicationLevelError(content[_ERROR]);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string state = content[_STATE];
|
||||
LLAssetType::EType asset_type = mImpl->getAssetType();
|
||||
|
||||
if ( _COMPLETE == state )
|
||||
{
|
||||
// rename file in VFS with new asset id
|
||||
if (mImpl->getFilename().empty())
|
||||
{
|
||||
// rename the file in the VFS to the actual asset id
|
||||
// llinfos << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << llendl;
|
||||
gVFS->renameFile(
|
||||
mImpl->getVFileID(),
|
||||
asset_type,
|
||||
content["new_asset"].asUUID(),
|
||||
asset_type);
|
||||
}
|
||||
|
||||
on_new_single_inventory_upload_complete(
|
||||
asset_type,
|
||||
mImpl->getInventoryType(),
|
||||
mImpl->getInventoryTypeString(),
|
||||
mImpl->getFolderID(),
|
||||
mImpl->getItemName(),
|
||||
mImpl->getItemDescription(),
|
||||
content,
|
||||
content[_UPLOAD_PRICE].asInteger());
|
||||
|
||||
// TODO* Add bulk (serial) uploading or add
|
||||
// a super class of this that does so
|
||||
}
|
||||
else if ( _CONFIRM_UPLOAD == state )
|
||||
{
|
||||
showConfirmationDialog(
|
||||
content[_UPLOAD_PRICE].asInteger(),
|
||||
content[_RESOURCE_COST].asInteger(),
|
||||
content[_RSVP].asString());
|
||||
}
|
||||
else
|
||||
{
|
||||
onApplicationLevelError("");
|
||||
}
|
||||
}
|
||||
|
||||
void LLNewAgentInventoryVariablePriceResponder::onApplicationLevelError(
|
||||
const LLSD& error)
|
||||
{
|
||||
mImpl->onApplicationLevelError(error);
|
||||
}
|
||||
|
||||
void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog(
|
||||
S32 upload_price,
|
||||
S32 resource_cost,
|
||||
const std::string& confirmation_url)
|
||||
{
|
||||
if ( 0 == upload_price )
|
||||
{
|
||||
// don't show confirmation dialog for free uploads, I mean,
|
||||
// they're free!
|
||||
|
||||
// The creating of a new instrusive_ptr(this)
|
||||
// creates a new boost::intrusive_ptr
|
||||
// which is a copy of this. This code is required because
|
||||
// 'this' is always of type Class* and not the intrusive_ptr,
|
||||
// and thus, a reference to 'this' is not registered
|
||||
// by using just plain 'this'.
|
||||
|
||||
// Since LLNewAgentInventoryVariablePriceResponder is a
|
||||
// reference counted class, it is possible (since the
|
||||
// reference to a plain 'this' would be missed here) that,
|
||||
// when using plain ol' 'this', that this object
|
||||
// would be deleted before the callback is triggered
|
||||
// and cause sadness.
|
||||
mImpl->confirmUpload(
|
||||
confirmation_url,
|
||||
boost::intrusive_ptr<LLNewAgentInventoryVariablePriceResponder>(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
LLSD substitutions;
|
||||
LLSD payload;
|
||||
|
||||
substitutions["PRICE"] = upload_price;
|
||||
|
||||
payload["confirmation_url"] = confirmation_url;
|
||||
|
||||
// The creating of a new instrusive_ptr(this)
|
||||
// creates a new boost::intrusive_ptr
|
||||
// which is a copy of this. This code is required because
|
||||
// 'this' is always of type Class* and not the intrusive_ptr,
|
||||
// and thus, a reference to 'this' is not registered
|
||||
// by using just plain 'this'.
|
||||
|
||||
// Since LLNewAgentInventoryVariablePriceResponder is a
|
||||
// reference counted class, it is possible (since the
|
||||
// reference to a plain 'this' would be missed here) that,
|
||||
// when using plain ol' 'this', that this object
|
||||
// would be deleted before the callback is triggered
|
||||
// and cause sadness.
|
||||
LLNotificationsUtil::add(
|
||||
"UploadCostConfirmation",
|
||||
substitutions,
|
||||
payload,
|
||||
boost::bind(
|
||||
&LLNewAgentInventoryVariablePriceResponder::Impl::uploadConfirmationCallback,
|
||||
mImpl,
|
||||
_1,
|
||||
_2,
|
||||
boost::intrusive_ptr<LLNewAgentInventoryVariablePriceResponder>(this)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,15 +61,60 @@ protected:
|
|||
std::string mFileName;
|
||||
};
|
||||
|
||||
|
||||
// TODO*: Remove this once deprecated
|
||||
class LLNewAgentInventoryResponder : public LLAssetUploadResponder
|
||||
{
|
||||
public:
|
||||
LLNewAgentInventoryResponder(const LLSD& post_data,
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type);
|
||||
LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name,
|
||||
LLAssetType::EType asset_type);
|
||||
LLNewAgentInventoryResponder(
|
||||
const LLSD& post_data,
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type);
|
||||
LLNewAgentInventoryResponder(
|
||||
const LLSD& post_data,
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type);
|
||||
virtual void error(U32 statusNum, const std::string& reason);
|
||||
virtual void uploadComplete(const LLSD& content);
|
||||
virtual void uploadFailure(const LLSD& content);
|
||||
};
|
||||
|
||||
// A base class which goes through and performs some default
|
||||
// actions for variable price uploads. If more specific actions
|
||||
// are needed (such as different confirmation messages, etc.)
|
||||
// the functions onApplicationLevelError and showConfirmationDialog.
|
||||
class LLNewAgentInventoryVariablePriceResponder :
|
||||
public LLHTTPClient::Responder
|
||||
{
|
||||
public:
|
||||
LLNewAgentInventoryVariablePriceResponder(
|
||||
const LLUUID& vfile_id,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLSD& inventory_info);
|
||||
|
||||
LLNewAgentInventoryVariablePriceResponder(
|
||||
const std::string& file_name,
|
||||
LLAssetType::EType asset_type,
|
||||
const LLSD& inventory_info);
|
||||
|
||||
virtual ~LLNewAgentInventoryVariablePriceResponder();
|
||||
|
||||
void errorWithContent(
|
||||
U32 statusNum,
|
||||
const std::string& reason,
|
||||
const LLSD& content);
|
||||
void result(const LLSD& content);
|
||||
|
||||
virtual void onApplicationLevelError(
|
||||
const LLSD& error);
|
||||
virtual void showConfirmationDialog(
|
||||
S32 upload_price,
|
||||
S32 resource_cost,
|
||||
const std::string& confirmation_url);
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
Impl* mImpl;
|
||||
};
|
||||
|
||||
class LLBakedUploadData;
|
||||
|
|
|
|||
|
|
@ -189,20 +189,30 @@ BOOL LLDrawable::isLight() const
|
|||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_CLEANUP_DRAWABLE("Cleanup Drawable");
|
||||
static LLFastTimer::DeclareTimer FTM_DEREF_DRAWABLE("Deref");
|
||||
static LLFastTimer::DeclareTimer FTM_DELETE_FACES("Faces");
|
||||
|
||||
void LLDrawable::cleanupReferences()
|
||||
{
|
||||
LLFastTimer t(FTM_PIPELINE);
|
||||
LLFastTimer t(FTM_CLEANUP_DRAWABLE);
|
||||
|
||||
std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
|
||||
mFaces.clear();
|
||||
{
|
||||
LLFastTimer t(FTM_DELETE_FACES);
|
||||
std::for_each(mFaces.begin(), mFaces.end(), DeletePointer());
|
||||
mFaces.clear();
|
||||
}
|
||||
|
||||
gObjectList.removeDrawable(this);
|
||||
|
||||
gPipeline.unlinkDrawable(this);
|
||||
|
||||
// Cleanup references to other objects
|
||||
mVObjp = NULL;
|
||||
mParent = NULL;
|
||||
{
|
||||
LLFastTimer t(FTM_DEREF_DRAWABLE);
|
||||
// Cleanup references to other objects
|
||||
mVObjp = NULL;
|
||||
mParent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawable::cleanupDeadDrawables()
|
||||
|
|
|
|||
|
|
@ -313,8 +313,10 @@ private:
|
|||
|
||||
inline LLFace* LLDrawable::getFace(const S32 i) const
|
||||
{
|
||||
llassert((U32)i < mFaces.size());
|
||||
llassert(mFaces[i]);
|
||||
if ((U32) i >= mFaces.size())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return mFaces[i];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -442,7 +442,6 @@ void LLRenderPass::renderTexture(U32 type, U32 mask)
|
|||
|
||||
void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture)
|
||||
{
|
||||
llpushcallstacks ;
|
||||
for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
|
||||
{
|
||||
LLDrawInfo* pparams = *i;
|
||||
|
|
@ -475,6 +474,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture)
|
|||
{
|
||||
if (params.mTexture.notNull())
|
||||
{
|
||||
params.mTexture->addTextureStats(params.mVSize);
|
||||
gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
|
||||
if (params.mTextureMatrix)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,7 +60,9 @@ static BOOL deferred_render = FALSE;
|
|||
|
||||
LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
|
||||
LLRenderPass(type), current_shader(NULL), target_shader(NULL),
|
||||
simple_shader(NULL), fullbright_shader(NULL)
|
||||
simple_shader(NULL), fullbright_shader(NULL),
|
||||
mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF),
|
||||
mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -178,9 +180,16 @@ void LLDrawPoolAlpha::render(S32 pass)
|
|||
|
||||
LLGLSPipelineAlpha gls_pipeline_alpha;
|
||||
|
||||
gGL.setColorMask(true, true);
|
||||
|
||||
if (LLPipeline::sFastAlpha && !deferred_render)
|
||||
{
|
||||
LLGLDisable blend_disable(GL_BLEND);
|
||||
mColorSFactor = LLRender::BF_ONE; // }
|
||||
mColorDFactor = LLRender::BF_ZERO; // } these are like disabling blend on the color channels, but we're still blending on the alpha channel so that we can suppress glow
|
||||
mAlphaSFactor = LLRender::BF_ZERO;
|
||||
mAlphaDFactor = LLRender::BF_ZERO; // block (zero-out) glow where the alpha test succeeds
|
||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||
|
||||
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f);
|
||||
if (mVertexShaderLevel > 0)
|
||||
{
|
||||
|
|
@ -204,8 +213,17 @@ void LLDrawPoolAlpha::render(S32 pass)
|
|||
}
|
||||
|
||||
LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE);
|
||||
|
||||
mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend
|
||||
mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // }
|
||||
mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression
|
||||
mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // }
|
||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||
|
||||
renderAlpha(getVertexDataMask());
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
|
||||
if (deferred_render && current_shader != NULL)
|
||||
{
|
||||
gPipeline.unbindDeferredShader(*current_shader);
|
||||
|
|
@ -283,9 +301,18 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
|||
for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
|
||||
{
|
||||
LLSpatialGroup* group = *i;
|
||||
llassert(group);
|
||||
llassert(group->mSpatialPartition);
|
||||
|
||||
if (group->mSpatialPartition->mRenderByGroup &&
|
||||
!group->isDead())
|
||||
!group->isDead())
|
||||
{
|
||||
bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow.
|
||||
// All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress.
|
||||
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE &&
|
||||
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_CLOUD &&
|
||||
group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE;
|
||||
|
||||
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA];
|
||||
|
||||
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
|
||||
|
|
@ -294,96 +321,118 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)
|
|||
|
||||
LLRenderPass::applyModelMatrix(params);
|
||||
|
||||
if (params.mFullbright)
|
||||
{
|
||||
// Turn off lighting if it hasn't already been so.
|
||||
if (light_enabled || !initialized_lighting)
|
||||
if (params.mFullbright)
|
||||
{
|
||||
// Turn off lighting if it hasn't already been so.
|
||||
if (light_enabled || !initialized_lighting)
|
||||
{
|
||||
initialized_lighting = TRUE;
|
||||
if (use_shaders)
|
||||
{
|
||||
target_shader = fullbright_shader;
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
|
||||
}
|
||||
light_enabled = FALSE;
|
||||
}
|
||||
}
|
||||
// Turn on lighting if it isn't already.
|
||||
else if (!light_enabled || !initialized_lighting)
|
||||
{
|
||||
initialized_lighting = TRUE;
|
||||
if (use_shaders)
|
||||
{
|
||||
target_shader = fullbright_shader;
|
||||
target_shader = simple_shader;
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
|
||||
gPipeline.enableLightsDynamic();
|
||||
}
|
||||
light_enabled = FALSE;
|
||||
light_enabled = TRUE;
|
||||
}
|
||||
}
|
||||
// Turn on lighting if it isn't already.
|
||||
else if (!light_enabled || !initialized_lighting)
|
||||
{
|
||||
initialized_lighting = TRUE;
|
||||
if (use_shaders)
|
||||
{
|
||||
target_shader = simple_shader;
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.enableLightsDynamic();
|
||||
}
|
||||
light_enabled = TRUE;
|
||||
}
|
||||
|
||||
// If we need shaders, and we're not ALREADY using the proper shader, then bind it
|
||||
// (this way we won't rebind shaders unnecessarily).
|
||||
if(use_shaders && (current_shader != target_shader))
|
||||
{
|
||||
llassert(target_shader != NULL);
|
||||
if (deferred_render && current_shader != NULL)
|
||||
// If we need shaders, and we're not ALREADY using the proper shader, then bind it
|
||||
// (this way we won't rebind shaders unnecessarily).
|
||||
if(use_shaders && (current_shader != target_shader))
|
||||
{
|
||||
gPipeline.unbindDeferredShader(*current_shader);
|
||||
diffuse_channel = 0;
|
||||
llassert(target_shader != NULL);
|
||||
if (deferred_render && current_shader != NULL)
|
||||
{
|
||||
gPipeline.unbindDeferredShader(*current_shader);
|
||||
diffuse_channel = 0;
|
||||
}
|
||||
current_shader = target_shader;
|
||||
if (deferred_render)
|
||||
{
|
||||
gPipeline.bindDeferredShader(*current_shader);
|
||||
diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_shader->bind();
|
||||
}
|
||||
}
|
||||
current_shader = target_shader;
|
||||
if (deferred_render)
|
||||
else if (!use_shaders && current_shader != NULL)
|
||||
{
|
||||
gPipeline.bindDeferredShader(*current_shader);
|
||||
diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
|
||||
if (deferred_render)
|
||||
{
|
||||
gPipeline.unbindDeferredShader(*current_shader);
|
||||
diffuse_channel = 0;
|
||||
}
|
||||
LLGLSLShader::bindNoShader();
|
||||
current_shader = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_shader->bind();
|
||||
}
|
||||
}
|
||||
else if (!use_shaders && current_shader != NULL)
|
||||
{
|
||||
if (deferred_render)
|
||||
{
|
||||
gPipeline.unbindDeferredShader(*current_shader);
|
||||
diffuse_channel = 0;
|
||||
}
|
||||
LLGLSLShader::bindNoShader();
|
||||
current_shader = NULL;
|
||||
}
|
||||
|
||||
if (params.mGroup)
|
||||
{
|
||||
params.mGroup->rebuildMesh();
|
||||
}
|
||||
|
||||
|
||||
if (params.mTexture.notNull())
|
||||
{
|
||||
gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get());
|
||||
if(params.mTexture.notNull())
|
||||
if (params.mGroup)
|
||||
{
|
||||
params.mTexture->addTextureStats(params.mVSize);
|
||||
params.mGroup->rebuildMesh();
|
||||
}
|
||||
if (params.mTextureMatrix)
|
||||
|
||||
|
||||
if (params.mTexture.notNull())
|
||||
{
|
||||
gGL.getTexUnit(0)->activate();
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
|
||||
gPipeline.mTextureMatrixOps++;
|
||||
gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get());
|
||||
if(params.mTexture.notNull())
|
||||
{
|
||||
params.mTexture->addTextureStats(params.mVSize);
|
||||
}
|
||||
if (params.mTextureMatrix)
|
||||
{
|
||||
gGL.getTexUnit(0)->activate();
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix);
|
||||
gPipeline.mTextureMatrixOps++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.mVertexBuffer->setBuffer(mask);
|
||||
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
|
||||
|
||||
// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha.
|
||||
if (draw_glow_for_this_partition &&
|
||||
params.mGlowColor.mV[3] > 0)
|
||||
{
|
||||
// install glow-accumulating blend mode
|
||||
gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color
|
||||
LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)
|
||||
|
||||
// glow doesn't use vertex colors from the mesh data
|
||||
params.mVertexBuffer->setBuffer(mask & ~LLVertexBuffer::MAP_COLOR);
|
||||
glColor4ubv(params.mGlowColor.mV);
|
||||
|
||||
// do the actual drawing, again
|
||||
params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
|
||||
gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
|
||||
|
||||
// restore our alpha blend mode
|
||||
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
|
||||
}
|
||||
|
||||
if (params.mTextureMatrix && params.mTexture.notNull())
|
||||
{
|
||||
gGL.getTexUnit(0)->activate();
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#define LL_LLDRAWPOOLALPHA_H
|
||||
|
||||
#include "lldrawpool.h"
|
||||
#include "llrender.h"
|
||||
#include "llframetimer.h"
|
||||
|
||||
class LLFace;
|
||||
|
|
@ -83,6 +84,12 @@ private:
|
|||
LLGLSLShader* target_shader;
|
||||
LLGLSLShader* simple_shader;
|
||||
LLGLSLShader* fullbright_shader;
|
||||
|
||||
// our 'normal' alpha blend function for this pass
|
||||
LLRender::eBlendFactor mColorSFactor;
|
||||
LLRender::eBlendFactor mColorDFactor;
|
||||
LLRender::eBlendFactor mAlphaSFactor;
|
||||
LLRender::eBlendFactor mAlphaDFactor;
|
||||
};
|
||||
|
||||
class LLDrawPoolAlphaPostWater : public LLDrawPoolAlpha
|
||||
|
|
|
|||
|
|
@ -157,6 +157,8 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
|
|||
{
|
||||
LLFastTimer t(FTM_RENDER_CHARACTERS);
|
||||
|
||||
sSkipTransparent = TRUE;
|
||||
|
||||
if (LLPipeline::sImpostorRender)
|
||||
{
|
||||
beginDeferredSkinned();
|
||||
|
|
@ -181,6 +183,8 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass)
|
|||
{
|
||||
LLFastTimer t(FTM_RENDER_CHARACTERS);
|
||||
|
||||
sSkipTransparent = FALSE;
|
||||
|
||||
if (LLPipeline::sImpostorRender)
|
||||
{
|
||||
endDeferredSkinned();
|
||||
|
|
@ -564,7 +568,6 @@ void LLDrawPoolAvatar::endSkinned()
|
|||
|
||||
void LLDrawPoolAvatar::beginDeferredSkinned()
|
||||
{
|
||||
sSkipTransparent = TRUE;
|
||||
sShaderLevel = mVertexShaderLevel;
|
||||
sVertexProgram = &gDeferredAvatarProgram;
|
||||
|
||||
|
|
@ -579,7 +582,6 @@ void LLDrawPoolAvatar::beginDeferredSkinned()
|
|||
|
||||
void LLDrawPoolAvatar::endDeferredSkinned()
|
||||
{
|
||||
sSkipTransparent = FALSE;
|
||||
// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
|
||||
sRenderingSkinned = FALSE;
|
||||
disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
|
||||
|
|
|
|||
|
|
@ -701,6 +701,18 @@ void LLDrawPoolBump::endBump()
|
|||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
}
|
||||
|
||||
S32 LLDrawPoolBump::getNumDeferredPasses()
|
||||
{
|
||||
if (gSavedSettings.getBOOL("RenderObjectBump"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LLDrawPoolBump::beginDeferredPass(S32 pass)
|
||||
{
|
||||
if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
|
||||
|
|
@ -825,7 +837,6 @@ void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32
|
|||
|
||||
void LLBumpImageList::updateImages()
|
||||
{
|
||||
llpushcallstacks ;
|
||||
for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); )
|
||||
{
|
||||
bump_image_map_t::iterator curiter = iter++;
|
||||
|
|
@ -852,7 +863,7 @@ void LLBumpImageList::updateImages()
|
|||
}
|
||||
}
|
||||
}
|
||||
llpushcallstacks ;
|
||||
|
||||
for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); )
|
||||
{
|
||||
bump_image_map_t::iterator curiter = iter++;
|
||||
|
|
@ -879,7 +890,6 @@ void LLBumpImageList::updateImages()
|
|||
}
|
||||
}
|
||||
}
|
||||
llpushcallstacks ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public:
|
|||
void renderBump();
|
||||
void endBump();
|
||||
|
||||
virtual S32 getNumDeferredPasses() { return 1; }
|
||||
virtual S32 getNumDeferredPasses();
|
||||
/*virtual*/ void beginDeferredPass(S32 pass);
|
||||
/*virtual*/ void endDeferredPass(S32 pass);
|
||||
/*virtual*/ void renderDeferred(S32 pass);
|
||||
|
|
|
|||
|
|
@ -185,22 +185,33 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
|
|||
mHasMedia = FALSE ;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_DESTROY_FACE("Destroy Face");
|
||||
static LLFastTimer::DeclareTimer FTM_DESTROY_TEXTURE("Texture");
|
||||
static LLFastTimer::DeclareTimer FTM_DESTROY_DRAWPOOL("Drawpool");
|
||||
static LLFastTimer::DeclareTimer FTM_DESTROY_TEXTURE_MATRIX("Texture Matrix");
|
||||
static LLFastTimer::DeclareTimer FTM_DESTROY_DRAW_INFO("Draw Info");
|
||||
static LLFastTimer::DeclareTimer FTM_DESTROY_ATLAS("Atlas");
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_DEREF("Deref");
|
||||
|
||||
void LLFace::destroy()
|
||||
{
|
||||
LLFastTimer t(FTM_DESTROY_FACE);
|
||||
if(mTexture.notNull())
|
||||
{
|
||||
LLFastTimer t(FTM_DESTROY_TEXTURE);
|
||||
mTexture->removeFace(this) ;
|
||||
}
|
||||
|
||||
if (mDrawPoolp)
|
||||
{
|
||||
LLFastTimer t(FTM_DESTROY_DRAWPOOL);
|
||||
mDrawPoolp->removeFace(this);
|
||||
mDrawPoolp = NULL;
|
||||
}
|
||||
|
||||
if (mTextureMatrix)
|
||||
{
|
||||
LLFastTimer t(FTM_DESTROY_TEXTURE_MATRIX);
|
||||
delete mTextureMatrix;
|
||||
mTextureMatrix = NULL;
|
||||
|
||||
|
|
@ -215,11 +226,21 @@ void LLFace::destroy()
|
|||
}
|
||||
}
|
||||
|
||||
setDrawInfo(NULL);
|
||||
{
|
||||
LLFastTimer t(FTM_DESTROY_DRAW_INFO);
|
||||
setDrawInfo(NULL);
|
||||
}
|
||||
|
||||
removeAtlas();
|
||||
mDrawablep = NULL;
|
||||
mVObjp = NULL;
|
||||
{
|
||||
LLFastTimer t(FTM_DESTROY_ATLAS);
|
||||
removeAtlas();
|
||||
}
|
||||
|
||||
{
|
||||
LLFastTimer t(FTM_FACE_DEREF);
|
||||
mDrawablep = NULL;
|
||||
mVObjp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -862,12 +883,14 @@ void LLFace::updateRebuildFlags()
|
|||
}
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_FACE_GET_GEOM("Face Geom");
|
||||
|
||||
BOOL LLFace::getGeometryVolume(const LLVolume& volume,
|
||||
const S32 &f,
|
||||
const LLMatrix4& mat_vert, const LLMatrix3& mat_normal,
|
||||
const U16 &index_offset)
|
||||
{
|
||||
llpushcallstacks ;
|
||||
LLFastTimer t(FTM_FACE_GET_GEOM);
|
||||
const LLVolumeFace &vf = volume.getVolumeFace(f);
|
||||
S32 num_vertices = (S32)vf.mVertices.size();
|
||||
S32 num_indices = LLPipeline::sUseTriStrips ? (S32)vf.mTriStrip.size() : (S32) vf.mIndices.size();
|
||||
|
|
|
|||
|
|
@ -55,12 +55,14 @@ LLFilePicker LLFilePicker::sInstance;
|
|||
#define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0"
|
||||
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
|
||||
#define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0"
|
||||
#define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0"
|
||||
#ifdef _CORY_TESTING
|
||||
#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
|
||||
#endif
|
||||
#define XML_FILTER L"XML files (*.xml)\0*.xml\0"
|
||||
#define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
|
||||
#define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
|
||||
#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
|
||||
#endif
|
||||
|
||||
//
|
||||
|
|
@ -176,6 +178,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
|
|||
mOFN.lpstrFilter = ANIM_FILTER \
|
||||
L"\0";
|
||||
break;
|
||||
case FFLOAD_COLLADA:
|
||||
mOFN.lpstrFilter = COLLADA_FILTER \
|
||||
L"\0";
|
||||
break;
|
||||
#ifdef _CORY_TESTING
|
||||
case FFLOAD_GEOMETRY:
|
||||
mOFN.lpstrFilter = GEOMETRY_FILTER \
|
||||
|
|
@ -194,6 +200,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
|
|||
mOFN.lpstrFilter = RAW_FILTER \
|
||||
L"\0";
|
||||
break;
|
||||
case FFLOAD_MODEL:
|
||||
mOFN.lpstrFilter = MODEL_FILTER \
|
||||
L"\0";
|
||||
break;
|
||||
default:
|
||||
res = FALSE;
|
||||
break;
|
||||
|
|
@ -201,7 +211,7 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
|
|||
return res;
|
||||
}
|
||||
|
||||
BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
|
||||
BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
|
||||
{
|
||||
if( mLocked )
|
||||
{
|
||||
|
|
@ -220,8 +230,11 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
|
|||
|
||||
setupFilter(filter);
|
||||
|
||||
// Modal, so pause agent
|
||||
send_agent_pause();
|
||||
if (blocking)
|
||||
{
|
||||
// Modal, so pause agent
|
||||
send_agent_pause();
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
|
|
@ -232,10 +245,14 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
|
|||
std::string filename = utf16str_to_utf8str(llutf16string(mFilesW));
|
||||
mFiles.push_back(filename);
|
||||
}
|
||||
send_agent_resume();
|
||||
|
||||
// Account for the fact that the app has been stalled.
|
||||
LLFrameTimer::updateFrameTime();
|
||||
if (blocking)
|
||||
{
|
||||
send_agent_resume();
|
||||
// Account for the fact that the app has been stalled.
|
||||
LLFrameTimer::updateFrameTime();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -543,6 +560,15 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB
|
|||
result = false;
|
||||
}
|
||||
}
|
||||
else if (filter == FFLOAD_COLLADA)
|
||||
{
|
||||
if (fileInfo.filetype != 'DAE ' &&
|
||||
(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dae"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
|
||||
)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
#ifdef _CORY_TESTING
|
||||
else if (filter == FFLOAD_GEOMETRY)
|
||||
{
|
||||
|
|
@ -808,7 +834,7 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& fi
|
|||
return error;
|
||||
}
|
||||
|
||||
BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
|
||||
BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
|
||||
{
|
||||
if( mLocked )
|
||||
return FALSE;
|
||||
|
|
@ -827,20 +853,29 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter)
|
|||
mNavOptions.optionFlags |= kNavSupportPackages;
|
||||
}
|
||||
|
||||
// Modal, so pause agent
|
||||
send_agent_pause();
|
||||
if (blocking)
|
||||
{
|
||||
// Modal, so pause agent
|
||||
send_agent_pause();
|
||||
}
|
||||
|
||||
{
|
||||
error = doNavChooseDialog(filter);
|
||||
}
|
||||
send_agent_resume();
|
||||
|
||||
if (error == noErr)
|
||||
{
|
||||
if (getFileCount())
|
||||
success = true;
|
||||
}
|
||||
|
||||
// Account for the fact that the app has been stalled.
|
||||
LLFrameTimer::updateFrameTime();
|
||||
if (blocking)
|
||||
{
|
||||
send_agent_resume();
|
||||
// Account for the fact that the app has been stalled.
|
||||
LLFrameTimer::updateFrameTime();
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
@ -1089,6 +1124,12 @@ static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker)
|
|||
LLTrans::getString("animation_files") + " (*.bvh)");
|
||||
}
|
||||
|
||||
static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker)
|
||||
{
|
||||
return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae",
|
||||
LLTrans::getString("scene_files") + " (*.dae)");
|
||||
}
|
||||
|
||||
static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
|
||||
{
|
||||
GtkFileFilter *gfilter = gtk_file_filter_new();
|
||||
|
|
@ -1191,7 +1232,7 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename
|
|||
return rtn;
|
||||
}
|
||||
|
||||
BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
|
||||
BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )
|
||||
{
|
||||
BOOL rtn = FALSE;
|
||||
|
||||
|
|
@ -1213,6 +1254,9 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
|
|||
case FFLOAD_ANIM:
|
||||
filtername = add_bvh_filter_to_gtkchooser(picker);
|
||||
break;
|
||||
case FFLOAD_COLLADA:
|
||||
filtername = add_collada_filter_to_gtkchooser(picker);
|
||||
break;
|
||||
case FFLOAD_IMAGE:
|
||||
filtername = add_imageload_filter_to_gtkchooser(picker);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,8 @@ public:
|
|||
FFLOAD_XML = 6,
|
||||
FFLOAD_SLOBJECT = 7,
|
||||
FFLOAD_RAW = 8,
|
||||
FFLOAD_MODEL = 9,
|
||||
FFLOAD_COLLADA = 10,
|
||||
};
|
||||
|
||||
enum ESaveFilter
|
||||
|
|
@ -111,7 +113,7 @@ public:
|
|||
|
||||
// open the dialog. This is a modal operation
|
||||
BOOL getSaveFile( ESaveFilter filter = FFSAVE_ALL, const std::string& filename = LLStringUtil::null );
|
||||
BOOL getOpenFile( ELoadFilter filter = FFLOAD_ALL );
|
||||
BOOL getOpenFile( ELoadFilter filter = FFLOAD_ALL, bool blocking = true );
|
||||
BOOL getMultipleOpenFiles( ELoadFilter filter = FFLOAD_ALL );
|
||||
|
||||
// Get the filename(s) found. getFirstFile() sets the pointer to
|
||||
|
|
@ -192,4 +194,6 @@ public:
|
|||
~LLFilePicker();
|
||||
};
|
||||
|
||||
const std::string upload_pick(void* data);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -809,7 +809,7 @@ void LLFloaterPreference::buildPopupLists()
|
|||
|
||||
void LLFloaterPreference::refreshEnabledState()
|
||||
{
|
||||
LLCheckBoxCtrl* ctrl_reflections = getChild<LLCheckBoxCtrl>("Reflections");
|
||||
LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
|
||||
LLRadioGroup* radio_reflection_detail = getChild<LLRadioGroup>("ReflectionDetailRadio");
|
||||
|
||||
// Reflections
|
||||
|
|
@ -822,7 +822,7 @@ void LLFloaterPreference::refreshEnabledState()
|
|||
bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
|
||||
getChild<LLCheckBoxCtrl>("BumpShiny")->setEnabled(bumpshiny ? TRUE : FALSE);
|
||||
|
||||
radio_reflection_detail->setEnabled(ctrl_reflections->get() && reflections);
|
||||
radio_reflection_detail->setEnabled(reflections);
|
||||
|
||||
// Avatar Mode
|
||||
// Enable Avatar Shaders
|
||||
|
|
@ -868,18 +868,41 @@ void LLFloaterPreference::refreshEnabledState()
|
|||
// *HACK just checks to see if we can use shaders...
|
||||
// maybe some cards that use shaders, but don't support windlight
|
||||
ctrl_wind_light->setEnabled(ctrl_shader_enable->getEnabled() && shaders);
|
||||
|
||||
//Deferred/SSAO/Shadows
|
||||
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
|
||||
if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseFBO") &&
|
||||
shaders)
|
||||
{
|
||||
BOOL enabled = ctrl_wind_light->get() ? TRUE : FALSE;
|
||||
|
||||
ctrl_deferred->setEnabled(enabled);
|
||||
|
||||
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
|
||||
LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail");
|
||||
|
||||
enabled = enabled && (ctrl_deferred->get() ? TRUE : FALSE);
|
||||
|
||||
ctrl_ssao->setEnabled(enabled);
|
||||
ctrl_shadow->setEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
// now turn off any features that are unavailable
|
||||
disableUnavailableSettings();
|
||||
}
|
||||
|
||||
void LLFloaterPreference::disableUnavailableSettings()
|
||||
{
|
||||
LLCheckBoxCtrl* ctrl_reflections = getChild<LLCheckBoxCtrl>("Reflections");
|
||||
LLComboBox* ctrl_reflections = getChild<LLComboBox>("Reflections");
|
||||
LLCheckBoxCtrl* ctrl_avatar_vp = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
|
||||
LLCheckBoxCtrl* ctrl_avatar_cloth = getChild<LLCheckBoxCtrl>("AvatarCloth");
|
||||
LLCheckBoxCtrl* ctrl_shader_enable = getChild<LLCheckBoxCtrl>("BasicShaders");
|
||||
LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
|
||||
LLCheckBoxCtrl* ctrl_avatar_impostors = getChild<LLCheckBoxCtrl>("AvatarImpostors");
|
||||
LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
|
||||
LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");
|
||||
LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
|
||||
|
||||
// if vertex shaders off, disable all shader related products
|
||||
if(!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"))
|
||||
|
|
@ -891,13 +914,22 @@ void LLFloaterPreference::disableUnavailableSettings()
|
|||
ctrl_wind_light->setValue(FALSE);
|
||||
|
||||
ctrl_reflections->setEnabled(FALSE);
|
||||
ctrl_reflections->setValue(FALSE);
|
||||
ctrl_reflections->setValue(0);
|
||||
|
||||
ctrl_avatar_vp->setEnabled(FALSE);
|
||||
ctrl_avatar_vp->setValue(FALSE);
|
||||
|
||||
ctrl_avatar_cloth->setEnabled(FALSE);
|
||||
ctrl_avatar_cloth->setValue(FALSE);
|
||||
|
||||
ctrl_shadows->setEnabled(FALSE);
|
||||
ctrl_shadows->setValue(0);
|
||||
|
||||
ctrl_ssao->setEnabled(FALSE);
|
||||
ctrl_ssao->setValue(FALSE);
|
||||
|
||||
ctrl_deferred->setEnabled(FALSE);
|
||||
ctrl_deferred->setValue(FALSE);
|
||||
}
|
||||
|
||||
// disabled windlight
|
||||
|
|
@ -905,10 +937,20 @@ void LLFloaterPreference::disableUnavailableSettings()
|
|||
{
|
||||
ctrl_wind_light->setEnabled(FALSE);
|
||||
ctrl_wind_light->setValue(FALSE);
|
||||
|
||||
//deferred needs windlight, disable deferred
|
||||
ctrl_shadows->setEnabled(FALSE);
|
||||
ctrl_shadows->setValue(0);
|
||||
|
||||
ctrl_ssao->setEnabled(FALSE);
|
||||
ctrl_ssao->setValue(FALSE);
|
||||
|
||||
ctrl_deferred->setEnabled(FALSE);
|
||||
ctrl_deferred->setValue(FALSE);
|
||||
}
|
||||
|
||||
// disabled reflections
|
||||
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderWaterReflections"))
|
||||
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail"))
|
||||
{
|
||||
ctrl_reflections->setEnabled(FALSE);
|
||||
ctrl_reflections->setValue(FALSE);
|
||||
|
|
@ -922,13 +964,25 @@ void LLFloaterPreference::disableUnavailableSettings()
|
|||
|
||||
ctrl_avatar_cloth->setEnabled(FALSE);
|
||||
ctrl_avatar_cloth->setValue(FALSE);
|
||||
|
||||
//deferred needs AvatarVP, disable deferred
|
||||
ctrl_shadows->setEnabled(FALSE);
|
||||
ctrl_shadows->setValue(0);
|
||||
|
||||
ctrl_ssao->setEnabled(FALSE);
|
||||
ctrl_ssao->setValue(FALSE);
|
||||
|
||||
ctrl_deferred->setEnabled(FALSE);
|
||||
ctrl_deferred->setValue(FALSE);
|
||||
}
|
||||
|
||||
// disabled cloth
|
||||
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderAvatarCloth"))
|
||||
{
|
||||
ctrl_avatar_cloth->setEnabled(FALSE);
|
||||
ctrl_avatar_cloth->setValue(FALSE);
|
||||
}
|
||||
|
||||
// disabled impostors
|
||||
if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderUseImpostors"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ void LLFloaterTools::refresh()
|
|||
LLResMgr::getInstance()->getIntegerString(obj_count_string, LLSelectMgr::getInstance()->getSelection()->getRootObjectCount());
|
||||
childSetTextArg("obj_count", "[COUNT]", obj_count_string);
|
||||
std::string prim_count_string;
|
||||
LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount());
|
||||
LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount(TRUE));
|
||||
childSetTextArg("prim_count", "[COUNT]", prim_count_string);
|
||||
|
||||
// calculate selection rendering cost
|
||||
|
|
|
|||
|
|
@ -567,6 +567,18 @@ void LLHUDText::setStringUTF8(const std::string &wtext)
|
|||
setString(utf8str_to_wstring(wtext));
|
||||
}
|
||||
|
||||
std::string LLHUDText::getString()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
for (U32 i = 0; i < mTextSegments.size(); ++i)
|
||||
{
|
||||
const std::string str = wstring_to_utf8str(mTextSegments[i].getText());
|
||||
ostr << str;
|
||||
}
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
void LLHUDText::setString(const LLWString &wtext)
|
||||
{
|
||||
mTextSegments.clear();
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public:
|
|||
|
||||
public:
|
||||
void setStringUTF8(const std::string &utf8string);
|
||||
std::string getString();
|
||||
void setString(const LLWString &wstring);
|
||||
void clearString();
|
||||
void addLine(const std::string &text, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL);
|
||||
|
|
|
|||
|
|
@ -128,7 +128,9 @@ std::string ICON_NAME[ICON_NAME_COUNT] =
|
|||
"Inv_Gesture",
|
||||
|
||||
"Inv_LinkItem",
|
||||
"Inv_LinkFolder"
|
||||
"Inv_LinkFolder",
|
||||
|
||||
"Inv_Mesh"
|
||||
};
|
||||
|
||||
// +=================================================+
|
||||
|
|
@ -981,6 +983,14 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
|
|||
// Only should happen for broken links.
|
||||
new_listener = new LLLinkItemBridge(inventory, uuid);
|
||||
break;
|
||||
case LLAssetType::AT_MESH:
|
||||
if(!(inv_type == LLInventoryType::IT_MESH))
|
||||
{
|
||||
llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
|
||||
}
|
||||
new_listener = new LLMeshBridge(inventory, uuid);
|
||||
break;
|
||||
|
||||
default:
|
||||
llinfos << "Unhandled asset type (llassetstorage.h): "
|
||||
<< (S32)asset_type << llendl;
|
||||
|
|
@ -2319,6 +2329,9 @@ LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
|
|||
return LLUI::getUIImage("Inv_LookFolderClosed");
|
||||
}
|
||||
return LLUI::getUIImage("Inv_FolderClosed");
|
||||
/*case LLAssetType::AT_MESH:
|
||||
control = "inv_folder_mesh.tga";
|
||||
break;*/
|
||||
}
|
||||
|
||||
LLUIImagePtr LLFolderBridge::getOpenIcon() const
|
||||
|
|
@ -2818,6 +2831,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
|
|||
case DAD_ANIMATION:
|
||||
case DAD_GESTURE:
|
||||
case DAD_LINK:
|
||||
case DAD_MESH:
|
||||
accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
|
||||
drop);
|
||||
break;
|
||||
|
|
@ -3704,6 +3718,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
|
|||
case DAD_BODYPART:
|
||||
case DAD_ANIMATION:
|
||||
case DAD_GESTURE:
|
||||
case DAD_MESH:
|
||||
{
|
||||
LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
|
||||
const LLPermissions& perm = inv_item->getPermissions();
|
||||
|
|
@ -5050,6 +5065,65 @@ void LLWearableBridge::removeFromAvatar()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// +=================================================+
|
||||
// | LLMeshBridge |
|
||||
// +=================================================+
|
||||
|
||||
LLUIImagePtr LLMeshBridge::getIcon() const
|
||||
{
|
||||
return get_item_icon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
|
||||
}
|
||||
|
||||
void LLMeshBridge::openItem()
|
||||
{
|
||||
LLViewerInventoryItem* item = getItem();
|
||||
|
||||
if (item)
|
||||
{
|
||||
// open mesh
|
||||
}
|
||||
}
|
||||
|
||||
void LLMeshBridge::previewItem()
|
||||
{
|
||||
LLViewerInventoryItem* item = getItem();
|
||||
if(item)
|
||||
{
|
||||
// preview mesh
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
||||
{
|
||||
lldebugs << "LLMeshBridge::buildContextMenu()" << llendl;
|
||||
std::vector<std::string> items;
|
||||
std::vector<std::string> disabled_items;
|
||||
|
||||
if(isItemInTrash())
|
||||
{
|
||||
items.push_back(std::string("Purge Item"));
|
||||
if (!isItemRemovable())
|
||||
{
|
||||
disabled_items.push_back(std::string("Purge Item"));
|
||||
}
|
||||
|
||||
items.push_back(std::string("Restore Item"));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.push_back(std::string("Properties"));
|
||||
|
||||
getClipboardEntries(true, items, disabled_items, flags);
|
||||
}
|
||||
|
||||
|
||||
hide_context_entries(menu, items, disabled_items);
|
||||
}
|
||||
|
||||
|
||||
|
||||
LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
|
||||
const LLUUID& uuid,LLInventoryModel* model)
|
||||
{
|
||||
|
|
@ -5098,6 +5172,12 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
|
|||
|
||||
break;
|
||||
|
||||
case LLAssetType::AT_MESH:
|
||||
action = new LLMeshBridgeAction(uuid,model);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -5346,6 +5426,18 @@ void LLWearableBridgeAction::doIt()
|
|||
LLInvFVBridgeAction::doIt();
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLMeshBridgeAction::doIt()
|
||||
{
|
||||
LLViewerInventoryItem* item = getItem();
|
||||
if(item)
|
||||
{
|
||||
// do it
|
||||
}
|
||||
|
||||
LLInvFVBridgeAction::doIt();
|
||||
}
|
||||
|
||||
// +=================================================+
|
||||
// | LLLinkItemBridge |
|
||||
// +=================================================+
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue