2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

CWE Directory Reorganization

Rearrange directory structure of CWE to be loosely equivalent to
the H'uru Plasma repository.

Part 1: Movement of directories and files.
This commit is contained in:
rarified
2021-05-15 12:49:46 -06:00
parent c3f4a640a3
commit 96903e8dca
4002 changed files with 159 additions and 644 deletions

View File

@ -0,0 +1,61 @@
struct HS_POINT2_NAME {
HS_POINT2_TYPE fX, fY;
HS_POINT2_NAME& Set(HS_POINT2_TYPE x, HS_POINT2_TYPE y)
{
fX = x;
fY = y;
return *this;
}
HS_POINT2_NAME& operator+=(const HS_POINT2_NAME& s)
{
this->fX += s.fX;
this->fY += s.fY;
return *this;
}
HS_POINT2_NAME& operator-=(const HS_POINT2_NAME& s)
{
this->fX -= s.fX;
this->fY -= s.fY;
return *this;
}
#if 0 // Havok reeks
friend int operator==(const HS_POINT2_NAME& s, const HS_POINT2_NAME& t)
{
return (s.fX == t.fX && s.fY == t.fY);
}
friend int operator!=(const HS_POINT2_NAME& s, const HS_POINT2_NAME& t)
{
return !(s == t);
}
#else // Havok reeks
int operator==(const HS_POINT2_NAME& ss) const
{
return (ss.fX == fX && ss.fY == fY);
}
int operator!=(const HS_POINT2_NAME& ss)
{
return !(ss == *this);
}
#endif // Havok reeks
friend HS_POINT2_NAME operator+(const HS_POINT2_NAME& s, const HS_POINT2_NAME& t)
{
HS_POINT2_NAME result;
result.Set(s.fX + t.fX, s.fY + t.fY);
return result;
}
friend HS_POINT2_NAME operator-(const HS_POINT2_NAME& s, const HS_POINT2_NAME& t)
{
HS_POINT2_NAME result;
result.Set(s.fX - t.fX, s.fY - t.fY);
return result;
}
friend HS_POINT2_NAME operator-(const HS_POINT2_NAME& s)
{
HS_POINT2_NAME result = { -s.fX, -s.fY };
return result;
}
#undef HS_POINT2_NAME
#undef HS_POINT2_TYPE

View File

@ -0,0 +1,190 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "hsRefCnt.h"
#include "hsUtils.h"
#include "hsStlUtils.h"
#include "hsExceptions.h"
#if HS_BUILD_FOR_MAC
#include <Events.h>
#include <ToolUtils.h>
#include <Windows.h>
#endif
#if HS_BUILD_FOR_WIN32
# include <crtdbg.h> /* for _RPT_BASE */
# define WIN32_LEAN_AND_MEAN
# define WIN32_EXTRA_LEAN
# include <windows.h> // For OutputDebugString()
#endif
///////////////////////////////////////////////////////////////////////////
/////////////////// For Status Messages ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////
hsDebugMessageProc gHSStatusProc = nil;
hsDebugMessageProc hsSetStatusMessageProc(hsDebugMessageProc newProc)
{
hsDebugMessageProc oldProc = gHSStatusProc;
gHSStatusProc = newProc;
return oldProc;
}
//////////////////////////////////////////////////////////////////////////
hsDebugMessageProc gHSDebugProc = nil;
hsDebugMessageProc hsSetDebugMessageProc(hsDebugMessageProc newProc)
{
hsDebugMessageProc oldProc = gHSDebugProc;
gHSDebugProc = newProc;
return oldProc;
}
#ifdef HS_DEBUGGING
void hsDebugMessage (const char message[], long val)
{
char s[1024];
#if HS_BUILD_FOR_WIN32
#define strfmt _snprintf
#else
#define strfmt snprintf
#endif
if (val)
s[0] = strfmt(&s[1], 1022, "%s: %ld", message, val);
else
s[0] = strfmt(&s[1], 1022, "%s", message);
if (gHSDebugProc)
gHSDebugProc(&s[1]);
else
#if HS_BUILD_FOR_MAC
DebugStr((unsigned char*)s);
#elif HS_BUILD_FOR_WIN32
{ OutputDebugString(&s[1]);
OutputDebugString("\n");
}
#elif (HS_BUILD_FOR_BE || HS_BUILD_FOR_UNIX )
{ fprintf(stderr, "%s\n", &s[1]);
// hsThrow(&s[1]);
}
#elif HS_BUILD_FOR_PS2
fprintf(stderr, "%s\n", &s[1]);
#else
hsThrow(&s[1]);
#endif
}
#endif
///////////////////////////////////////////////////////////////////
hsRefCnt::~hsRefCnt()
{
hsDebugCode(hsThrowIfFalse(fRefCnt == 1);)
}
void hsRefCnt::Ref()
{
fRefCnt++;
}
void hsRefCnt::UnRef()
{
hsDebugCode(hsThrowIfFalse(fRefCnt >= 1);)
if (fRefCnt == 1) // don't decrement if we call delete
delete this;
else
--fRefCnt;
}
////////////////////////////////////////////////////////////////////////////
#ifndef PLASMA_EXTERNAL_RELEASE
void hsStatusMessage(const char message[])
{
if (gHSStatusProc) {
gHSStatusProc(message);
} else {
#if HS_BUILD_FOR_PS2 || HS_BUILD_FOR_UNIX
printf("%s",message);
int len = strlen(message);
if (len>0 && message[len-1]!='\n')
printf("\n");
#elif HS_BUILD_FOR_WIN32
OutputDebugString(message);
int len = strlen(message);
if (len>0 && message[len-1]!='\n')
OutputDebugString("\n");
#endif // MAC ?????? TODO
}
}
void hsStatusMessageV(const char * fmt, va_list args)
{
char buffer[2000];
vsprintf(buffer, fmt, args);
hsStatusMessage(buffer);
}
void hsStatusMessageF(const char * fmt, ...)
{
va_list args;
va_start(args,fmt);
hsStatusMessageV(fmt,args);
va_end(args);
}
#endif // not PLASMA_EXTERNAL_RELEASE

View File

@ -0,0 +1,51 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HeadSpinHDefined
#define HeadSpinHDefined
#include "hsConfig.h"
// Winsock2 compatibility; winsock2.h must always be included before windows.h =(
#include "hsWindows.h"
#include "hsTypes.h"
#include "hsMalloc.h"
#endif

View File

@ -0,0 +1,493 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsBiExpander_inc
#define hsBiExpander_inc
#include "hsMemory.h"
#include "hsTemplates.h"
///////////////////////////////////////////////////////////////////////////////
////////////// Expander ///////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
template <class T> class hsExpander {
private:
Int32 fNumPost;
Int32 fNumPostAlloc;
T* fArray;
Int32 fGrowBy; // default = 0, to double
Int32 fMinSize; // default = 1, min == 1
Int32 fCurrent;
hsExpander(const hsExpander& x); // make it passed as ref or pointer
void IExpand(int newSize);
public:
enum { kMissingIndex = -1 };
hsExpander(Int32 minSize = 1, Int32 growBy = 0);
virtual ~hsExpander();
hsExpander<T>& operator=(const hsExpander<T>&orig) { return Copy(orig); }
hsExpander<T>& Copy(const hsExpander<T>& orig);
void SetCount(int cnt) { if( cnt >= fNumPostAlloc )IExpand(cnt); fNumPost = cnt; }
Int32 GetCount() const { return fNumPost; }
hsBool Empty() const { return GetCount() == 0; }
const T& Get(Int32 index) const;
Int32 Get(Int32 index, Int32 count, T data[]) const;
Int32 Find(const T&) const; // returns kMissingIndex if not found
void SetArray(T* a, Int32 cnt);
T* GetArray() { return fArray; }
T& operator[]( Int32 index );
Int32 Append(const T&); // returns t's index
T* Append();
Int32 Push(const T& t) { return Append(t); }
T* Push() { return Append(); }
T* Top() { return fNumPost ? fArray + fNumPost-1 : nil; }
Int32 Pop(T* t); // returns count of remaining
Int32 Pop();
void Reset(); // clears out everything
T& Head() { return fArray[0]; }
T& Tail() { return fArray[fNumPost-1]; }
T& Current() { return fArray[fCurrent]; }
void First();
void Last();
void Plus() { ++fCurrent; }
hsBool More() { return (fCurrent < fNumPost); }
};
template <class T>
hsExpander<T>& hsExpander<T>::Copy(const hsExpander<T>& orig)
{
SetCount(orig.GetCount());
int i;
for( i = 0; i < GetCount(); i++ )
fArray[i] = orig.fArray[i];
return *this;
}
template <class T>
void hsExpander<T>::SetArray(T* a, Int32 cnt)
{
delete [] fArray;
if( a )
fArray = a;
fNumPost = fNumPostAlloc = cnt;
}
template <class T>
void hsExpander<T>::IExpand(int newSize)
{
Int32 newPostAlloc = fNumPostAlloc;
if( !newPostAlloc )
newPostAlloc++;
while( newPostAlloc <= newSize )
newPostAlloc = fGrowBy ? newPostAlloc + fGrowBy : newPostAlloc << 1;
T* newArray = TRACKED_NEW T[newPostAlloc];
int i;
for( i = 0; i < fNumPost; i++ )
newArray[i] = fArray[i];
delete [] (fArray);
fArray = newArray;
fNumPostAlloc = newPostAlloc;
}
template <class T>
hsExpander<T>::hsExpander(Int32 minSize, Int32 growBy)
{
hsThrowIfBadParam(minSize < 0);
hsThrowIfBadParam(growBy < 0);
fMinSize = minSize+1;
fGrowBy = growBy;
fArray = TRACKED_NEW T[fMinSize];
fNumPostAlloc = fMinSize;
fNumPost = 0;
}
template <class T>
hsExpander<T>::~hsExpander()
{
delete [] fArray;
}
template <class T>
void hsExpander<T>::First()
{
fCurrent = 0;
}
template <class T>
void hsExpander<T>::Last()
{
fCurrent = fNumPost-1;
}
template <class T>
T& hsExpander<T>::operator[]( Int32 index )
{
hsDebugCode(hsThrowIfBadParam((index < 0)||(index >= fNumPost));)
return fArray[index];
}
template <class T>
const T& hsExpander<T>::Get( Int32 index ) const
{
hsDebugCode(hsThrowIfBadParam((index < 0)||(index >= fNumPost));)
return fArray[index];
}
template <class T>
Int32 hsExpander<T>::Get(Int32 index, Int32 count, T data[]) const
{
if( count > 0 )
{ hsThrowIfNilParam(data);
hsThrowIfBadParam((index < 0)||(index >= fNumPost));
if (index + count > fNumPost)
count = fNumPost - index;
for (int i = 0; i < count; i++)
data[i] = fArray[i + index];
}
return count;
}
template <class T>
Int32 hsExpander<T>::Find(const T& obj) const
{
for (int i = 0; i < fNumPost; i++)
if (fArray[i] == obj)
return i;
return kMissingIndex;
}
template <class T>
Int32 hsExpander<T>::Append(const T& obj)
{
hsAssert(!(fNumPost >= fNumPostAlloc), "Must be less");
if( fNumPost == fNumPostAlloc-1 )
IExpand(fNumPostAlloc);
fArray[fNumPost] = obj;
return fNumPost++;
}
template <class T>
T* hsExpander<T>::Append()
{
hsAssert(!(fNumPost >= fNumPostAlloc), "Must be less");
if( fNumPost == fNumPostAlloc-1 )
IExpand(fNumPostAlloc);
return fArray + fNumPost++;
}
template <class T>
Int32 hsExpander<T>::Pop(T*t)
{
hsThrowIfBadParam(Empty());
--fNumPost;
if( t )
*t = fArray[fNumPost];
return GetCount();
}
template <class T>
Int32 hsExpander<T>::Pop()
{
hsThrowIfBadParam(Empty());
--fNumPost;
return GetCount();
}
template <class T>
void hsExpander<T>::Reset()
{
fNumPost = 0;
}
///////////////////////////////////////////////////////////////////////////////
////////////// BiExpander /////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
template <class T> class hsBiExpander {
private:
Int32 fNumPre;
Int32 fNumPost;
Int32 fNumPreAlloc;
Int32 fNumPostAlloc;
T* fArray;
Int32 fGrowBy; // default = 0, to double
Int32 fMinSize; // default = 1, min == 1
Int32 fCurrent;
hsBiExpander<T>& operator=(const hsBiExpander<T>&); // don't allow assignment
hsBiExpander(const hsBiExpander<T>&); // make it passed as ref or pointer
void IExpand(int newSize, hsBool towardEnd = true);
public:
enum { kMissingIndex = -1 };
hsBiExpander(Int32 minSize = 1, Int32 growBy = 0);
virtual ~hsBiExpander();
Int32 GetFirst() const { return -fNumPre; }
Int32 GetCount() const { return fNumPre + fNumPost; }
hsBool Empty() const { return GetCount() == 0; }
const T& Get(Int32 index) const;
Int32 Get(Int32 index, Int32 count, T data[]) const;
Int32 Find(const T&) const; // returns kMissingIndex if not found
void SetArray(T* a, Int32 cnt, Int32 numPre=0);
T** GetArray() { return fArray - fNumPre; }
T& operator[]( Int32 index );
T* Append(); // returns t's index
T* Push(); // returns t's index
Int32 Append(const T&); // returns t's index
Int32 Push(const T&); // returns t's index
Int32 Pop(T*t = nil) { return PopHead(t); } // returns count of remaining
Int32 PopHead(T*t = nil); // returns count of remaining
Int32 PopTail(T*t = nil); // returns count of remaining
void Reset(); // clears out everything
T& Head() { return fArray[-fNumPre]; }
T& Tail() { return fArray[fNumPost-1]; }
T& Current() { return fArray[fCurrent]; }
void First();
void Last();
void Plus() { ++fCurrent; }
void Minus() { --fCurrent; }
hsBool More() { return (fCurrent < fNumPost)&&(fCurrent >= -fNumPre); }
};
template <class T>
void hsBiExpander<T>::SetArray(T* a, Int32 cnt, Int32 numPre)
{
if( !numPre )
Reset();
else
{
fNumPreAlloc = fNumPre = numPre;
fNumPostAlloc = fNumPost = cnt - numPre;
fArray = a + numPre;
}
}
template <class T>
void hsBiExpander<T>::IExpand(int newSize, hsBool towardEnd)
{
Int32 newPreAlloc = fNumPreAlloc;
Int32 newPostAlloc = fNumPostAlloc;
if( towardEnd )
{
if( !newPostAlloc )
newPostAlloc++;
while( newPostAlloc <= newSize )
newPostAlloc = fGrowBy ? newPostAlloc + fGrowBy : newPostAlloc << 1;
}
else
{
if( !newPreAlloc )
newPreAlloc++;
while( newPreAlloc <= newSize )
newPreAlloc = fGrowBy ? newPreAlloc + fGrowBy : newPreAlloc << 1;
}
T* newArray = TRACKED_NEW T[newPreAlloc + newPostAlloc];
newArray += newPreAlloc;
int i;
for( i = -fNumPre; i < fNumPost; i++ )
newArray[i] = fArray[i];
// HSMemory::BlockMove(fArray-fNumPre, newArray-fNumPre,
// (fNumPre+fNumPost)*sizeof(*fArray));
delete [] (fArray-fNumPreAlloc);
fArray = newArray;
fNumPreAlloc = newPreAlloc;
fNumPostAlloc = newPostAlloc;
}
template <class T>
hsBiExpander<T>::hsBiExpander(Int32 minSize, Int32 growBy)
{
hsThrowIfBadParam(minSize < 0);
hsThrowIfBadParam(growBy < 0);
fMinSize = minSize+1;
fGrowBy = growBy;
fArray = TRACKED_NEW T[fMinSize << 1];
fNumPreAlloc = fNumPostAlloc = fMinSize;
fArray += fNumPreAlloc;
fNumPre = fNumPost = 0;
}
template <class T>
hsBiExpander<T>::~hsBiExpander()
{
delete [] (fArray - fNumPreAlloc);
}
template <class T>
void hsBiExpander<T>::First()
{
fCurrent = -fNumPre;
}
template <class T>
void hsBiExpander<T>::Last()
{
fCurrent = fNumPost-1;
}
template <class T>
T& hsBiExpander<T>::operator[]( Int32 index )
{
hsDebugCode(hsThrowIfBadParam((index < -fNumPre)||(index >= fNumPost));)
return fArray[index];
}
template <class T>
const T& hsBiExpander<T>::Get( Int32 index ) const
{
hsDebugCode(hsThrowIfBadParam((index < -fNumPre)||(index >= fNumPost));)
return fArray[index];
}
template <class T>
Int32 hsBiExpander<T>::Get(Int32 index, Int32 count, T data[]) const
{
if( count > 0 )
{ hsThrowIfNilParam(data);
hsThrowIfBadParam((index < -fNumPre)||(index >= fNumPost));
if (index + count > fNumPost)
count = fNumPost - index;
for (int i = 0; i < count; i++)
data[i] = fArray[i + index];
}
return count;
}
template <class T>
Int32 hsBiExpander<T>::Find(const T& obj) const
{
for (int i = -fNumPre; i < fNumPost; i++)
if (fArray[i] == obj)
return i;
return kMissingIndex;
}
template <class T>
T* hsBiExpander<T>::Append()
{
hsAssert(!(fNumPost >= fNumPostAlloc), "Must be less");
if( fNumPost == fNumPostAlloc-1 )
IExpand(fNumPostAlloc, true);
return fArray + fNumPost++;
}
template <class T>
T* hsBiExpander<T>::Push()
{
hsAssert(!(fNumPre >= fNumPreAlloc), "Must be less");
if( ++fNumPre == fNumPreAlloc )
IExpand(fNumPreAlloc, false);
return fArray - fNumPre;
}
template <class T>
Int32 hsBiExpander<T>::Append(const T& obj)
{
hsAssert(!(fNumPost >= fNumPostAlloc), "Must be less");
if( fNumPost == fNumPostAlloc-1 )
IExpand(fNumPostAlloc, true);
fArray[fNumPost] = obj;
return fNumPost++;
}
template <class T>
Int32 hsBiExpander<T>::Push(const T& obj)
{
hsAssert(!(fNumPre >= fNumPreAlloc), "Must be less");
if( ++fNumPre == fNumPreAlloc )
IExpand(fNumPreAlloc, false);
fArray[-fNumPre] = obj;
return -fNumPre;
}
template <class T>
Int32 hsBiExpander<T>::PopHead(T*t)
{
hsThrowIfBadParam(Empty());
if( t )
*t = fArray[-fNumPre];
--fNumPre;
return GetCount();
}
template <class T>
Int32 hsBiExpander<T>::PopTail(T*t)
{
hsThrowIfBadParam(Empty());
--fNumPost;
if( t )
*t = fArray[fNumPost];
return GetCount();
}
template <class T>
void hsBiExpander<T>::Reset()
{
fNumPre = fNumPost = 0;
}
#endif // hsBiExpander_inc

View File

@ -0,0 +1,221 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsStream.h"
#include "hsBitVector.h"
#include "hsTemplates.h"
#include <stdarg.h>
hsBitVector::hsBitVector(int b, ...)
: fBitVectors(nil),
fNumBitVectors(0)
{
va_list vl;
va_start( vl, b );
do {
SetBit( b, true );
} while( (b = va_arg( vl, int )) >= 0 );
va_end( vl );
}
hsBitVector::hsBitVector(const hsTArray<Int16>& src)
: fBitVectors(nil),
fNumBitVectors(0)
{
FromList(src);
}
void hsBitVector::IGrow(UInt32 newNumBitVectors)
{
hsAssert(newNumBitVectors > fNumBitVectors, "Growing smaller");
UInt32 *old = fBitVectors;
fBitVectors = TRACKED_NEW UInt32[newNumBitVectors];
int i;
for( i = 0; i < fNumBitVectors; i++ )
fBitVectors[i] = old[i];
for( ; i < newNumBitVectors; i++ )
fBitVectors[i] = 0;
delete [] old;
fNumBitVectors = newNumBitVectors;
}
hsBitVector& hsBitVector::Compact()
{
if( !fBitVectors )
return *this;
if( fBitVectors[fNumBitVectors-1] )
return *this;
int hiVec = 0;
for( hiVec = fNumBitVectors-1; (hiVec >= 0)&& !fBitVectors[hiVec]; --hiVec );
if( hiVec >= 0 )
{
UInt32 *old = fBitVectors;
fBitVectors = TRACKED_NEW UInt32[++hiVec];
int i;
for( i = 0; i < hiVec; i++ )
fBitVectors[i] = old[i];
fNumBitVectors = hiVec;
delete [] old;
}
else
{
Reset();
}
return *this;
}
void hsBitVector::Read(hsStream* s)
{
Reset();
s->LogReadSwap(&fNumBitVectors,"NumBitVectors");
if( fNumBitVectors )
{
delete [] fBitVectors;
fBitVectors = TRACKED_NEW UInt32[fNumBitVectors];
int i;
for( i = 0; i < fNumBitVectors; i++ )
s->LogReadSwap(&fBitVectors[i],"BitVector");
}
}
void hsBitVector::Write(hsStream* s) const
{
s->WriteSwap32(fNumBitVectors);
int i;
for( i = 0; i < fNumBitVectors; i++ )
s->WriteSwap32(fBitVectors[i]);
}
hsTArray<Int16>& hsBitVector::Enumerate(hsTArray<Int16>& dst) const
{
dst.SetCount(0);
hsBitIterator iter(*this);
int i = iter.Begin();
while( i >= 0 )
{
dst.Append(i);
i = iter.Advance();
}
return dst;
}
hsBitVector& hsBitVector::FromList(const hsTArray<Int16>& src)
{
Clear();
int i;
for( i = 0; i < src.GetCount(); i++ )
SetBit(src[i]);
return *this;
}
//////////////////////////////////////////////////////////////////////////
int hsBitIterator::IAdvanceVec()
{
hsAssert((fCurrVec >= 0) && (fCurrVec < fBits.fNumBitVectors), "Invalid state to advance from");
while( (++fCurrVec < fBits.fNumBitVectors) && !fBits.fBitVectors[fCurrVec] );
return fCurrVec < fBits.fNumBitVectors;
}
int hsBitIterator::IAdvanceBit()
{
do
{
if( ++fCurrBit > 31 )
{
if( !IAdvanceVec() )
return false;
fCurrBit = 0;
}
} while( !(fBits.fBitVectors[fCurrVec] & (1 << fCurrBit)) );
return true;
}
int hsBitIterator::Advance()
{
if( End() )
return -1;
if( !IAdvanceBit() )
return fCurrVec = -1;
return fCurrent = (fCurrVec << 5) + fCurrBit;
}
int hsBitIterator::Begin()
{
fCurrent = -1;
fCurrVec = -1;
int i;
for( i = 0; i < fBits.fNumBitVectors; i++ )
{
if( fBits.fBitVectors[i] )
{
int j;
for( j = 0; j < 32; j++ )
{
if( fBits.fBitVectors[i] & (1 << j) )
{
fCurrVec = i;
fCurrBit = j;
return fCurrent = (fCurrVec << 5) + fCurrBit;
}
}
}
}
return fCurrent;
}

View File

@ -0,0 +1,410 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsBitVector_inc
#define hsBitVector_inc
#include "hsTypes.h"
template <class T> class hsTArray;
class hsStream;
class hsBitVector {
protected:
UInt32* fBitVectors;
UInt32 fNumBitVectors;
void IGrow(UInt32 newNumBitVectors);
friend class hsBitIterator;
public:
hsBitVector(const hsBitVector& other);
hsBitVector(UInt32 which) : fBitVectors(nil), fNumBitVectors(0) { SetBit(which); }
hsBitVector(int b, ...); // list of one or more integer bits to set. -1 (or any negative) terminates the list (e.g. hsBitVector(0,1,4,-1);
hsBitVector(const hsTArray<Int16>& list); // sets bit for each int in list
hsBitVector() : fBitVectors(nil), fNumBitVectors(0) {}
virtual ~hsBitVector() { Reset(); }
hsBitVector& Reset() { delete [] fBitVectors; fBitVectors = nil; fNumBitVectors = 0; return *this; }
hsBitVector& Clear(); // everyone clear, but no dealloc
hsBitVector& Set(int upToBit=-1); // WARNING - see comments at function
int operator==(const hsBitVector& other) const; // unset (ie uninitialized) bits are clear,
int operator!=(const hsBitVector& other) const { return !(*this == other); }
hsBitVector& operator=(const hsBitVector& other); // will wind up identical
hsBool ClearBit(UInt32 which) { return SetBit(which, 0); } // returns previous state
hsBool SetBit(UInt32 which, hsBool on = true); // returns previous state
hsBool IsBitSet(UInt32 which) const; // returns current state
hsBool ToggleBit(UInt32 which); // returns previous state
hsBitVector& RemoveBit(UInt32 which); // removes bit, sliding higher bits down to fill the gap.
friend inline int Overlap(const hsBitVector& lhs, const hsBitVector& rhs) { return lhs.Overlap(rhs); }
hsBool Overlap(const hsBitVector& other) const;
hsBool Empty() const;
hsBool operator[](UInt32 which) const { return IsBitSet(which); }
friend inline hsBitVector operator&(const hsBitVector& lhs, const hsBitVector& rhs); // See Overlap()
friend inline hsBitVector operator|(const hsBitVector& lhs, const hsBitVector& rhs);
friend inline hsBitVector operator^(const hsBitVector& lhs, const hsBitVector& rhs);
friend inline hsBitVector operator-(const hsBitVector& lhs, const hsBitVector& rhs); // return lhs w/ rhs's bits turned off
hsBitVector& operator&=(const hsBitVector& other); // See Overlap()
hsBitVector& operator|=(const hsBitVector& other);
hsBitVector& operator^=(const hsBitVector& other);
hsBitVector& operator-=(const hsBitVector& other); // return me w/ other's bits turned off
hsBitVector& Compact();
hsBitVector& SetSize(UInt32 numBits) { ClearBit(numBits+1); return *this; }
UInt32 GetSize() { return fNumBitVectors << 5; }
// integer level access
UInt32 GetNumBitVectors() const { return fNumBitVectors; }
UInt32 GetBitVector(int i) const { return fBitVectors[i]; }
void SetNumBitVectors(UInt32 n) { Reset(); fNumBitVectors=n; fBitVectors = TRACKED_NEW UInt32[n]; }
void SetBitVector(int i, UInt32 val) { fBitVectors[i]=val; }
// Do dst.SetCount(0), then add each set bit's index into dst, returning dst.
hsTArray<Int16>& Enumerate(hsTArray<Int16>& dst) const;
// this->Clear(), then set all bits listed in src, returning *this.
hsBitVector& FromList(const hsTArray<Int16>& src);
void Read(hsStream* s);
void Write(hsStream* s) const;
};
inline hsBitVector::hsBitVector(const hsBitVector& other)
{
if( 0 != (fNumBitVectors = other.fNumBitVectors) )
{
fBitVectors = TRACKED_NEW UInt32[fNumBitVectors];
int i;
for( i = 0; i < fNumBitVectors; i++ )
fBitVectors[i] = other.fBitVectors[i];
}
else
fBitVectors = nil;
}
inline hsBool hsBitVector::Empty() const
{
int i;
for( i = 0; i < fNumBitVectors; i++ )
{
if( fBitVectors[i] )
return false;
}
return true;
}
inline hsBool hsBitVector::Overlap(const hsBitVector& other) const
{
if( fNumBitVectors > other.fNumBitVectors )
return other.Overlap(*this);
int i;
for( i = 0; i < fNumBitVectors; i++ )
{
if( fBitVectors[i] & other.fBitVectors[i] )
return true;
}
return false;
}
inline hsBitVector& hsBitVector::operator=(const hsBitVector& other)
{
if( this != &other )
{
if( fNumBitVectors < other.fNumBitVectors )
{
Reset();
fNumBitVectors = other.fNumBitVectors;
fBitVectors = TRACKED_NEW UInt32[fNumBitVectors];
}
else
{
Clear();
}
int i;
for( i = 0; i < other.fNumBitVectors; i++ )
fBitVectors[i] = other.fBitVectors[i];
}
return *this;
}
inline int hsBitVector::operator==(const hsBitVector& other) const
{
if( fNumBitVectors < other.fNumBitVectors )
return other.operator==(*this);
int i;
for( i = 0; i < other.fNumBitVectors; i++ )
if( fBitVectors[i] ^ other.fBitVectors[i] )
return false;
for( ; i < fNumBitVectors; i++ )
if( fBitVectors[i] )
return false;
return true;
}
inline hsBitVector& hsBitVector::operator&=(const hsBitVector& other)
{
if( this == &other )
return *this;
if( fNumBitVectors > other.fNumBitVectors )
{
fNumBitVectors = other.fNumBitVectors;
}
int i;
for( i = 0; i < fNumBitVectors; i++ )
fBitVectors[i] &= other.fBitVectors[i];
return *this;
}
inline hsBitVector& hsBitVector::operator|=(const hsBitVector& other)
{
if( this == &other )
return *this;
if( fNumBitVectors < other.fNumBitVectors )
{
IGrow(other.fNumBitVectors);
}
int i;
for( i = 0; i < other.fNumBitVectors; i++ )
fBitVectors[i] |= other.fBitVectors[i];
return *this;
}
inline hsBitVector& hsBitVector::operator^=(const hsBitVector& other)
{
if( this == &other )
{
Clear();
return *this;
}
if( fNumBitVectors < other.fNumBitVectors )
{
IGrow(other.fNumBitVectors);
}
int i;
for( i = 0; i < other.fNumBitVectors; i++ )
fBitVectors[i] ^= other.fBitVectors[i];
return *this;
}
inline hsBitVector& hsBitVector::operator-=(const hsBitVector& other)
{
if( this == &other )
{
Clear();
return *this;
}
int minNum = fNumBitVectors < other.fNumBitVectors ? fNumBitVectors : other.fNumBitVectors;
int i;
for( i = 0; i < minNum; i++ )
fBitVectors[i] &= ~other.fBitVectors[i];
return *this;
}
inline hsBitVector operator&(const hsBitVector& rhs, const hsBitVector& lhs)
{
hsBitVector ret(rhs);
return ret &= lhs;
}
inline hsBitVector operator|(const hsBitVector& rhs, const hsBitVector& lhs)
{
hsBitVector ret(rhs);
return ret |= lhs;
}
inline hsBitVector operator^(const hsBitVector& rhs, const hsBitVector& lhs)
{
hsBitVector ret(rhs);
return ret ^= lhs;
}
inline hsBitVector operator-(const hsBitVector& rhs, const hsBitVector& lhs)
{
hsBitVector ret(rhs);
return ret -= lhs;
}
inline hsBitVector& hsBitVector::Clear()
{
int i;
for( i = 0; i < fNumBitVectors; i++ )
fBitVectors[i] = 0;
return *this;
}
// WARNING - since the bitvector is conceptually infinitely long,
// we can't actually set all the bits. If you pass in a non-negative
// upToBit, this sets all bits up to and including that one, otherwise
// it just sets however many bits are currently allocated. You can
// assure this is as many as you want by first calling SetSize, but
// if there are more bits than the requested size, these will also
// get set. Calling Set with a non-negative upToBit will only set
// the bits from 0 to upToBit, but won't clear any higher bits.
inline hsBitVector& hsBitVector::Set(int upToBit)
{
if( upToBit >= 0 )
{
UInt32 major = upToBit >> 5;
UInt32 minor = 1 << (upToBit & 0x1f);
if( major >= fNumBitVectors )
IGrow(major+1);
UInt32 i;
for( i = 0; i < major; i++ )
fBitVectors[i] = 0xffffffff;
for( i = 1; i <= minor && i > 0; i <<= 1 )
fBitVectors[major] |= i;
}
else
{
int i;
for( i = 0; i < fNumBitVectors; i++ )
fBitVectors[i] = 0xffffffff;
}
return *this;
}
inline hsBool hsBitVector::IsBitSet(UInt32 which) const
{
UInt32 major = which >> 5;
return
(major < fNumBitVectors)
&& (0 != (fBitVectors[major] & 1 << (which & 0x1f)));
}
inline hsBool hsBitVector::SetBit(UInt32 which, hsBool on)
{
UInt32 major = which >> 5;
UInt32 minor = 1 << (which & 0x1f);
if( major >= fNumBitVectors )
IGrow(major+1);
hsBool ret = 0 != (fBitVectors[major] & minor);
if( ret != on )
{
if( on )
fBitVectors[major] |= minor;
else
fBitVectors[major] &= ~minor;
}
return ret;
}
inline hsBool hsBitVector::ToggleBit(UInt32 which)
{
UInt32 major = which >> 5;
UInt32 minor = 1 << (which & 0x1f);
if( major >= fNumBitVectors )
IGrow(major);
hsBool ret = 0 != (fBitVectors[major] & minor);
if( ret )
fBitVectors[major] &= ~minor;
else
fBitVectors[major] |= minor;
return ret;
}
inline hsBitVector& hsBitVector::RemoveBit(UInt32 which)
{
UInt32 major = which >> 5;
if( major >= fNumBitVectors )
return *this;
UInt32 minor = 1 << (which & 0x1f);
UInt32 lowMask = minor-1;
UInt32 hiMask = ~(lowMask);
fBitVectors[major] = (fBitVectors[major] & lowMask)
| ((fBitVectors[major] >> 1) & hiMask);
while( major < fNumBitVectors-1 )
{
if( fBitVectors[major+1] & 0x1 )
fBitVectors[major] |= 0x80000000;
else
fBitVectors[major] &= ~0x80000000;
major++;
fBitVectors[major] >>= 1;
}
fBitVectors[major] &= ~0x80000000;
return *this;
}
class hsBitIterator
{
protected:
const hsBitVector& fBits;
int fCurrent;
int fCurrVec;
int fCurrBit;
int IAdvanceBit();
int IAdvanceVec();
public:
// Must call begin after instanciating.
hsBitIterator(const hsBitVector& bits) : fBits(bits) {}
int Begin();
int Current() const { return fCurrent; }
int Advance();
int End() const { return fCurrVec < 0; }
};
#endif // hsBitVector_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,439 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsBounds_inc
#define hsBounds_inc
#include "hsGeometry3.h"
#include "hsPoint2.h"
#include "hsMatrix44.h"
class hsTriangle3;
class hsGView3;
class hsG3DDevice;
///////////////////////////////////////////////////////////////////////////////
// BOUNDS
///////////////////////////////////////////////////////////////////////////////
enum hsBoundsType
{
kBoundsNormal,
kBoundsFull,
kBoundsEmpty,
kBoundsUninitialized
};
//
// Abstract base class
//
class hsBounds3;
class hsBounds
{
protected:
hsBoundsType fType;
public:
static const hsScalar kRealSmall;
hsBounds() : fType(kBoundsUninitialized) { };
hsBounds& MakeEmpty() { fType = kBoundsEmpty; return *this; }
hsBounds& MakeFull() { fType = kBoundsFull; return *this; }
hsBoundsType GetType() const { return fType; }
//
// These set type to kBounds Normal
//
virtual void Reset(const hsBounds3*) = 0;
virtual hsBool IsInside(const hsPoint3* pos) const =0; // Only valid for kBounds Normal
virtual void Read(hsStream*);
virtual void Write(hsStream*);
};
//
//
//
class hsGTriMesh;
struct hsMatrix44;
class hsBounds3 : public hsBounds
{
public:
enum {
kCenterValid = 0x1,
kIsSphere = 0x2
};
protected:
mutable UInt32 fBounds3Flags;
hsPoint3 fMins;
hsPoint3 fMaxs;
mutable hsPoint3 fCenter;
void ICalcCenter() const;
public:
hsBounds3() : fBounds3Flags(0) {}
hsBounds3(const hsBounds3 &pRHS) : fBounds3Flags(0) { Reset(&pRHS); }
hsBounds3 &operator=(const hsBounds3 &pRHS )
{ if (&pRHS != this) Reset(&pRHS); return *this; }
//
// These set type to kBounds Normal
//
virtual void Reset(const hsBounds3*);
virtual void Reset(const hsPoint3 *p);
virtual void Reset(int n, const hsPoint3 *p);
virtual void Union(const hsPoint3 *p);
virtual void Union(const hsBounds3 *b);
virtual void Union(const hsVector3 *v); // smears the bounds in given direction
virtual void MakeSymmetric(const hsPoint3* p); // Expands bounds to be symmetric about p
virtual void InscribeSphere();
virtual void Transform(const hsMatrix44*);
//
// Only valid for kBounds Normal
//
void Draw(hsGView3* v, hsG3DDevice* d, hsScalar r, hsScalar g, hsScalar b, hsScalar a, hsBool spheric=false);
virtual void GetCorners(hsPoint3 *b) const;
const hsPoint3& GetMins() const;
const hsPoint3& GetMaxs() const;
hsScalar GetMaxDim() const; // Computes the answer
const hsPoint3& GetCenter() const; // Computes the answer if not already there
// void MakeTriMesh(hsGTriMesh* tMesh, UInt32 triFlags, hsPoint3* cornersIn=nil) const;
// void MakeTriMeshSphere(hsGTriMesh* tMesh, hsPoint3* cornersIn=nil) const;
virtual hsBool IsInside(const hsPoint3* pos) const; // ok for full/empty
virtual void TestPlane(const hsVector3 &n, hsPoint2 &depth) const;
virtual void TestPlane(const hsPlane3 *p, hsPoint2 &depth) const;
virtual hsBool ClosestPoint(const hsPoint3& p, hsPoint3& inner, hsPoint3& outer) const;
// Test according to my axes only, doesn't check other's axes
// neg, pos, zero == disjoint, I contain other, overlap
virtual Int32 TestBound(const hsBounds3& other) const;
static hsScalar ClosestPointToLine(const hsPoint3 *p, const hsPoint3 *v0, const hsPoint3 *v1, hsPoint3 *out);
static hsScalar ClosestPointToInfiniteLine(const hsPoint3* p, const hsVector3* v, hsPoint3* out);
virtual void Read(hsStream*);
virtual void Write(hsStream*);
};
inline void hsBounds3::ICalcCenter() const
{
hsAssert(kBoundsNormal == fType, "Invalid type for ICalcCenter");
fCenter = ((fMins + fMaxs) / 2.0);
fBounds3Flags |= kCenterValid;
}
inline void hsBounds3::GetCorners(hsPoint3 *b) const
{
hsAssert(kBoundsNormal == fType, "Invalid type for GetCorners");
for(int i = 0; i < 8; i++)
{
b[i][0] = (i & 0x1) ? fMins[0] : fMaxs[0];
b[i][1] = (i & 0x2) ? fMins[1] : fMaxs[1];
b[i][2] = (i & 0x4) ? fMins[2] : fMaxs[2];
}
}
inline const hsPoint3& hsBounds3::GetMins() const
{
hsAssert(kBoundsNormal == fType, "Invalid type for GetMins");
return fMins;
}
inline const hsPoint3& hsBounds3::GetMaxs() const
{
hsAssert(kBoundsNormal == fType, "Invalid type for GetMaxs");
return fMaxs;
}
inline const hsPoint3& hsBounds3::GetCenter() const
{
hsAssert(kBoundsNormal == fType, "Invalid type for GetCenter");
if(!(fBounds3Flags & kCenterValid))
ICalcCenter();
return fCenter;
}
inline hsScalar hsBounds3::GetMaxDim() const
{
hsAssert(kBoundsNormal == fType, "Invalid type for GetMaxDim");
return hsMaximum(hsMaximum(fMaxs.fX-fMins.fX, fMaxs.fY-fMins.fY), fMaxs.fZ-fMins.fZ);
}
//
// A convex region specified by a series of planes.
//
class hsBoundsOriented : public hsBounds
{
private:
hsBool fCenterValid;
hsPoint3 fCenter;
hsPlane3 *fPlanes;
UInt32 fNumPlanes;
public:
hsBoundsOriented() : fPlanes(nil),fNumPlanes(0),fCenterValid(false) {}
virtual ~hsBoundsOriented() { if (fPlanes) delete [] fPlanes; }
// Center is not computed by the class, it must be set by the creator of the class.
void SetCenter(const hsPoint3* c) { fCenter=*c; fCenterValid = true; }
void SetCenter(const hsBounds3* b) { hsBounds3 bb=*b; fCenter=bb.GetCenter(); fCenterValid = true; }
void SetCenter(const hsBoundsOriented* b) { fCenter=b->GetCenter(); fCenterValid = true; }
hsPoint3 GetCenter() const;
void SetNumberPlanes(UInt32 n);
hsPlane3* GetPlane(int i) { return &fPlanes[i]; }
int GetNumPlanes() { return fNumPlanes; }
//
// These set type to kBounds Normal
//
virtual void Reset(const hsBounds3*);
void Reset(hsGTriMesh *tMesh);
void SetPlane(UInt32 i, hsPlane3 *p);
//
// Only valid for kBounds Normal
//
virtual hsBool IsInside(const hsPoint3* pos) const;
virtual void TestPlane(const hsVector3 &n, hsPoint2 &depth) const; // Complain and refuse
virtual void Write(hsStream *stream);
virtual void Read(hsStream *stream);
};
//class hsBounds3Tri;
class hsHitInfoExt;
class hsBounds3Ext : public hsBounds3 {
protected:
enum {
kAxisAligned =0x1,
kSphereSet =0x2,
kDistsSet =0x4,
kAxisZeroZero =(1<<20),
kAxisOneZero =(1<<21),
kAxisTwoZero =(1<<22)
};
mutable UInt32 fExtFlags;
hsPoint3 fCorner;
hsVector3 fAxes[3];
mutable hsPoint2 fDists[3];
mutable hsScalar fRadius;
hsBool IAxisIsZero(UInt32 i) const { return (fExtFlags & (1 << (20+i))) != 0; };
void IMakeSphere() const;
void IMakeDists() const;
void IMakeMinsMaxs();
public:
hsBounds3Ext() : fExtFlags(kAxisAligned) {};
hsBounds3Ext(const hsBounds3 &b);
hsBounds3Ext &operator=(const hsBounds3 &b);
hsBounds3Ext(const hsBounds3Ext &pRHS) { Reset(&pRHS); }
hsBounds3Ext &operator=(const hsBounds3Ext &pRHS )
{ if (&pRHS != this) Reset(&pRHS); return *this; }
virtual void Reset(const hsBounds3Ext *b);
virtual void Reset(const hsBounds3 *b);
virtual void Reset(const hsPoint3 *p);
virtual void Reset(int n, const hsPoint3 *p);
virtual void Union(const hsPoint3 *p);
virtual void Union(const hsBounds3 *b);
virtual void Union(const hsVector3 *v); // smears the bounds in given direction
virtual void MakeSymmetric(const hsPoint3* p); // Expands bounds to be symmetric about p
virtual void InscribeSphere();
virtual void Unalign();
virtual void Transform(const hsMatrix44 *m);
virtual void Translate(const hsVector3 &v);
virtual hsScalar GetRadius() const;
virtual void GetAxes(hsVector3 *fAxis0, hsVector3 *fAxis1, hsVector3 *fAxis2) const;
virtual hsPoint3 *GetCorner(hsPoint3 *c) const { *c = (fExtFlags & kAxisAligned ? fMins : fCorner); return c; }
virtual void GetCorners(hsPoint3 *b) const;
virtual hsBool ClosestPoint(const hsPoint3& p, hsPoint3& inner, hsPoint3& outer) const;
virtual hsBool IsInside(const hsPoint3* pos) const; // ok for full/empty
virtual void TestPlane(const hsVector3 &n, hsPoint2 &depth) const;
virtual Int32 TestPoints(int n, const hsPoint3 *pList) const; // pos,neg,zero == allout, allin, cut
// Test according to my axes only, doesn't check other's axes
// neg, pos, zero == disjoint, I contain other, overlap
virtual Int32 TestBound(const hsBounds3Ext& other) const;
virtual void TestPlane(const hsVector3 &n, const hsVector3 &myVel, hsPoint2 &depth) const;
virtual void TestPlane(const hsPlane3 *p, const hsVector3 &myVel, hsPoint2 &depth) const;
virtual Int32 TestPoints(int n, const hsPoint3 *pList, const hsVector3 &ptVel) const; // pos,neg,zero == allout, allin, cut
virtual hsBool ISectBB(const hsBounds3Ext &other, const hsVector3 &myVel) const;
virtual hsBool ISectBB(const hsBounds3Ext &other, const hsVector3 &myVel, hsHitInfoExt *hit) const;
virtual hsBool ISectABB(const hsBounds3Ext &other, const hsVector3 &myVel) const;
virtual hsBool ISectBS(const hsBounds3Ext &other, const hsVector3 &myVel) const;
#if 0 // Commenting out this which will be made redundant and/or obsolete by Havok integration
virtual hsBool ISectTriABB(hsBounds3Tri &tri, const hsVector3 &myVel) const;
virtual hsBool ISectTriBB(hsBounds3Tri &tri, const hsVector3 &myVel) const;
virtual hsBool ISectTriBB(hsBounds3Tri &tri, const hsVector3 &myVel, hsHitInfoExt *hit) const;
virtual hsBool TriBSHitInfo(hsBounds3Tri& tri, const hsVector3& myVel, hsHitInfoExt* hit) const;
virtual hsBool TriBBHitInfo(hsBounds3Tri& tri, const hsVector3& myVel, hsHitInfoExt* hit) const;
#endif // Commenting out this which will be made redundant and/or obsolete by Havok integration
virtual Int32 IClosestISect(const hsBounds3Ext& other, const hsVector3& myVel,
hsScalar* tClose, hsScalar* tImpact) const;
#if 0 // Commenting out this which will be made redundant and/or obsolete by Havok integration
virtual hsBool ISectTriBS(hsBounds3Tri &tri, const hsVector3 &myVel) const;
virtual hsBool ISectTriBS(hsBounds3Tri &tri, const hsVector3 &myVel, hsHitInfoExt *hit) const;
#endif // Commenting out this which will be made redundant and/or obsolete by Havok integration
virtual hsBool ISectBoxBS(const hsBounds3Ext &other, const hsVector3 &myVel, hsHitInfoExt *hit) const;
virtual hsBool ISectBSBox(const hsBounds3Ext &other, const hsVector3 &myVel, hsHitInfoExt *hit) const;
virtual hsBool ISectBoxBS(const hsBounds3Ext &other, const hsVector3 &myVel) const;
virtual hsBool ISectBSBS(const hsBounds3Ext &other, const hsVector3 &myVel, hsHitInfoExt *hit) const;
virtual hsBool ISectLine(const hsPoint3* from, const hsPoint3* to) const;
virtual hsBool ISectCone(const hsPoint3* from, const hsPoint3* to, hsScalar radius) const;
virtual hsBool ISectRayBS(const hsPoint3& from, const hsPoint3& to, hsPoint3& at) const;
virtual void Read(hsStream *s);
virtual void Write(hsStream *s);
};
inline hsScalar hsBounds3Ext::GetRadius() const
{
if( !(fExtFlags & kSphereSet) )
IMakeSphere();
return fRadius;
}
#if 0 // Commenting out this which will be made redundant and/or obsolete by Havok integration
class hsBounds3Tri {
protected:
enum {
kOnEdge0 = (1 << 0),
kOnEdge1 = (1 << 1),
kOnEdge2 = (1 << 2),
kOnTriPlane = (1 << 3)
};
public:
enum {
kAxesSet = 0x1,
kDoubleSide = 0x2
};
hsVector3 fNormal;
// hsVector3 fNormal;
hsScalar fDist;
hsPoint3 fVerts[3];
// hsVector3 fPerpAxes[3];
mutable UInt32 fTriFlags;
mutable hsVector3 fPerpAxes[3];
mutable hsPoint2 fPerpDists[3];
mutable UInt32 fOnIsMax;
hsTriangle3* fTriangle;
void TestPlane(const hsVector3 &n, hsPoint2 &depth) const;
hsBool PointOutsideTriPlane(const hsPoint3 *p) const { return fNormal.InnerProduct(p) > fDist; };
hsBool ClosestTriPoint(const hsPoint3 *p, hsPoint3 *out, const hsVector3 *ax=nil) const; // sets out, true if out = p + t*fNormal
hsBool ISectCone(const hsPoint3& from, const hsPoint3& to, hsScalar cosThetaSq, hsBool32 ignoreBackFacing, hsPoint3& at, hsBool32& backSide) const;
void SetAxes() const;
hsBounds3Tri* Transform(const hsMatrix44& x);
hsBounds3Tri* Translate(const hsVector3& v);
void Set(const hsPoint3& v0,
const hsPoint3& v1,
const hsPoint3& v2,
hsTriangle3* t,
const hsMatrix44& x);
hsBounds3Tri(const hsPoint3& v0,
const hsPoint3& v1,
const hsPoint3& v2,
hsTriangle3* t,
const hsMatrix44& x);
hsBounds3Tri(hsTriangle3* t,
const hsMatrix44& x);
void Set(hsPoint3 *v0,
hsPoint3 *v1,
hsPoint3 *v2,
hsVector3 *n,
UInt32 triFlags,
hsTriangle3 *t=nil);
hsBounds3Tri(hsPoint3 *v0,
hsPoint3 *v1,
hsPoint3 *v2,
hsVector3 *n,
UInt32 triFlags,
hsTriangle3 *t=nil);
hsBounds3Tri(hsTriangle3* t);
hsBounds3Tri() {}
~hsBounds3Tri();
friend class hsBounds3Ext;
} ATTRIBUTE_FOR_PS2; /* SUNSOFT */
#endif // Commenting out this which will be made redundant and/or obsolete by Havok integration
class hsHitInfoExt {
public:
hsScalar fDepth;
hsVector3 fNormal;
hsVector3 fDelPos;
#if 0 // Commenting out this which will be made redundant and/or obsolete by Havok integration
const hsBounds3Tri* fTriBnd;
#endif // Commenting out this which will be made redundant and/or obsolete by Havok integration
const hsBounds3Ext* fBoxBnd;
const hsBounds3Ext* fOtherBoxBnd;
const hsPoint3* fRootCenter;
hsHitInfoExt(const hsPoint3 *ctr, const hsVector3& offset) { fRootCenter=ctr; fDelPos=offset; };
#if 0 // Commenting out this which will be made redundant and/or obsolete by Havok integration
void Set(const hsBounds3Ext *m, const hsBounds3Tri *t, const hsVector3* n, hsScalar d)
{ fDepth = d; fTriBnd = t; fBoxBnd = m; fNormal = *n; fOtherBoxBnd = nil; }
void Set(const hsBounds3Ext *m, const hsBounds3Ext *o, const hsVector3 &norm, hsScalar d)
{ fDepth = d; fBoxBnd = m, fOtherBoxBnd = o; fNormal = norm; fTriBnd = nil; }
#else // Commenting out this which will be made redundant and/or obsolete by Havok integration
void Set(const hsBounds3Ext *m, const hsVector3* n, hsScalar d)
{ fDepth = d; fBoxBnd = m; fNormal = *n; fOtherBoxBnd = nil; }
void Set(const hsBounds3Ext *m, const hsBounds3Ext *o, const hsVector3 &norm, hsScalar d)
{ fDepth = d; fBoxBnd = m, fOtherBoxBnd = o; fNormal = norm; }
#endif // Commenting out this which will be made redundant and/or obsolete by Havok integration
};
#endif // hsBounds_inc

View File

@ -0,0 +1,196 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsColorRGBA_inc
#define hsColorRGBA_inc
#include "hsScalar.h"
#include "hsStream.h"
struct hsColorRGBA {
hsScalar r,g,b,a;
hsRGBAColor32 ToRGBA32() const;
hsColorRGBA& Set(hsScalar red, hsScalar grn, hsScalar blu, hsScalar alp) { r = red; g = grn; b = blu; a = alp; return *this; }
hsBool operator==(const hsColorRGBA&c) const { return (r==c.r)&&(g==c.g)&&(b==c.b)&&(a==c.a); }
hsBool operator!=(const hsColorRGBA&c) const { return !(c == *this); }
friend inline hsColorRGBA operator+(const hsColorRGBA& s, const hsColorRGBA& t);
hsColorRGBA& operator+=(const hsColorRGBA& s);
friend inline hsColorRGBA operator*(const hsColorRGBA& s, const hsColorRGBA& t);
hsColorRGBA& operator*=(const hsColorRGBA& s);
friend inline hsColorRGBA operator-(const hsColorRGBA& s, const hsColorRGBA& t);
hsColorRGBA& operator-=(const hsColorRGBA& s);
friend inline hsColorRGBA operator*(const hsColorRGBA& c, const hsScalar s);
friend inline hsColorRGBA operator*(const hsScalar s, const hsColorRGBA& c);
hsColorRGBA& operator*=(const hsScalar s);
hsColorRGBA& FromARGB32(UInt32 c);
UInt32 ToARGB32() const;
UInt32 ToARGB32Premultiplied() const;
void Read(hsStream *stream);
void Write(hsStream *stream) const;
};
inline void hsColorRGBA::Read(hsStream *s)
{
r = s->ReadSwapScalar();
g = s->ReadSwapScalar();
b = s->ReadSwapScalar();
a = s->ReadSwapScalar();
}
inline void hsColorRGBA::Write(hsStream *s) const
{
s->WriteSwapScalar(r);
s->WriteSwapScalar(g);
s->WriteSwapScalar(b);
s->WriteSwapScalar(a);
}
inline hsColorRGBA& hsColorRGBA::FromARGB32(UInt32 c)
{
const hsScalar oo255 = 1.f / 255.f;
a = hsScalar((c >> 24) & 0xff) * oo255;
r = hsScalar((c >> 16) & 0xff) * oo255;
g = hsScalar((c >> 8) & 0xff) * oo255;
b = hsScalar((c >> 0) & 0xff) * oo255;
return *this;
}
inline UInt32 hsColorRGBA::ToARGB32() const
{
return (UInt32(a * 255.99f) << 24)
| (UInt32(r * 255.99f) << 16)
| (UInt32(g * 255.99f) << 8)
| (UInt32(b * 255.99f) << 0);
}
inline UInt32 hsColorRGBA::ToARGB32Premultiplied() const
{
return (UInt32(a * 255.0f + 0.5f) << 24)
| (UInt32(a * r * 255.0f + 0.5f) << 16)
| (UInt32(a * g * 255.0f + 0.5f) << 8)
| (UInt32(a * b * 255.0f + 0.5f) << 0);
}
inline hsColorRGBA operator+(const hsColorRGBA& s, const hsColorRGBA& t)
{
hsColorRGBA res;
return res.Set(s.r + t.r, s.g + t.g, s.b + t.b, s.a + t.a);
}
inline hsColorRGBA& hsColorRGBA::operator+=(const hsColorRGBA& s)
{
r += s.r;
g += s.g;
b += s.b;
a += s.a;
return *this;
}
inline hsColorRGBA operator*(const hsColorRGBA& s, const hsColorRGBA& t)
{
hsColorRGBA res;
return res.Set(s.r * t.r, s.g * t.g, s.b * t.b, s.a * t.a);
}
inline hsColorRGBA& hsColorRGBA::operator*=(const hsColorRGBA& s)
{
r *= s.r;
g *= s.g;
b *= s.b;
a *= s.a;
return *this;
}
inline hsColorRGBA operator-(const hsColorRGBA& s, const hsColorRGBA& t)
{
hsColorRGBA res;
return res.Set(s.r - t.r, s.g - t.g, s.b - t.b, s.a - t.a);
}
inline hsColorRGBA& hsColorRGBA::operator-=(const hsColorRGBA& s)
{
r -= s.r;
g -= s.g;
b -= s.b;
a -= s.a;
return *this;
}
inline hsColorRGBA operator*(const hsColorRGBA& t, const hsScalar s)
{
hsColorRGBA res;
return res.Set(s * t.r, s * t.g, s * t.b, s * t.a);
}
inline hsColorRGBA operator*(const hsScalar s, const hsColorRGBA&t)
{
return t * s;
}
inline hsColorRGBA& hsColorRGBA::operator*=(const hsScalar s)
{
r *= s;
g *= s;
b *= s;
a *= s;
return *this;
}
class hsColorOverride
{
public:
enum {
kNone,
kModColor,
kModAlpha,
kModShade
};
hsColorRGBA fShade;
hsColorRGBA fColor;
hsBool fFlags;
};
#endif // hsColorRGBA_inc

View File

@ -0,0 +1,185 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#ifndef hsConfigDefined
#define hsConfigDefined
#ifndef SERVER
# define CLIENT
#endif
#ifdef BUILDPS2
#define HS_BUILD_FOR_PS2 1
#define PLASMA_NO_NETWORK 1
#define PLASMA_NO_KEYBOARD 1
#define PLASMA_NO_GLIDE 1
#define PLASMA_NO_DDRAW 1
#define HS_BUILD_PLASMA 1
#define NEXUS_NO_2D 1
#endif
//////////////////// Change the 1s and 0s //////////////////////
#define HS_CAN_USE_FLOAT 1
#define HS_SCALAR_IS_FLOAT 1
#define HS_PIN_MATH_OVERFLOW 0 // This forces hsWide versions of FixMath routines
#define HS_DEBUG_MATH_OVERFLOW 0 // This calls hsDebugMessage on k[Pos,Neg]Infinity
///////////////////////Impulse Defines////////////////////////////////////////////////
#define HS_IMPULSE_SUPPORT_GRAY4 0
///////////////////////Plasma Defines //////////////////////////////////////////////////
#ifdef HS_BUILD_PLASMA
#define HS_IGNORE_T2K 1
#define HS_SUPPORT_NFNT_FONTS 1
#endif // HS_BUILD_PLASMA
//////////////////// Specific Compiler Stuff This Section is computed ////////////
#if defined(macintosh) && defined(__POWERPC__)
#define HS_BUILD_FOR_MACPPC 1
#define HS_CPU_BENDIAN 1
#elif defined(macintosh)
#define HS_BUILD_FOR_MAC68K 1
#elif defined(_M_IX86) && defined(_WIN32)
#define HS_BUILD_FOR_WIN32 1
#define HS_CPU_LENDIAN 1
#elif defined(__unix__)
#define HS_BUILD_FOR_UNIX 1
#if defined(__intel__) || defined(__i386__)
#define HS_CPU_LENDIAN 1
#elif defined(__mips__)
#define HS_CPU_BENDIAN 1
#endif
#elif !HS_BUILD_FOR_PS2
#define HS_BUILD_FOR_REFERENCE 1
#endif
#if defined(HS_BUILD_FOR_MAC68K) || defined(HS_BUILD_FOR_MACPPC)
#define HS_BUILD_FOR_MAC 1
#endif
#if defined(__INTEL__) && defined(HS_BUILD_FOR_MAC)
#error "Can't have HS_BUILD_FOR_MAC defined"
#endif
#if (defined(GENERATING68K) || defined(GENERATINGPOWERPC)) && defined(HS_BUILD_FOR_WIN32)
#define "Can't define HS_BUILD_FOR_WIN32"
#endif
#define HS_SCALAR_IS_FIXED !(HS_SCALAR_IS_FLOAT)
#define HS_NEVER_USE_FLOAT !(HS_CAN_USE_FLOAT)
#if HS_DEBUG_MATH_OVERFLOW && !(HS_PIN_MATH_OVERFLOW)
#error "Can't debug overflow unless HS_PIN_MATH_OVERFLOW is ON"
#endif
///////////////////////Windows Specific Defines /////////////////////////////
#if HS_BUILD_FOR_WIN32
// 4244: Conversion
// 4305: Truncation
// 4503: 'identifier' : decorated name length exceeded, name was truncated
// 4018: signed/unsigned mismatch
// 4786: 255 character debug limit
// 4284: STL template defined operator-> for a class it doesn't make sense for (int, etc)
#if !__MWERKS__
#pragma warning( disable : 4305 4503 4018 4786 4284)
#endif
// VC++ version greater than 6.0, must be building for .NET
#if defined(_MSC_VER) && (_MSC_VER > 1200)
#define HS_BUILD_FOR_WIN32_NET
#endif
#pragma optimize( "y", off )
#endif
/////////////////////Debugging Defines ///////////////////////////////////
#if (defined(_DEBUG)||defined(UNIX_DEBUG)) && !defined(HS_DISABLE_ASSERT)
#define HS_DEBUGGING
#if (!defined(HS_NO_MEM_TRACKER))
#define HS_FIND_MEM_LEAKS
#endif
#endif
#if HS_BUILD_FOR_PS2
#define ATTRIBUTE_FOR_PS2 __attribute__((aligned (16))) /* SUNSOFT */
#else
#define ATTRIBUTE_FOR_PS2
#endif
/////////////////////Myst3D Defines /////////////////////////////////////
#ifdef M3DRELEASE
#define PLASMA_NO_NETWORK 1
#define NEXUS_NO_2D 1
#define NO_LOAD_MSG 1
#define PLASMA_NO_CONSOLE 1
#define NEXUS_NO_DEBUG 1
#endif
///////////////////// Required facilities ///////////////////////////////
#ifndef HeadSpinHDefined
#include "HeadSpin.h"
#endif
#endif // hsConfigDefined

View File

@ -0,0 +1,83 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/CoreLib/hsCritSect.cpp
*
*
* By Eric Anderson (10/23/2005)
* Copyright 2005 Cyan Worlds, Inc.
*
***/
#include "HeadSpin.h"
#include "hsCritSect.h"
#pragma hdrstop
/****************************************************************************
*
* Critical section implementation
*
***/
#ifdef HS_BUILD_FOR_WIN32
//===========================================================================
CCritSect::CCritSect () {
InitializeCriticalSection(&m_handle);
}
//===========================================================================
CCritSect::~CCritSect () {
DeleteCriticalSection(&m_handle);
}
//===========================================================================
void CCritSect::Enter () {
EnterCriticalSection(&m_handle);
}
//===========================================================================
void CCritSect::Leave () {
LeaveCriticalSection(&m_handle);
}
#endif

View File

@ -0,0 +1,79 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/CoreLib/hsCritSect.h
*
*
* By Eric Anderson (10/23/2005)
* Copyright 2005 Cyan Worlds, Inc.
*
***/
#ifndef PLASMA20_SOURCES_PLASMA_CORELIB_HSCRITSECT_H
#define PLASMA20_SOURCES_PLASMA_CORELIB_HSCRITSECT_H
/****************************************************************************
*
* Critical section
*
***/
#ifdef HS_BUILD_FOR_WIN32
typedef CRITICAL_SECTION CritSectHandle;
#else
# error "CCritSect: Not implemented on this platform"
#endif
class CCritSect {
protected:
CritSectHandle m_handle;
public:
CCritSect ();
~CCritSect ();
void Enter ();
void Leave ();
};
#endif // PLASMA20_SOURCES_PLASMA_CORELIB_HSCRITSECT_H

View File

@ -0,0 +1,51 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsExceptionStack.h"
hsExceptionStack* hsExceptionStack::fExceptionStack;
hsExceptionStackDestroyer hsExceptionStack::fExceptionStackDestroyer;
void hsExceptionStack::FreeInstance()
{
delete fExceptionStack;
fExceptionStack = nil;
}

View File

@ -0,0 +1,126 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsExceptionStack_inc
#define hsExceptionStack_inc
#include "hsUtils.h"
#include "hsTypes.h"
#include "hsTemplates.h"
class hsExceptionStackDestroyer;
//
// hsExceptionStack - logs function/scope IDs added by hsStackToken
//
class hsExceptionStack
{
friend class hsExceptionStackDestroyer;
private:
hsExceptionStack() { }
public:
~hsExceptionStack() { }
static hsExceptionStack& Instance();
Int32 GetNumEntries() const { return fEntries.Count(); }
const char* GetEntry(Int32 i) const { return fEntries[i]; }
void Push(const char* str);
// After an exception is caught and stack has been displayed,
// call continue to flush stack
void Continue() { fEntries.Reset(); }
private:
static void FreeInstance();
hsTArray<const char*> fEntries;
static hsExceptionStack* fExceptionStack;
static hsExceptionStackDestroyer fExceptionStackDestroyer;
};
inline hsExceptionStack& hsExceptionStack::Instance()
{
if (!fExceptionStack)
{
fExceptionStack = TRACKED_NEW hsExceptionStack;
}
return *fExceptionStack;
}
inline void hsExceptionStack::Push(const char* str)
{
fEntries.Append(str);
}
//
// hsExceptionStackDestroyer - removes the hsExceptionStack instance
//
class hsExceptionStackDestroyer
{
public:
~hsExceptionStackDestroyer()
{
hsExceptionStack::FreeInstance();
}
};
#ifdef HS_DEBUGGING
#define HS_NO_TRY
#endif
#ifdef HS_NO_TRY
#define hsGuardBegin(X)
#define hsGuardEnd
#else // HS_NO_TRY
#define hsGuardBegin(X) { const char* guardToken = X; try {
#define hsGuardEnd } catch(...) { hsExceptionStack::Instance().Push(guardToken); throw; } }
#endif // HS_NO_TRY
#endif // hsExceptionStack_inc

View File

@ -0,0 +1,212 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsExceptionDefined
#define hsExceptionDefined
#include "hsTypes.h"
// #define HS_NO_EXCEPTIONS -- this will turn off execptions you might want
// to do it with -D or equivalent instead of here since who knows who includes this.
enum hsErrorEnum {
kNo_hsError,
kBadAlloc_hsError,
kNilParam_hsError,
kBadParam_hsError,
kInternal_hsError,
kOS_hsError
};
//////////////////////////////////////////////////////////////////////////////
class hsException {
public:
hsErrorEnum fError;
long fParam;
hsException(hsErrorEnum error, long param = 0) : fError(error), fParam(param) {}
};
class hsBadAllocException : public hsException {
public:
hsBadAllocException() : hsException(kBadAlloc_hsError) {}
};
class hsNilParamException : public hsException {
public:
hsNilParamException() : hsException(kNilParam_hsError) {}
};
class hsBadParamException : public hsException {
public:
hsBadParamException() : hsException(kBadParam_hsError) {}
};
class hsInternalException : public hsException {
public:
hsInternalException() : hsException(kInternal_hsError) {}
};
class hsOSException : public hsException {
public:
hsOSException(long error) : hsException(kOS_hsError, error) {}
};
/////////////////////////////////////////////////////////////////////////////////
#ifndef HS_NO_EXCEPTIONS
#define hsThrow(a) {hsAssert(0,#a);throw a;}
#define hsCatch(a) catch (a)
#define hsCatch2(a,b) catch (a b)
#define hsTry try
inline void hsThrowIfNilParam(const void* p)
{
if (p == nil)
{
hsAssert(0,"hsNilParamException");
throw hsNilParamException();
}
}
inline void hsThrowIfBadParam(hsBool trueIfBadParam)
{
if (trueIfBadParam)
{
hsAssert(0,"hsBadParamException");
throw hsBadParamException();
}
}
inline void hsThrowIfOSErr(long osErr)
{
if (osErr != 0)
{
hsAssert(0,"hsOSException");
throw hsOSException(osErr);
}
}
inline void hsThrowIfTrue(hsBool condition)
{
if (condition)
{
hsAssert(0,"hsThrowIfTrue");
throw hsInternalException();
}
}
inline void hsThrowIfFalse(hsBool condition)
{
if (condition == false)
{
hsAssert(0,"hsThrowIfFalse");
throw hsInternalException();
}
}
inline void hsThrowIfTrue(hsBool condition, const char message[])
{
if (condition)
{
hsAssert(0,message);
throw message;
}
}
inline void hsThrowIfFalse(hsBool condition, const char message[])
{
if (condition == false)
{
hsAssert(0,message);
throw message;
}
}
#else
#define hsThrow(a) {hsAssert(0,#a);}
#define hsCatch(a) if(0)
#define hsCatch2(a,b) if(0)
#define hsTry
inline void hsThrowIfNilParam(const void* p)
{
hsAssert(p!=nil,"hsThrowIfNilParam");
}
inline void hsThrowIfBadParam(hsBool trueIfBadParam)
{
hsAssert(!trueIfBadParam,"hsThrowIfBadParam");
}
inline void hsThrowIfOSErr(long osErr)
{
hsAssert(osErr==0,"hsThrowIfOSErr");
}
inline void hsThrowIfTrue(hsBool condition)
{
hsAssert(!condition,"hsThrowIfTrue");
}
inline void hsThrowIfFalse(hsBool condition)
{
hsAssert(condition,"hsThrowIfFalse");
}
inline void hsThrowIfTrue(hsBool condition, const char message[])
{
hsAssert(!condition,message);
}
inline void hsThrowIfFalse(hsBool condition, const char message[])
{
hsAssert(condition,message);
}
#endif
#endif

View File

@ -0,0 +1,642 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsScalar.h"
#include "hsGeometry3.h"
#include "hsFastMath.h"
const hsScalar hsFastMath::kSqrtTwo = hsSquareRoot(2.f);
const hsScalar hsFastMath::kInvSqrtTwo = hsScalarInvert(hsFastMath::kSqrtTwo);
const hsScalar hsFastMath::kTwoPI = hsScalarPI * 2.f;
hsPoint2 statCosSinTable[9] = // must match length in inline
{
{ 1.f, 0.f },
{ hsFastMath::kInvSqrtTwo, hsFastMath::kInvSqrtTwo },
{ 0.f, 1.f },
{ -hsFastMath::kInvSqrtTwo, hsFastMath::kInvSqrtTwo },
{ -1.f, 0.f },
{ -hsFastMath::kInvSqrtTwo, -hsFastMath::kInvSqrtTwo },
{ 0.f, -1.f },
{ hsFastMath::kInvSqrtTwo, -hsFastMath::kInvSqrtTwo },
{ 1.f, 0.f }
};
const hsPoint2* hsFastMath::fCosSinTable = statCosSinTable;
unsigned char statSeedTable[] = {
0x69,
0x69,
0x68,
0x67,
0x67,
0x66,
0x65,
0x65,
0x64,
0x63,
0x63,
0x62,
0x61,
0x61,
0x60,
0x5f,
0x5f,
0x5e,
0x5d,
0x5d,
0x5c,
0x5b,
0x5b,
0x5a,
0x5a,
0x59,
0x58,
0x58,
0x57,
0x57,
0x56,
0x55,
0x55,
0x54,
0x54,
0x53,
0x52,
0x52,
0x51,
0x51,
0x50,
0x50,
0x4f,
0x4e,
0x4e,
0x4d,
0x4d,
0x4c,
0x4c,
0x4b,
0x4b,
0x4a,
0x4a,
0x49,
0x48,
0x48,
0x47,
0x47,
0x46,
0x46,
0x45,
0x45,
0x44,
0x44,
0x43,
0x43,
0x42,
0x42,
0x41,
0x41,
0x40,
0x40,
0x3f,
0x3f,
0x3e,
0x3e,
0x3d,
0x3d,
0x3c,
0x3c,
0x3c,
0x3b,
0x3b,
0x3a,
0x3a,
0x39,
0x39,
0x38,
0x38,
0x37,
0x37,
0x36,
0x36,
0x36,
0x35,
0x35,
0x34,
0x34,
0x33,
0x33,
0x33,
0x32,
0x32,
0x31,
0x31,
0x30,
0x30,
0x30,
0x2f,
0x2f,
0x2e,
0x2e,
0x2e,
0x2d,
0x2d,
0x2c,
0x2c,
0x2b,
0x2b,
0x2b,
0x2a,
0x2a,
0x29,
0x29,
0x29,
0x28,
0x28,
0x28,
0x27,
0x27,
0x26,
0x26,
0x26,
0x25,
0x25,
0x25,
0x24,
0x24,
0x23,
0x23,
0x23,
0x22,
0x22,
0x22,
0x21,
0x21,
0x20,
0x20,
0x20,
0x1f,
0x1f,
0x1f,
0x1e,
0x1e,
0x1e,
0x1d,
0x1d,
0x1d,
0x1c,
0x1c,
0x1c,
0x1b,
0x1b,
0x1b,
0x1a,
0x1a,
0x1a,
0x19,
0x19,
0x19,
0x18,
0x18,
0x18,
0x17,
0x17,
0x17,
0x16,
0x16,
0x16,
0x15,
0x15,
0x15,
0x14,
0x14,
0x14,
0x13,
0x13,
0x13,
0x13,
0x12,
0x12,
0x12,
0x11,
0x11,
0x11,
0x10,
0x10,
0x10,
0xf,
0xf,
0xf,
0xf,
0xe,
0xe,
0xe,
0xd,
0xd,
0xd,
0xd,
0xc,
0xc,
0xc,
0xb,
0xb,
0xb,
0xb,
0xa,
0xa,
0xa,
0x9,
0x9,
0x9,
0x9,
0x8,
0x8,
0x8,
0x7,
0x7,
0x7,
0x7,
0x6,
0x6,
0x6,
0x6,
0x5,
0x5,
0x5,
0x5,
0x4,
0x4,
0x4,
0x3,
0x3,
0x3,
0x3,
0x2,
0x2,
0x2,
0x2,
0x1,
0x1,
0x1,
0x1,
0x0,
0x0,
0x0,
0xff,
0xfe,
0xfd,
0xfc,
0xfb,
0xfa,
0xf9,
0xf8,
0xf7,
0xf7,
0xf6,
0xf5,
0xf4,
0xf3,
0xf2,
0xf1,
0xf0,
0xef,
0xee,
0xed,
0xec,
0xec,
0xeb,
0xea,
0xe9,
0xe8,
0xe7,
0xe6,
0xe5,
0xe5,
0xe4,
0xe3,
0xe2,
0xe1,
0xe0,
0xe0,
0xdf,
0xde,
0xdd,
0xdc,
0xdb,
0xdb,
0xda,
0xd9,
0xd8,
0xd8,
0xd7,
0xd6,
0xd5,
0xd4,
0xd4,
0xd3,
0xd2,
0xd1,
0xd1,
0xd0,
0xcf,
0xce,
0xce,
0xcd,
0xcc,
0xcb,
0xcb,
0xca,
0xc9,
0xc9,
0xc8,
0xc7,
0xc7,
0xc6,
0xc5,
0xc4,
0xc4,
0xc3,
0xc2,
0xc2,
0xc1,
0xc0,
0xc0,
0xbf,
0xbe,
0xbe,
0xbd,
0xbc,
0xbc,
0xbb,
0xba,
0xba,
0xb9,
0xb8,
0xb8,
0xb7,
0xb7,
0xb6,
0xb5,
0xb5,
0xb4,
0xb3,
0xb3,
0xb2,
0xb2,
0xb1,
0xb0,
0xb0,
0xaf,
0xaf,
0xae,
0xad,
0xad,
0xac,
0xac,
0xab,
0xaa,
0xaa,
0xa9,
0xa9,
0xa8,
0xa8,
0xa7,
0xa7,
0xa6,
0xa5,
0xa5,
0xa4,
0xa4,
0xa3,
0xa3,
0xa2,
0xa2,
0xa1,
0xa0,
0xa0,
0x9f,
0x9f,
0x9e,
0x9e,
0x9d,
0x9d,
0x9c,
0x9c,
0x9b,
0x9b,
0x9a,
0x9a,
0x99,
0x99,
0x98,
0x98,
0x97,
0x97,
0x96,
0x96,
0x95,
0x95,
0x94,
0x94,
0x93,
0x93,
0x92,
0x92,
0x91,
0x91,
0x90,
0x90,
0x8f,
0x8f,
0x8e,
0x8e,
0x8d,
0x8d,
0x8c,
0x8c,
0x8b,
0x8b,
0x8b,
0x8a,
0x8a,
0x89,
0x89,
0x88,
0x88,
0x87,
0x87,
0x87,
0x86,
0x86,
0x85,
0x85,
0x84,
0x84,
0x83,
0x83,
0x83,
0x82,
0x82,
0x81,
0x81,
0x80,
0x80,
0x80,
0x7f,
0x7f,
0x7e,
0x7e,
0x7d,
0x7d,
0x7d,
0x7c,
0x7c,
0x7b,
0x7b,
0x7b,
0x7a,
0x7a,
0x79,
0x79,
0x79,
0x78,
0x78,
0x77,
0x77,
0x77,
0x76,
0x76,
0x75,
0x75,
0x75,
0x74,
0x74,
0x74,
0x73,
0x73,
0x72,
0x72,
0x72,
0x71,
0x71,
0x71,
0x70,
0x70,
0x6f,
0x6f,
0x6f,
0x6e,
0x6e,
0x6e,
0x6d,
0x6d,
0x6c,
0x6c,
0x6c,
0x6b,
0x6b,
0x6b,
0x6a,
0x6a
};
hsScalar hsFastMath::IATan2OverTwoPi(hsScalar y, hsScalar x)
{
const int tabSize = 16; // pad with one extra because hi can go hi
const int tabMax = tabSize-1;
static hsScalar tab[tabSize+1] = {
0.f,
0.0105947f,
0.0210962f,
0.0314165f,
0.0414762f,
0.0512082f,
0.0605595f,
0.0694914f,
0.0779791f,
0.0860104f,
0.0935835f,
0.100705f,
0.107388f,
0.113651f,
0.119514f,
0.125f,
0 };
if( (x == 0)&&(y == 0) )
return 0;
hsBool xNeg, yNeg;
if( yNeg = (y < 0) )y = -y;
if( xNeg = (x < 0) )x = -x;
hsBool yBigger = y >= x;
hsScalar div = yBigger ? x / y : y / x;
hsScalar fInd = div * tabMax;
int lo = int(fInd);
int hi = lo+1;
hsScalar frac = fInd - lo;
hsScalar res = tab[lo];
res += frac * (tab[hi] - res);
// now move to proper half quadrant
hsAssert((res >= 0)&&(res <= 0.25f), "Lookup atan2 out of bounds");
if( yBigger )
res = 0.25f - res;
switch( (yNeg << 1)|xNeg )
{
case 0:
break;
case 1:
res = 0.5f - res;
break;
case 3:
res += 0.5f;
break;
case 2:
res = 1.f - res;
break;
}
return res;
}

View File

@ -0,0 +1,306 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsFastMath_inc
#define hsFastMath_inc
#include "hsPoint2.h"
#include "hsGeometry3.h"
class hsFastMath {
protected:
static const hsPoint2* fCosSinTable;
public:
static const hsScalar kSqrtTwo;
static const hsScalar kInvSqrtTwo;
static const hsScalar kTwoPI;
static hsScalar IATan2OverTwoPi(hsScalar y, hsScalar x);
static inline hsScalar InvSqrtAppr(hsScalar x);
static inline hsScalar InvSqrt(hsScalar x);
static inline hsVector3& Normalize(hsVector3& v) { return (v *= InvSqrt(v.MagnitudeSquared())); }
static inline hsVector3& NormalizeAppr(hsVector3& v) { return (v *= InvSqrtAppr(v.MagnitudeSquared())); }
static inline void SinCosAppr(hsScalar rads, hsScalar& sinRads, hsScalar& cosRads);
static inline void SinCosInRangeAppr(hsScalar rads, hsScalar& sinRads, hsScalar& cosRads);
static inline void SinCos(hsScalar rads, hsScalar& sinRads, hsScalar& cosRads);
static inline void SinCosInRange(hsScalar ang, hsScalar& sinRads, hsScalar& cosRads);
static inline hsScalar Sin(hsScalar rads);
static inline hsScalar Cos(hsScalar rads);
static inline hsScalar SinInRange(hsScalar rads);
static inline hsScalar CosInRange(hsScalar rads);
};
// One over Square Root - from Graphics Gems
// Interesting combo's are
// NUM_ITER LOOKUP_BITS err frac us per call
// 0 8 5e-3 0.045
// 1 8 3e-5 0.082
// 0 6 1e-2 0.045
// 1 6 1e-4 0.082
// 2 6 1e-7 0.11
// 1 4 2e-3 0.082
// 2 4 5e-6 0.11
// 2 3 8e-5 0.11
// Tested on 5000 random numbers from [1.e-6..1.e3] over several runs
// These are tight loops, though, so they don't weigh in a bigger
// table trashing the cache.
#define NUM_ITER 0
#define LOOKUP_BITS 8
#define EXP_POS 23
#define EXP_BIAS 127
#define LOOKUP_POS (EXP_POS - LOOKUP_BITS)
#define SEED_POS (EXP_POS - 8)
#define TABLE_SIZE (2 << LOOKUP_BITS)
#define LOOKUP_MASK (TABLE_SIZE - 1)
#define GET_EXP(a) (((a) >> EXP_POS) & 0xff)
#define SET_EXP(a) ((a) << EXP_POS)
#define GET_EMANT(a) (((a) >> LOOKUP_POS) & LOOKUP_MASK)
#define SET_MANTSEED(a) (((unsigned long) (a)) << SEED_POS)
inline hsScalar hsFastMath::InvSqrtAppr(hsScalar x)
{
register unsigned long a = *(long*)&x;
register float arg = x;
union {
long i;
float f;
} seed;
register float r;
extern unsigned char statSeedTable[];
seed.i = SET_EXP(((3*EXP_BIAS - 1) - GET_EXP(a)) >> 1) | SET_MANTSEED(statSeedTable[GET_EMANT(a)]);
r = seed.f;
#if NUM_ITER > 0
r = (3.0f - r * r * arg) * r * 0.5f;
#if NUM_ITER > 1
r = (3.0f - r * r * arg) * r * 0.5f;
#endif
#endif
return r;
}
inline hsScalar hsFastMath::InvSqrt(hsScalar x)
{
register unsigned long a = *(long*)&x;
register float arg = x;
union {
long i;
float f;
} seed;
register float r;
extern unsigned char statSeedTable[];
seed.i = SET_EXP(((3*EXP_BIAS - 1) - GET_EXP(a)) >> 1) | SET_MANTSEED(statSeedTable[GET_EMANT(a)]);
r = seed.f;
r = (3.0f - r * r * arg) * r * 0.5f;
r = (3.0f - r * r * arg) * r * 0.5f;
return r;
}
inline void hsFastMath::SinCosAppr(hsScalar rads, hsScalar& sinRads, hsScalar& cosRads)
{
rads = fmodf(rads, kTwoPI);
if( rads < 0 )
rads += kTwoPI;
SinCosInRangeAppr(rads, sinRads, cosRads);
}
inline void hsFastMath::SinCosInRangeAppr(hsScalar rads, hsScalar& sinRads, hsScalar& cosRads)
{
const int kNumSinCosEntries = 8;
const hsScalar kNumEntriesOverTwoPI = kNumSinCosEntries * 0.5f / hsScalarPI;
hsScalar t = rads * kNumEntriesOverTwoPI;
int iLo = (int)t;
t -= iLo;
const hsPoint2* p = &fCosSinTable[iLo + 1];
cosRads = p->fX;
sinRads = p->fY;
p--;
cosRads -= p->fX;
sinRads -= p->fY;
cosRads *= t;
sinRads *= t;
cosRads += p->fX;
sinRads += p->fY;
}
inline hsScalar hsFastMath::Sin(hsScalar rads)
{
rads = fmodf(rads, kTwoPI);
if( rads < 0 )
rads += kTwoPI;
return SinInRange(rads);
}
inline hsScalar hsFastMath::Cos(hsScalar rads)
{
rads = fmodf(rads, kTwoPI);
if( rads < 0 )
rads += kTwoPI;
return CosInRange(rads);
}
inline hsScalar hsFastMath::SinInRange(hsScalar ang)
{
float sgn = 1.f;
if(ang >= (0.75f * kTwoPI))
ang -= kTwoPI;
else if(ang >= (0.25f * kTwoPI))
{
ang -= 3.141592654f;
sgn = -1.0f;
}
return (ang - (ang*ang*ang) * (1.0f/6.0f) + (ang*ang*ang*ang*ang) / 120.0f) * sgn;
}
inline hsScalar hsFastMath::CosInRange(hsScalar ang)
{
float sgn = 1.f;
if(ang >= (0.75f * kTwoPI))
ang -= kTwoPI;
else if(ang >= (0.25f * kTwoPI))
{
ang -= 3.141592654f;
sgn = -1.0f;
}
return (1.0f - (ang*ang / 2.0f) + (ang*ang*ang*ang) / 24.0f) *sgn;
}
inline void hsFastMath::SinCos(hsScalar rads, hsScalar& sinRads, hsScalar& cosRads)
{
rads = fmodf(rads, kTwoPI);
if( rads < 0 )
rads += kTwoPI;
SinCosInRange(rads, sinRads, cosRads);
}
inline void hsFastMath::SinCosInRange(hsScalar ang, hsScalar& sinRads, hsScalar& cosRads)
{
float sgn = 1.f;
if(ang >= (0.75f * kTwoPI))
ang -= kTwoPI;
else if(ang >= (0.25f * kTwoPI))
{
ang -= 3.141592654f;
sgn = -1.0f;
}
sinRads = (ang - (ang*ang*ang) * (1.0f/6.0f) + (ang*ang*ang*ang*ang) / 120.0f) * sgn;
cosRads = (1.0f - (ang*ang / 2.0f) + (ang*ang*ang*ang) / 24.0f) *sgn;
}
//
// Here's an interesting one from GDalgorithms, which doesn't need a LUT
// Not sure how the accuracy compares, but it's probably fine for this purpose.
#if 0 // For future reference
/*
From: "Jason Dorie" <jason.dorie@blackboxgames.com>
To: "GDAlgorithms" <gdalgorithms-list@lists.sourceforge.net>
Date: Wed, 14 Mar 2001 11:43:48 -0800
Subject: [Algorithms] Fast simultaneous Sin() and Cos()
Reply-To: gdalgorithms-list@lists.sourceforge.net
I know someone (Jason Zisk?) was looking for fast rotation matrix
generation code. I realize that a Sin/Cos lookup table is the way to go for
absolute speed, but if storage is a concern and the accuracy isn't, this
code is about 5x faster than using the built-in sin and cos instructions,
and accurate to about 4 decimal places.
If you really want speed, and don't care about accuracy, drop the 2nd
polynomial from each term. It's less accurate and faster still. It could
probably be made even faster by replacing the if/else with branchless code,
but I haven't bothered to figure out how yet.
My angles are 0-65535 so that they can be masked into range easily, stored
as shorts, and converted to normalized floats where necessary using SIMD
instructions.
*/
void FastSinCos(long Angle, float *pSin, float *pCos)
{
float ang, sgn;
ang = (Angle & 65535) * ((1.0f/65536.0f) * TwoPI);
sgn = 1.0f;
if(ang >= (0.75f * TwoPI))
ang -= TwoPI;
else if(ang >= (0.25f * TwoPI))
{
ang -= 3.141592654f;
sgn = -1.0f;
}
*pSin = (ang - (ang*ang*ang) * (1.0f/6.0f) + (ang*ang*ang*ang*ang) / 120.0f) * sgn;
*pCos = (1.0f - (ang*ang / 2.0f) + (ang*ang*ang*ang) / 24.0f) *sgn;
}
#endif // For future reference
#endif // hsFastMath_inc

View File

@ -0,0 +1,134 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsFixedTypesDefined
#define hsFixedTypesDefined
#include "hsTypes.h"
#if HS_BUILD_FOR_MAC
#include <ToolUtils.h>
#include <FixMath.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define hsIntToFixed(x) ((hsFixed)(x) << 16)
#define hsFixedToInt(x) ((x) >> 16)
#define hsFixedRound(x) (((x) + 0x8000) >> 16)
#define hsFixed1 hsIntToFixed(1)
#define hsFixedPI (0x3243F)
#define hsFixedPiOver2 (0x1921F)
#define hsFixedToFract(x) ((hsFract)(x) << 14)
#define hsFractToFixed(x) ((hsFixed)(x) >> 14)
#define hsFract1 hsFixedToFract(hsFixed1)
#define hsFractPiOver2 (0x6487ED34) /* needs some work */
#define hsFixFloor(x) \
(hsFixed)((x) < 0 ? -(hsFixed)((-(x) + 0xFFFF) & 0xFFFF0000) : (x) & 0xFFFF0000)
#define hsFixedToFloorInt(x) \
(int)((x) < 0 ? -(int)((-(x) + 0xFFFF) >> 16) : ((x) >> 16))
#define hsFixCeiling(x) \
(hsFixed)((x) < 0 ? -(hsFixed)(-(x) & 0xFFFF0000) : ((x) + 0xFFFF) & 0xFFFF0000)
#define hsFixedToCeilingInt(x) \
(int)((x) < 0 ? -(int)(-(x) >> 16) : (((x) + 0xFFFF) >> 16))
#if HS_CAN_USE_FLOAT
#define hsFixedToFloat(x) ((x) / float(hsFixed1))
#define hsFloatToFixed(x) hsFixed((x) * hsFixed1)
#define hsFractToFloat(x) ((x) / float(hsFract1))
#define hsFloatToFract(x) hsFract((x) * hsFract1)
#endif
#if HS_BUILD_FOR_MAC68K && !(HS_PIN_MATH_OVERFLOW)
#define hsFixMul(a, b) FixMul(a, b)
#else
hsFixed hsFixMul(hsFixed a, hsFixed b);
#endif
#if HS_BUILD_FOR_MAC && !(HS_PIN_MATH_OVERFLOW) && !(HS_MP_SAFE)
#define hsFixDiv(a, b) FixDiv(a, b)
#define hsFracMul(a, b) FracMul(a, b)
#define hsFracDiv(a, b) FracDiv(a, b)
#else
hsFract hsFixDiv(hsFixed a, hsFixed b);
hsFract hsFracMul(hsFract a, hsFract b);
hsFract hsFracDiv(hsFract a, hsFract b);
#endif
hsFract hsFracSqrt(hsFract value);
#define hsFixSqrt(value) (hsFracSqrt(value) >> 7)
hsFract hsFracCubeRoot(hsFract value);
hsFixed hsFixedSin(hsFixed s);
hsFixed hsFixedCos(hsFixed s);
hsFixed hsFixedASin(hsFixed s);
hsFixed hsFixedACos(hsFixed s);
UInt16 hsSqrt32(UInt32 value);
UInt16 hsCubeRoot32(UInt32 value);
Int32 hsMulDiv32(Int32 numer1, Int32 numer2, Int32 denom);
Int32 hsMagnitude32(Int32 x, Int32 y);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
struct hsFixedPlane {
hsFixed fA, fB, fC;
void Set(hsFixed a, hsFixed b, hsFixed c) { fA = a; fB = b; fC = c; }
hsFixed FixEval(hsFixed x, hsFixed y) const { return hsFixMul(fA, x) + hsFixMul(fB, y) + fC; }
Int32 IntEval(Int32 x, Int32 y) const { return fA * x + fB * y + fC; }
void ShiftDown(UInt32 i) { fA >>= i; fB >>= i; fC >>= i;}
};
#endif
#endif

View File

@ -0,0 +1,133 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsGeometry3.h"
#include "hsStream.h"
hsVector3 operator%(const hsVector3& t, const hsVector3& s)
{
hsVector3 result;
return *result.Set( hsScalarMul(t.fY, s.fZ) - hsScalarMul(s.fY, t.fZ),
-hsScalarMul(t.fX, s.fZ) + hsScalarMul(s.fX, t.fZ),
hsScalarMul(t.fX, s.fY) - hsScalarMul(s.fX, t.fY));
}
//////////////////////////////////
/////////////////////////////////
#if HS_SCALAR_IS_FIXED
hsScalar hsScalarTriple::Magnitude() const
{
hsWide result, temp;
result.Mul(fCoord[0], fCoord[0]);
temp.Mul(fCoord[1], fCoord[1]);
result.Add(&temp);
temp.Mul(fCoord[2], fCoord[2]);
result.Add(&temp);
return result.Sqrt();
}
hsScalar hsScalarTriple::MagnitudeSquared() const
{
hsWide result, temp;
result.Mul(fCoord[0], fCoord[0]);
temp.Mul(fCoord[1], fCoord[1]);
result.Add(&temp);
temp.Mul(fCoord[2], fCoord[2]);
result.Add(&temp);
return result.AsFixed();
}
#endif
void hsScalarTriple::Read(hsStream *stream)
{
// DANGER for speed read directly into these variables...ASSUMES fX,fY, and fZ are in contiguous order (PBG)
stream->Read12Bytes(&fX);
#if HS_BUILD_FOR_MAC
fX = hsSwapEndianFloat(fX);
fY = hsSwapEndianFloat(fY);
fZ = hsSwapEndianFloat(fZ);
#endif
}
void hsScalarTriple::Write(hsStream *stream) const
{
stream->WriteSwapScalar(fX);
stream->WriteSwapScalar(fY);
stream->WriteSwapScalar(fZ);
}
hsPlane3::hsPlane3(const hsPoint3* pt1, const hsPoint3* pt2, const hsPoint3* pt3)
{
// convert into a point with two vectors
hsVector3 v1(pt2, pt1);
hsVector3 v2(pt3, pt1);
// calculate the normal (wedge)
fN.fX = (v1.fY * v2.fZ) - (v2.fY * v1.fZ);
fN.fY = (v1.fZ * v2.fX) - (v2.fZ * v1.fX);
fN.fZ = (v1.fX * v2.fY) - (v2.fX * v1.fY);
fN.Normalize();
fD = -pt1->InnerProduct(&fN);
}
void hsPlane3::Read(hsStream *stream)
{
fN.Read(stream);
fD=stream->ReadSwapScalar();
}
void hsPlane3::Write(hsStream *stream) const
{
fN.Write(stream);
stream->WriteSwapScalar(fD);
}

View File

@ -0,0 +1,512 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsGGeometry3Defined
#define hsGGeometry3Defined
#include "hsTypes.h"
struct hsVector3;
struct hsPoint3;
struct hsScalarTriple;
class hsStream;
#if HS_BUILD_FOR_PS2
#include <eekernel.h>
#include <stdlib.h>
#include <stdio.h>
#include <eeregs.h>
#include <libgraph.h>
#include <libdma.h>
#include <libpkt.h>
#include <sifdev.h>
#include <libdev.h>
/**** vu0 inline ****/
#if 1
#define inline_asm inline /* inline */
#else
#define inline_asm /* not inline */
#endif
/******* HeadSpin *******/
typedef float hsScalar;
/* -------------------------------------------------------------------------------- */
/* return(sqrt(x)) */
inline_asm hsScalar SqrtVU0(hsScalar x)
{
register hsScalar ret;
asm volatile(" \
mfc1 $8,%1 \
qmtc2 $8,vf4 \
vsqrt Q,vf4x \
vwaitq \
cfc2 $2,$vi22 \
mtc1 $2,%0 \
" :"=f" (ret) : "f" (x), "0" (ret) : "$2", "$8", "memory");
return ret;
}
/* -------------------------------------------------------------------------------- */
/* return(1 / a) */
inline_asm hsScalar ScalarInvertVU0(hsScalar a)
{
register hsScalar ret;
asm volatile(" \
mfc1 $8,%1 \
qmtc2 $8,vf2 \
vdiv Q,vf0w,vf2x \
vwaitq \
cfc2 $2,$vi22 \
mtc1 $2,%0 \
" :"=f" (ret) : "f" (a), "0" (ret) : "$2", "$8", "memory");
return ret;
}
/* -------------------------------------------------------------------------------- */
/* return(a * b) */
inline_asm hsScalar ScalarMulVU0(hsScalar a, hsScalar b)
{
register hsScalar ret;
asm volatile(" \
mfc1 $8,%1 \
qmtc2 $8,vf2 \
mfc1 $9,%2 \
qmtc2 $9,vf3 \
vmul.x vf3,vf2,vf3 \
qmfc2 $2 ,vf3 \
mtc1 $2,%0 \
" :"=f" (ret) : "f" (a), "f" (b), "0" (ret) : "$2", "$8", "$9", "memory");
return ret;
}
#endif // PS2
/*
If value is already close to hsScalar1, then this is a good approx. of 1/sqrt(value)
*/
static inline hsScalar hsInvSqrt(hsScalar value)
{
hsScalar guess;
hsScalar threeOverTwo = hsScalar1 + hsScalarHalf;
value = hsScalarDiv2(value);
guess = threeOverTwo - value; // with initial guess = 1.0
// repeat this line for better approx
guess = hsScalarMul(guess, threeOverTwo - hsScalarMul(hsScalarMul(value, guess), guess));
guess = hsScalarMul(guess, threeOverTwo - hsScalarMul(hsScalarMul(value, guess), guess));
return guess;
}
/////////////////////////////////////////////////////////////////////////////////////////////
struct hsScalarTriple
{
//protected:
// hsScalarTriple() : fX(privateData[0]), fY(privateData[1]), fZ(privateData[2]) {}
// hsScalarTriple(hsScalar x, hsScalar y, hsScalar z)
// : fX(privateData[0]), fY(privateData[1]), fZ(privateData[2]) { fX = x, fY = y, fZ = z; }
//
// union {
// u_long128 privateTemp;
// hsScalar privateData[4];
// };
//public:
//
// int operator=(const hsScalarTriple& o) { privateTemp = o.privateTemp; }
// hsScalarTriple(const hsScalarTriple& o) : fX(privateData[0]), fY(privateData[1]), fZ(privateData[2])
// { *this = o; }
//
// hsScalar& fX;
// hsScalar& fY;
// hsScalar& fZ;
protected:
hsScalarTriple() {}
hsScalarTriple(hsScalar x, hsScalar y, hsScalar z) : fX(x), fY(y), fZ(z) {}
public:
hsScalar fX, fY, fZ;
hsScalarTriple* Set(hsScalar x, hsScalar y, hsScalar z) { fX= x; fY = y; fZ = z; return this;}
hsScalarTriple* Set(const hsScalarTriple *p) { fX = p->fX; fY = p->fY; fZ = p->fZ; return this;}
hsScalar InnerProduct(const hsScalarTriple &p) const;
hsScalar InnerProduct(const hsScalarTriple *p) const;
// hsScalarTriple LERP(hsScalarTriple &other, hsScalar t);
#if HS_SCALAR_IS_FIXED
hsScalar Magnitude() const;
hsScalar MagnitudeSquared() const;
#else
#if HS_BUILD_FOR_PS2
hsScalar Magnitude() const;
#else
hsScalar Magnitude() const { return hsSquareRoot(MagnitudeSquared()); }
#endif
hsScalar MagnitudeSquared() const { return (fX * fX + fY * fY + fZ * fZ); }
#endif
hsBool IsEmpty() const { return fX == 0 && fY == 0 && fZ == 0; }
hsScalar operator[](int i) const;
hsScalar& operator[](int i);
void Read(hsStream *stream);
void Write(hsStream *stream) const;
} ATTRIBUTE_FOR_PS2; /* SUNSOFT */
#if HS_BUILD_FOR_PS2
inline hsScalar hsScalarTriple::Magnitude() const
{
MATRIX4 m;
m[0] = fX;
m[1] = fY;
m[2] = fZ;
return MagnitudeVU0(m);
}
#endif
///////////////////////////////////////////////////////////////////////////
inline hsScalar& hsScalarTriple::operator[] (int i)
{
hsAssert(i >=0 && i <3, "Bad index for hsScalarTriple::operator[]");
return *(&fX + i);
}
inline hsScalar hsScalarTriple::operator[] (int i) const
{
hsAssert(i >=0 && i <3, "Bad index for hsScalarTriple::operator[]");
return *(&fX + i);
}
inline hsScalar hsScalarTriple::InnerProduct(const hsScalarTriple &p) const
{
hsScalar tmp = fX*p.fX;
tmp += fY*p.fY;
tmp += fZ*p.fZ;
return tmp;
}
inline hsScalar hsScalarTriple::InnerProduct(const hsScalarTriple *p) const
{
hsScalar tmp = fX*p->fX;
tmp += fY*p->fY;
tmp += fZ*p->fZ;
return tmp;
}
//inline hsScalarTriple hsScalarTriple::LERP(hsScalarTriple &other, hsScalar t)
//{
// hsScalarTriple p = other - this;
// p = p / t;
// return this + p;
//}
/////////////////////////////////////////////////////////////////////////////////////////////
struct hsPoint3 : public hsScalarTriple {
hsPoint3() {};
hsPoint3(hsScalar x, hsScalar y, hsScalar z) : hsScalarTriple(x,y,z) {}
explicit hsPoint3(const hsScalarTriple& p) : hsScalarTriple(p) {}
hsPoint3* Set(hsScalar x, hsScalar y, hsScalar z) { return (hsPoint3*)this->hsScalarTriple::Set(x,y,z);}
hsPoint3* Set(const hsScalarTriple* p) { return (hsPoint3*)this->hsScalarTriple::Set(p) ;}
friend inline hsPoint3 operator+(const hsPoint3& s, const hsPoint3& t);
friend inline hsPoint3 operator+(const hsPoint3& s, const hsVector3& t);
friend inline hsPoint3 operator-(const hsPoint3& s, const hsPoint3& t);
friend inline hsPoint3 operator-(const hsPoint3& s);
friend inline hsPoint3 operator*(const hsScalar& s, const hsPoint3& t);
friend inline hsPoint3 operator*(const hsPoint3& t, const hsScalar& s);
friend inline hsPoint3 operator/(const hsPoint3& t, const hsScalar& s);
hsBool operator==(const hsPoint3& ss) const
{
return (ss.fX == fX && ss.fY == fY && ss.fZ == fZ);
}
hsBool operator!=(const hsPoint3& ss) const { return !(*this == ss); }
hsPoint3 &operator+=(const hsScalarTriple &s) { fX += s.fX; fY += s.fY; fZ += s.fZ; return *this; }
hsPoint3 &operator*=(const hsScalar s) { fX *= s; fY *= s; fZ *= s; return *this; }
} ATTRIBUTE_FOR_PS2; /* SUNSOFT */
/////////////////////////////////////////////////////////////////////////////////////////////
struct hsVector3 : public hsScalarTriple {
hsVector3() {};
hsVector3(hsScalar x, hsScalar y, hsScalar z) : hsScalarTriple(x,y,z) {}
explicit hsVector3(const hsScalarTriple& p) : hsScalarTriple(p) { }
hsVector3(const hsPoint3 *p1, const hsPoint3 *p2) {
fX = p1->fX - p2->fX, fY= p1->fY - p2->fY, fZ = p1->fZ - p2->fZ; }
hsVector3* Set(hsScalar x, hsScalar y, hsScalar z) { return (hsVector3*)hsScalarTriple::Set(x,y,z); }
hsVector3* Set(const hsScalarTriple* p) { return (hsVector3*)hsScalarTriple::Set(p) ;}
hsVector3* Set(const hsScalarTriple* p1, const hsScalarTriple* p2) { return Set(p1->fX-p2->fX,p1->fY-p2->fY,p1->fZ-p2->fZ);}
void Normalize()
{
#if HS_BUILD_FOR_PS2
hsScalar length = this->Magnitude();
hsIfDebugMessage(length == 0, "Err: Normalizing hsVector3 of length 0", 0);
if (length == 0)
return;
NormalizeVU0(length, (MATRIX4)this);
#else
hsScalar length = this->Magnitude();
// hsIfDebugMessage(length == 0, "Err: Normalizing hsVector3 of length 0", 0);
if (length == 0)
return;
hsScalar invMag = hsScalarInvert(length);
fX = hsScalarMul(fX, invMag);
fY = hsScalarMul(fY, invMag);
fZ = hsScalarMul(fZ, invMag);
#endif
}
inline void Renormalize() // if the vector is already close to unit length
{
hsScalar mag2 = *this * *this;
hsIfDebugMessage(mag2 == 0, "Err: Renormalizing hsVector3 of length 0", 0);
if (mag2 == 0)
return;
hsScalar invMag = hsInvSqrt(mag2);
fX = hsScalarMul(fX, invMag);
fY = hsScalarMul(fY, invMag);
fZ = hsScalarMul(fZ, invMag);
}
// hsVector3 &Sub(const hsPoint3& s, const hsPoint3& t)
// { Set(s.fX - t.fX, s.fY - t.fY, s.fZ - t.fZ);
// return *this; };
friend inline hsVector3 operator+(const hsVector3& s, const hsVector3& t);
friend inline hsVector3 operator-(const hsVector3& s, const hsVector3& t);
friend inline hsVector3 operator-(const hsVector3& s);
friend inline hsVector3 operator*(const hsScalar& s, const hsVector3& t);
friend inline hsVector3 operator*(const hsVector3& t, const hsScalar& s);
friend inline hsVector3 operator/(const hsVector3& t, const hsScalar& s);
friend inline hsScalar operator*(const hsVector3& t, const hsVector3& s);
friend hsVector3 operator%(const hsVector3& t, const hsVector3& s);
#if 0 // Havok reeks
friend hsBool32 operator==(const hsVector3& s, const hsVector3& t)
{
return (s.fX == t.fX && s.fY == t.fY && s.fZ == t.fZ);
}
#else // Havok reeks
hsBool operator==(const hsVector3& ss) const
{
return (ss.fX == fX && ss.fY == fY && ss.fZ == fZ);
}
#endif // Havok reeks
hsVector3 &operator+=(const hsScalarTriple &s) { fX += s.fX; fY += s.fY; fZ += s.fZ; return *this; }
hsVector3 &operator-=(const hsScalarTriple &s) { fX -= s.fX; fY -= s.fY; fZ -= s.fZ; return *this; }
hsVector3 &operator*=(const hsScalar s) { fX *= s; fY *= s; fZ *= s; return *this; }
hsVector3 &operator/=(const hsScalar s) { fX /= s; fY /= s; fZ /= s; return *this; }
} ATTRIBUTE_FOR_PS2; /* SUNSOFT */
struct hsPoint4 {
hsScalar fX, fY, fZ, fW;
hsPoint4() {}
hsPoint4(hsScalar x, hsScalar y, hsScalar z, hsScalar w) : fX(x), fY(y), fZ(z), fW(w) {}
hsScalar& operator[](int i);
hsScalar operator[](int i) const;
hsPoint4& operator=(const hsPoint3&p) { Set(p.fX, p.fY, p.fZ, hsScalar1); return *this; }
hsPoint4* Set(hsScalar x, hsScalar y, hsScalar z, hsScalar w)
{ fX = x; fY = y; fZ = z; fW = w; return this; }
} ATTRIBUTE_FOR_PS2; /* SUNSOFT */
inline hsVector3 operator+(const hsVector3& s, const hsVector3& t)
{
hsVector3 result;
return *result.Set(s.fX + t.fX, s.fY + t.fY, s.fZ + t.fZ);
}
inline hsVector3 operator-(const hsVector3& s, const hsVector3& t)
{
hsVector3 result;
return *result.Set(s.fX - t.fX, s.fY - t.fY, s.fZ - t.fZ);
}
// unary minus
inline hsVector3 operator-(const hsVector3& s)
{
hsVector3 result;
return *result.Set(-s.fX, -s.fY, -s.fZ);
}
inline hsVector3 operator*(const hsVector3& s, const hsScalar& t)
{
hsVector3 result;
return *result.Set(hsScalarMul(s.fX, t), hsScalarMul(s.fY, t), hsScalarMul(s.fZ, t));
}
inline hsVector3 operator/(const hsVector3& s, const hsScalar& t)
{
hsVector3 result;
return *result.Set(hsScalarDiv(s.fX, t), hsScalarDiv(s.fY, t), hsScalarDiv(s.fZ, t));
}
inline hsVector3 operator*(const hsScalar& t, const hsVector3& s)
{
hsVector3 result;
return *result.Set(hsScalarMul(s.fX, t), hsScalarMul(s.fY, t), hsScalarMul(s.fZ, t));
}
inline hsScalar operator*(const hsVector3& t, const hsVector3& s)
{
return hsScalarMul(t.fX, s.fX) + hsScalarMul(t.fY, s.fY) + hsScalarMul(t.fZ, s.fZ);
}
////////////////////////////////////////////////////////////////////////////
inline hsPoint3 operator+(const hsPoint3& s, const hsPoint3& t)
{
hsPoint3 result;
return *result.Set(s.fX + t.fX, s.fY + t.fY, s.fZ + t.fZ);
}
inline hsPoint3 operator+(const hsPoint3& s, const hsVector3& t)
{
hsPoint3 result;
return *result.Set(s.fX + t.fX, s.fY + t.fY, s.fZ + t.fZ);
}
inline hsPoint3 operator-(const hsPoint3& s, const hsPoint3& t)
{
hsPoint3 result;
return *result.Set(s.fX - t.fX, s.fY - t.fY, s.fZ - t.fZ);
}
// unary -
inline hsPoint3 operator-(const hsPoint3& s)
{
hsPoint3 result;
return *result.Set(-s.fX, -s.fY, -s.fZ);
}
inline hsPoint3 operator-(const hsPoint3& s, const hsVector3& t)
{
hsPoint3 result;
return *result.Set(s.fX - t.fX, s.fY - t.fY, s.fZ - t.fZ);
}
inline hsPoint3 operator*(const hsPoint3& s, const hsScalar& t)
{
hsPoint3 result;
return *result.Set(hsScalarMul(s.fX, t), hsScalarMul(s.fY, t), hsScalarMul(s.fZ, t));
}
inline hsPoint3 operator/(const hsPoint3& s, const hsScalar& t)
{
hsPoint3 result;
return *result.Set(hsScalarDiv(s.fX, t), hsScalarDiv(s.fY, t), hsScalarDiv(s.fZ, t));
}
inline hsPoint3 operator*(const hsScalar& t, const hsPoint3& s)
{
hsPoint3 result;
return *result.Set(hsScalarMul(s.fX, t), hsScalarMul(s.fY, t), hsScalarMul(s.fZ, t));
}
inline hsScalar hsPoint4::operator[] (int i) const
{
hsAssert(i >=0 && i <4, "Bad index for hsPoint4::operator[]");
return *(&fX + i);
}
inline hsScalar& hsPoint4::operator[] (int i)
{
hsAssert(i >=0 && i <4, "Bad index for hsPoint4::operator[]");
return *(&fX + i);
}
typedef hsPoint3 hsGUv;
struct hsPointNorm {
hsPoint3 fPos;
hsVector3 fNorm;
void Read(hsStream* s) { fPos.Read(s); fNorm.Read(s); }
void Write(hsStream* s) const { fPos.Write(s); fNorm.Write(s); }
} ATTRIBUTE_FOR_PS2; /* SUNSOFT */
struct hsPlane3 {
hsVector3 fN;
hsScalar fD;
hsPlane3() { }
hsPlane3(const hsVector3* nrml, hsScalar d)
{ fN = *nrml; fD=d; }
hsPlane3(const hsPoint3* pt, const hsVector3* nrml)
{ fN = *nrml; fD = -pt->InnerProduct(nrml); }
// create plane from a triangle (assumes clockwise winding of vertices)
hsPlane3(const hsPoint3* pt1, const hsPoint3* pt2, const hsPoint3* pt3);
hsVector3 GetNormal() const { return fN; }
void Read(hsStream *stream);
void Write(hsStream *stream) const;
} ATTRIBUTE_FOR_PS2;
#endif

View File

@ -0,0 +1,199 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// hsHashTable.h
#ifndef _hsHashTable_Included_
#define _hsHashTable_Included_
#include "hsTemplates.h"
template <class T>
class hsHashTableIterator
{
public:
hsHashTableIterator() : fList(nil), fIndex(-1) { }
explicit hsHashTableIterator(hsTArray<T>* list, UInt32 idx) : fList(list), fIndex(idx) { }
T* operator->() const { return &((*fList)[fIndex]); }
T& operator*() const { return (*fList)[fIndex]; }
hsHashTableIterator<T>& operator++() { fIndex--; return *this; }
const hsHashTableIterator<T>& operator++(int) { hsHashTableIterator<T> temp(*this); --(*this); return temp; }
hsHashTableIterator<T>& operator--() { fIndex++; return *this; }
const hsHashTableIterator<T>& operator--(int) { hsHashTableIterator<T> temp(*this); ++(*this); return temp; }
hsBool operator==(const hsHashTableIterator<T>& other) const { return fList==other.fList && fIndex==other.fIndex; }
hsBool operator!=(const hsHashTableIterator<T>& other) const { return !(*this == other); }
private:
hsTArray<T>* fList;
UInt32 fIndex;
};
template <class T>
class hsHashTable
{
public:
hsHashTable(UInt32 size=150001, UInt32 step=1);
~hsHashTable();
typedef hsHashTableIterator<T> iterator;
iterator begin() { return iterator(&fItemList,fItemList.Count()-1); }
iterator end() { return iterator(&fItemList,0); }
void clear();
UInt32 count() { return fItemList.Count()-1; }
UInt32 size() { return fSize; }
UInt32 CollisionCount() { return fCollisionCount; }
inline void insert(T& item);
inline void erase(T& item);
inline iterator find(const T& item);
iterator GetItem(UInt32 i);
private:
hsTArray<T> fItemList;
hsTArray<UInt32> fClearList;
UInt32* fHashTable;
UInt32 fSize;
UInt32 fCollisionStep;
UInt32 fCollisionCount;
// No copy or assignment
hsHashTable(const hsHashTable&);
hsHashTable &operator=(const hsHashTable&);
};
template <class T>
hsHashTable<T>::hsHashTable(UInt32 size, UInt32 step) :
fSize(size),
fCollisionStep(step),
fCollisionCount(0)
{
fItemList.SetCount(1);
fHashTable = TRACKED_NEW UInt32[fSize];
memset(fHashTable,0,fSize*sizeof(UInt32));
}
template <class T>
hsHashTable<T>::~hsHashTable()
{
delete [] fHashTable;
}
template <class T>
void hsHashTable<T>::clear()
{
fItemList.SetCount(1);
for (Int32 i=0; i<fClearList.Count(); i++)
fHashTable[ fClearList[i] ] = 0;
fClearList.Reset();
}
template <class T>
void hsHashTable<T>::insert(T& item)
{
hsAssert(fClearList.Count() < fSize,"Hash table overflow! Increase the table size.");
UInt32 h = item.GetHash();
h %= fSize;
while (UInt32 it = fHashTable[h])
{
if ( fItemList[it] == item)
{
fItemList[it] = item;
return;
}
h += fCollisionStep;
h %= fSize;
fCollisionCount++;
}
fHashTable[h] = fItemList.Count();
fItemList.Append(item);
fClearList.Append(h);
}
template <class T>
void hsHashTable<T>::erase(T& item)
{
UInt32 h = item.GetHash();
h %= fSize;
while (UInt32 it = fHashTable[h])
{
if ( fItemList[it] == item )
{
fHashTable[h] = 0;
return;
}
}
}
template <class T>
hsHashTableIterator<T> hsHashTable<T>::find(const T& item)
{
UInt32 h = item.GetHash();
h %= fSize;
while (UInt32 it = fHashTable[h])
{
if ( fItemList[it] == item )
{
return iterator(&fItemList,it);
}
h += fCollisionStep;
h %= fSize;
fCollisionCount++;
}
return end();
}
template <class T>
hsHashTableIterator<T> hsHashTable<T>::GetItem(UInt32 i)
{
return iterator(&fItemList,i+1);
}
#endif // _hsHashTable_Included_

View File

@ -0,0 +1,56 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsLOD_inc
#define hsLOD_inc
namespace hsLOD
{
enum
{
kLODNone = 0x00000000,
kLODLow = 0x00000001,
kLODHigh = 0x00000002,
kLODAll = kLODLow | kLODHigh
};
}
#endif // hsLOD_inc

View File

@ -0,0 +1,105 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsMMIOStream.h"
//////////////////////////////////////////////////////////////////////////////////////
#if HS_BUILD_FOR_WIN32
#include "hsExceptions.h"
UInt32 hsMMIOStream::Read(UInt32 bytes, void* buffer)
{
fBytesRead += bytes;
fPosition += bytes;
int numItems = ::mmioRead(fHmfr, (char*)buffer, bytes);
if ((unsigned)numItems < bytes)
{
if (numItems>=0 && ::mmioSeek(fHmfr,0,SEEK_CUR)==::mmioSeek(fHmfr,0,SEEK_END)) {
// EOF ocurred
char str[128];
sprintf(str, "Hit EOF on MMIO Read, only read %d out of requested %d bytes\n", numItems, bytes);
hsDebugMessage(str, 0);
}
else
{
hsDebugMessage("Error on MMIO Read",0);
}
}
return numItems;
}
hsBool hsMMIOStream::AtEnd()
{
return (::mmioSeek(fHmfr,0,SEEK_CUR)==::mmioSeek(fHmfr,0,SEEK_END));
}
UInt32 hsMMIOStream::Write(UInt32 bytes, const void* buffer)
{
fPosition += bytes;
return ::mmioWrite(fHmfr,(const char*)buffer,bytes);
}
void hsMMIOStream::Skip(UInt32 delta)
{
fBytesRead += delta;
fPosition += delta;
(void)::mmioSeek(fHmfr, delta, SEEK_CUR);
}
void hsMMIOStream::Rewind()
{
fBytesRead = 0;
fPosition = 0;
(void)::mmioSeek(fHmfr, 0, SEEK_SET);
}
void hsMMIOStream::FastFwd()
{
fBytesRead = fPosition = ::mmioSeek(fHmfr, 0, SEEK_END);
}
void hsMMIOStream::Truncate()
{
hsThrow("Truncate unimplemented by subclass of stream");
}
#endif

View File

@ -0,0 +1,72 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsMMIOStream_inc
#define hsMMIOStream_inc
#include "hsWindows.h"
#include "hsStream.h"
#if HS_BUILD_FOR_WIN32
#include <mmsystem.h>
#endif
class hsMMIOStream: public hsStream
{
HMMIO fHmfr;
public:
virtual hsBool Open(const char *, const char *) { hsAssert(0, "hsMMIOStream::Open NotImplemented"); return false; }
virtual hsBool Close() { hsAssert(0, "hsMMIOStream::Close NotImplemented"); return false; }
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void* buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void FastFwd();
virtual void Truncate();
HMMIO GetHandle() { return fHmfr; }
void SetHandle(HMMIO handle) { fHmfr = handle; }
};
#endif // hsMMIOStream_inc

View File

@ -0,0 +1,56 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/CoreLib/hsMalloc.cpp
*
***/
#include "HeadSpin.h"
/*****************************************************************************
*
* Exports
*
***/

View File

@ -0,0 +1,183 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/CoreLib/hsMalloc.h
*
***/
#ifndef PLASMA20_SOURCES_PLASMA_CORELIB_HSMALLOC_H
#define PLASMA20_SOURCES_PLASMA_CORELIB_HSMALLOC_H
/****************************************************************************
*
* Allocation functions
*
***/
#ifdef __cplusplus
extern "C" {
#endif
// MemAlloc flags
extern const unsigned kMemReallocInPlaceOnly; // use _expand when realloc'ing
extern const unsigned kMemZero; // fill allocated memory with zeros
extern const unsigned kMemIgnoreBlock; // don't track this allocation
void * MemAlloc (unsigned bytes, unsigned flags, const char file[], int line);
void * MemDup (const void * ptr, unsigned bytes, unsigned flags, const char file[], int line);
void MemFree (void * ptr, unsigned flags);
void * MemRealloc (void * ptr, unsigned bytes, unsigned flags, const char file[], int line);
unsigned MemSize (void * ptr);
/****************************************************************************
*
* Manipulation functions
*
***/
int MemCmp (const void * buf1, const void * buf2, unsigned bytes);
void MemCopy (void * dest, const void * source, unsigned bytes);
void MemMove (void * dest, const void * source, unsigned bytes);
void MemSet (void * dest, unsigned value, unsigned bytes);
void MemZero (void * dest, unsigned bytes);
/*****************************************************************************
*
* Debugging functions
*
***/
void MemDumpAllocReport ();
void MemDumpUsageReport ();
void MemValidateNow ();
void MemSetValidation (unsigned on);
void MemPushDisableTracking ();
void MemPopDisableTracking ();
void MemSetColor (unsigned short color);
#ifdef __cplusplus
}
#endif
/****************************************************************************
*
* C++ Operators
*
***/
#ifdef __cplusplus
// standard new and delete
inline void * __cdecl operator new (size_t bytes) { return MemAlloc((unsigned)bytes, 0, __FILE__, __LINE__); }
inline void __cdecl operator delete (void * ptr) { MemFree(ptr, 0); }
// memcheck-friendly new
inline void * __cdecl operator new (size_t bytes, const char file[], unsigned line) { return MemAlloc((unsigned)bytes, 0, file, line); }
inline void __cdecl operator delete (void * ptr, const char [] , unsigned) { return MemFree(ptr, 0); }
#define TRACKED_NEW new(__FILE__, __LINE__)
// placement new
#ifndef __PLACEMENT_NEW_INLINE
#define __PLACEMENT_NEW_INLINE
inline void * __cdecl operator new (size_t, void * ptr) { return ptr; }
inline void __cdecl operator delete (void *, void *) {}
#endif // ifndef __PLACEMENT_NEW_INLINE
#endif // ifdef __cplusplus
/****************************************************************************
*
* Macros
*
***/
#define ALLOC(b) MemAlloc(b, 0, __FILE__, __LINE__)
#define ALLOCZERO(b) MemAlloc(b, kMemZero, __FILE__, __LINE__)
#define ALLOCFLAGS(b, f) MemAlloc(b, (f), __FILE__, __LINE__)
#define FREE(p) MemFree(p, 0)
#define FREEFLAGS(p, f) MemFree(p, (f))
#define REALLOC(p, b) MemRealloc(p, b, 0, __FILE__, __LINE__)
#define REALLOCFLAGS(p, b, f) MemRealloc(p, b, (f), __FILE__, __LINE__)
#define CALLOC(n, s) MemAlloc((n)*(s), kMemZero, __FILE__, __LINE__)
#define MEMDUP(s, b) MemDup(s, b, 0, __FILE__, __LINE__)
#define ZERO(s) MemSet(&s, 0, sizeof(s))
#define ZEROPTR(p) MemSet(p, 0, sizeof(*p))
// Client must #include <malloc.h>
#define ALLOCA(t, n) (t *)_alloca((n) * sizeof(t))
#ifdef __cplusplus
#define NEW(t) new(MemAlloc(sizeof(t), 0, __FILE__, __LINE__)) t
#define NEWFLAGS(t, f) new(MemAlloc(sizeof(t), (f), __FILE__, __LINE__)) t
#define NEWZERO(t) new(MemAlloc(sizeof(t), kMemZero, __FILE__, __LINE__)) t
#define DEL(t) delete (t)
#endif // __cplusplus
/****************************************************************************
*
* TypeInfo
* (needed for memory leak reporting)
*
***/
#ifdef __cplusplus
#if !defined(HS_NO_TYPEINFO)
#include <typeinfo.h>
#endif
#endif // ifdef __cplusplus
#endif // PLASMA20_SOURCES_PLASMA_CORELIB_HSMALLOC_H

View File

@ -0,0 +1,113 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsMatrix33.h"
#include "hsStream.h"
hsMatrix33* hsMatrix33::Reset()
{
static const hsMatrix33 gIdentity = { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
*this = gIdentity;
return this;
}
hsMatrix33* hsMatrix33::SetConcat(const hsMatrix33* a, const hsMatrix33* b)
{
hsMatrix33 tmpMatrix;
hsMatrix33* c;
c = this;
if (this == a || this == b)
c = &tmpMatrix;
c->fMap[0][0] = a->fMap[0][0] * b->fMap[0][0] + a->fMap[0][1] * b->fMap[1][0] + a->fMap[0][2] * b->fMap[2][0];
c->fMap[0][1] = a->fMap[0][0] * b->fMap[0][1] + a->fMap[0][1] * b->fMap[1][1] + a->fMap[0][2] * b->fMap[2][1];
c->fMap[0][2] = a->fMap[0][0] * b->fMap[0][2] + a->fMap[0][1] * b->fMap[1][2] + a->fMap[0][2] * b->fMap[2][2];
c->fMap[1][0] = a->fMap[1][0] * b->fMap[0][0] + a->fMap[1][1] * b->fMap[1][0] + a->fMap[1][2] * b->fMap[2][0];
c->fMap[1][1] = a->fMap[1][0] * b->fMap[0][1] + a->fMap[1][1] * b->fMap[1][1] + a->fMap[1][2] * b->fMap[2][1];
c->fMap[1][2] = a->fMap[1][0] * b->fMap[0][2] + a->fMap[1][1] * b->fMap[1][2] + a->fMap[1][2] * b->fMap[2][2];
c->fMap[2][0] = a->fMap[2][0] * b->fMap[0][0] + a->fMap[2][1] * b->fMap[1][0] + a->fMap[2][2] * b->fMap[2][0];
c->fMap[2][1] = a->fMap[2][0] * b->fMap[0][1] + a->fMap[2][1] * b->fMap[1][1] + a->fMap[2][2] * b->fMap[2][1];
c->fMap[2][2] = a->fMap[2][0] * b->fMap[0][2] + a->fMap[2][1] * b->fMap[1][2] + a->fMap[2][2] * b->fMap[2][2];
if (this != c)
*this = *c;
return this;
}
hsMatrix33 operator*(const hsMatrix33& a, const hsMatrix33& b)
{
hsMatrix33 c;
(void)c.SetConcat(&a, &b);
return c;
}
void hsMatrix33::Read(hsStream* s)
{
int i, j;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
fMap[i][j] = s->ReadSwapScalar();
}
}
}
void hsMatrix33::Write(hsStream* s)
{
int i, j;
for( i = 0; i < 3; i++ )
{
for( j = 0; j < 3; j++ )
{
s->WriteSwapScalar(fMap[i][j]);
}
}
}

View File

@ -0,0 +1,72 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsMatrix33_inc
#define hsMatrix33_inc
class hsStream;
struct hsMatrix33
{
hsScalar fMap[3][3];
hsMatrix33* Reset();
int operator==(const hsMatrix33& aa) const
{
return aa.fMap[0][0] == fMap[0][0] && aa.fMap[0][1] == fMap[0][1] && aa.fMap[0][2] == fMap[0][2] &&
aa.fMap[1][0] == fMap[1][0] && aa.fMap[1][1] == fMap[1][1] && aa.fMap[1][2] == fMap[1][2] &&
aa.fMap[2][0] == fMap[2][0] && aa.fMap[2][1] == fMap[2][1] && aa.fMap[2][2] == fMap[2][2];
}
int operator!=(const hsMatrix33& aa) const
{
return !(aa == *this);
}
hsMatrix33* SetConcat(const hsMatrix33* a, const hsMatrix33* b);
friend hsMatrix33 operator*(const hsMatrix33& a, const hsMatrix33& b);
void Read(hsStream* s);
void Write(hsStream* s);
};
#endif // hsMatrix33_inc

View File

@ -0,0 +1,970 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "hsGeometry3.h"
#include "hsQuat.h"
#include "hsMatrix44.h"
#include "hsStream.h"
static hsMatrix44 myIdent = hsMatrix44().Reset();
const hsMatrix44& hsMatrix44::IdentityMatrix() { return myIdent; }
/*
For the rotation:
<20> 2 2 <20>
<20> 1 - (2Y + 2Z ) 2XY + 2ZW 2XZ - 2YW <20>
<20> <20>
<20> 2 2 <20>
M = <20> 2XY - 2ZW 1 - (2X + 2Z ) 2YZ + 2XW <20>
<20> <20>
<20> 2 2 <20>
<20> 2XZ + 2YW 2YZ - 2XW 1 - (2X + 2Y ) <20>
<20> <20>
The translation is far too complex to discuss here. ;^)
*/
hsMatrix44::hsMatrix44(const hsScalarTriple &translate, const hsQuat &rotate)
{
float xx = rotate.fX * rotate.fX;
float xy = rotate.fX * rotate.fY;
float xz = rotate.fX * rotate.fZ;
float xw = rotate.fX * rotate.fW;
float yy = rotate.fY * rotate.fY;
float yz = rotate.fY * rotate.fZ;
float yw = rotate.fY * rotate.fW;
float zz = rotate.fZ * rotate.fZ;
float zw = rotate.fZ * rotate.fW;
fMap[0][0] = 1 - 2 * ( yy + zz ); fMap[0][1] = 2 * ( xy - zw ); fMap[0][2] = 2 * ( xz + yw ); fMap[0][3] = translate.fX;
fMap[1][0] = 2 * ( xy + zw ); fMap[1][1] = 1 - 2 * ( xx + zz ); fMap[1][2] = 2 * ( yz - xw ); fMap[1][3] = translate.fY;
fMap[2][0] = 2 * ( xz - yw ); fMap[2][1] = 2 * ( yz + xw ); fMap[2][2] = 1 - 2 * ( xx + yy ); fMap[2][3] = translate.fZ;
fMap[3][0] = fMap[3][1] = fMap[3][2] = 0.0f;
fMap[3][3] = 1.0f;
NotIdentity();
}
void hsMatrix44::DecompRigid(hsScalarTriple &translate, hsQuat &rotate) const
{
translate = GetTranslate();
rotate.QuatFromMatrix44(*this);
}
#if 0
hsMatrix44& hsMatrix44::Reset()
{
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
fMap[i][j] = (i==j) ? hsScalar1 : 0;
}
}
return *this;
}
#endif
#if 0 // Havok reeks
hsMatrix44 operator*(const hsMatrix44& a, const hsMatrix44& b)
{
hsMatrix44 c;
if( a.fFlags & b.fFlags & hsMatrix44::kIsIdent )
{
c.Reset();
return c;
}
if( a.fFlags & hsMatrix44::kIsIdent )
return b;
if( b.fFlags & hsMatrix44::kIsIdent )
return a;
#if HS_BUILD_FOR_PS2
MulMatrixVU0(a.fMap, b.fMap, c.fMap);
#else
c.fMap[0][0] = hsScalarMul(a.fMap[0][0], b.fMap[0][0]) + hsScalarMul(a.fMap[0][1], b.fMap[1][0]) + hsScalarMul(a.fMap[0][2], b.fMap[2][0]) + hsScalarMul(a.fMap[0][3], b.fMap[3][0]);
c.fMap[0][1] = hsScalarMul(a.fMap[0][0], b.fMap[0][1]) + hsScalarMul(a.fMap[0][1], b.fMap[1][1]) + hsScalarMul(a.fMap[0][2], b.fMap[2][1]) + hsScalarMul(a.fMap[0][3], b.fMap[3][1]);
c.fMap[0][2] = hsScalarMul(a.fMap[0][0], b.fMap[0][2]) + hsScalarMul(a.fMap[0][1], b.fMap[1][2]) + hsScalarMul(a.fMap[0][2], b.fMap[2][2]) + hsScalarMul(a.fMap[0][3], b.fMap[3][2]);
c.fMap[0][3] = hsScalarMul(a.fMap[0][0], b.fMap[0][3]) + hsScalarMul(a.fMap[0][1], b.fMap[1][3]) + hsScalarMul(a.fMap[0][2], b.fMap[2][3]) + hsScalarMul(a.fMap[0][3], b.fMap[3][3]);
c.fMap[1][0] = hsScalarMul(a.fMap[1][0], b.fMap[0][0]) + hsScalarMul(a.fMap[1][1], b.fMap[1][0]) + hsScalarMul(a.fMap[1][2], b.fMap[2][0]) + hsScalarMul(a.fMap[1][3], b.fMap[3][0]);
c.fMap[1][1] = hsScalarMul(a.fMap[1][0], b.fMap[0][1]) + hsScalarMul(a.fMap[1][1], b.fMap[1][1]) + hsScalarMul(a.fMap[1][2], b.fMap[2][1]) + hsScalarMul(a.fMap[1][3], b.fMap[3][1]);
c.fMap[1][2] = hsScalarMul(a.fMap[1][0], b.fMap[0][2]) + hsScalarMul(a.fMap[1][1], b.fMap[1][2]) + hsScalarMul(a.fMap[1][2], b.fMap[2][2]) + hsScalarMul(a.fMap[1][3], b.fMap[3][2]);
c.fMap[1][3] = hsScalarMul(a.fMap[1][0], b.fMap[0][3]) + hsScalarMul(a.fMap[1][1], b.fMap[1][3]) + hsScalarMul(a.fMap[1][2], b.fMap[2][3]) + hsScalarMul(a.fMap[1][3], b.fMap[3][3]);
c.fMap[2][0] = hsScalarMul(a.fMap[2][0], b.fMap[0][0]) + hsScalarMul(a.fMap[2][1], b.fMap[1][0]) + hsScalarMul(a.fMap[2][2], b.fMap[2][0]) + hsScalarMul(a.fMap[2][3], b.fMap[3][0]);
c.fMap[2][1] = hsScalarMul(a.fMap[2][0], b.fMap[0][1]) + hsScalarMul(a.fMap[2][1], b.fMap[1][1]) + hsScalarMul(a.fMap[2][2], b.fMap[2][1]) + hsScalarMul(a.fMap[2][3], b.fMap[3][1]);
c.fMap[2][2] = hsScalarMul(a.fMap[2][0], b.fMap[0][2]) + hsScalarMul(a.fMap[2][1], b.fMap[1][2]) + hsScalarMul(a.fMap[2][2], b.fMap[2][2]) + hsScalarMul(a.fMap[2][3], b.fMap[3][2]);
c.fMap[2][3] = hsScalarMul(a.fMap[2][0], b.fMap[0][3]) + hsScalarMul(a.fMap[2][1], b.fMap[1][3]) + hsScalarMul(a.fMap[2][2], b.fMap[2][3]) + hsScalarMul(a.fMap[2][3], b.fMap[3][3]);
c.fMap[3][0] = hsScalarMul(a.fMap[3][0], b.fMap[0][0]) + hsScalarMul(a.fMap[3][1], b.fMap[1][0]) + hsScalarMul(a.fMap[3][2], b.fMap[2][0]) + hsScalarMul(a.fMap[3][3], b.fMap[3][0]);
c.fMap[3][1] = hsScalarMul(a.fMap[3][0], b.fMap[0][1]) + hsScalarMul(a.fMap[3][1], b.fMap[1][1]) + hsScalarMul(a.fMap[3][2], b.fMap[2][1]) + hsScalarMul(a.fMap[3][3], b.fMap[3][1]);
c.fMap[3][2] = hsScalarMul(a.fMap[3][0], b.fMap[0][2]) + hsScalarMul(a.fMap[3][1], b.fMap[1][2]) + hsScalarMul(a.fMap[3][2], b.fMap[2][2]) + hsScalarMul(a.fMap[3][3], b.fMap[3][2]);
c.fMap[3][3] = hsScalarMul(a.fMap[3][0], b.fMap[0][3]) + hsScalarMul(a.fMap[3][1], b.fMap[1][3]) + hsScalarMul(a.fMap[3][2], b.fMap[2][3]) + hsScalarMul(a.fMap[3][3], b.fMap[3][3]);
#endif
return c;
}
hsVector3 operator*(const hsMatrix44& m, const hsVector3& p)
{
if( m.fFlags & hsMatrix44::kIsIdent )
return p;
hsVector3 rVal;
#if HS_BUILD_FOR_PS2
MulVectorVU0(m.fMap, (MATRIX4) &p, (MATRIX4) &rVal);
#else
rVal.fX = hsScalarMul(p.fX, m.fMap[0][0]) + hsScalarMul(p.fY, m.fMap[0][1]) + hsScalarMul(p.fZ, m.fMap[0][2]);
rVal.fY = hsScalarMul(p.fX, m.fMap[1][0]) + hsScalarMul(p.fY, m.fMap[1][1]) + hsScalarMul(p.fZ, m.fMap[1][2]);
rVal.fZ = hsScalarMul(p.fX, m.fMap[2][0]) + hsScalarMul(p.fY, m.fMap[2][1]) + hsScalarMul(p.fZ, m.fMap[2][2]);
#endif
return rVal;
}
#else // Havok reeks
hsMatrix44 hsMatrix44::operator*(const hsMatrix44& b) const
{
hsMatrix44 c;
if( fFlags & b.fFlags & hsMatrix44::kIsIdent )
{
c.Reset();
return c;
}
if( fFlags & hsMatrix44::kIsIdent )
return b;
if( b.fFlags & hsMatrix44::kIsIdent )
return *this;
#if HS_BUILD_FOR_PS2
MulMatrixVU0(fMap, b.fMap, c.fMap);
#else
c.fMap[0][0] = hsScalarMul(fMap[0][0], b.fMap[0][0]) + hsScalarMul(fMap[0][1], b.fMap[1][0]) + hsScalarMul(fMap[0][2], b.fMap[2][0]) + hsScalarMul(fMap[0][3], b.fMap[3][0]);
c.fMap[0][1] = hsScalarMul(fMap[0][0], b.fMap[0][1]) + hsScalarMul(fMap[0][1], b.fMap[1][1]) + hsScalarMul(fMap[0][2], b.fMap[2][1]) + hsScalarMul(fMap[0][3], b.fMap[3][1]);
c.fMap[0][2] = hsScalarMul(fMap[0][0], b.fMap[0][2]) + hsScalarMul(fMap[0][1], b.fMap[1][2]) + hsScalarMul(fMap[0][2], b.fMap[2][2]) + hsScalarMul(fMap[0][3], b.fMap[3][2]);
c.fMap[0][3] = hsScalarMul(fMap[0][0], b.fMap[0][3]) + hsScalarMul(fMap[0][1], b.fMap[1][3]) + hsScalarMul(fMap[0][2], b.fMap[2][3]) + hsScalarMul(fMap[0][3], b.fMap[3][3]);
c.fMap[1][0] = hsScalarMul(fMap[1][0], b.fMap[0][0]) + hsScalarMul(fMap[1][1], b.fMap[1][0]) + hsScalarMul(fMap[1][2], b.fMap[2][0]) + hsScalarMul(fMap[1][3], b.fMap[3][0]);
c.fMap[1][1] = hsScalarMul(fMap[1][0], b.fMap[0][1]) + hsScalarMul(fMap[1][1], b.fMap[1][1]) + hsScalarMul(fMap[1][2], b.fMap[2][1]) + hsScalarMul(fMap[1][3], b.fMap[3][1]);
c.fMap[1][2] = hsScalarMul(fMap[1][0], b.fMap[0][2]) + hsScalarMul(fMap[1][1], b.fMap[1][2]) + hsScalarMul(fMap[1][2], b.fMap[2][2]) + hsScalarMul(fMap[1][3], b.fMap[3][2]);
c.fMap[1][3] = hsScalarMul(fMap[1][0], b.fMap[0][3]) + hsScalarMul(fMap[1][1], b.fMap[1][3]) + hsScalarMul(fMap[1][2], b.fMap[2][3]) + hsScalarMul(fMap[1][3], b.fMap[3][3]);
c.fMap[2][0] = hsScalarMul(fMap[2][0], b.fMap[0][0]) + hsScalarMul(fMap[2][1], b.fMap[1][0]) + hsScalarMul(fMap[2][2], b.fMap[2][0]) + hsScalarMul(fMap[2][3], b.fMap[3][0]);
c.fMap[2][1] = hsScalarMul(fMap[2][0], b.fMap[0][1]) + hsScalarMul(fMap[2][1], b.fMap[1][1]) + hsScalarMul(fMap[2][2], b.fMap[2][1]) + hsScalarMul(fMap[2][3], b.fMap[3][1]);
c.fMap[2][2] = hsScalarMul(fMap[2][0], b.fMap[0][2]) + hsScalarMul(fMap[2][1], b.fMap[1][2]) + hsScalarMul(fMap[2][2], b.fMap[2][2]) + hsScalarMul(fMap[2][3], b.fMap[3][2]);
c.fMap[2][3] = hsScalarMul(fMap[2][0], b.fMap[0][3]) + hsScalarMul(fMap[2][1], b.fMap[1][3]) + hsScalarMul(fMap[2][2], b.fMap[2][3]) + hsScalarMul(fMap[2][3], b.fMap[3][3]);
c.fMap[3][0] = hsScalarMul(fMap[3][0], b.fMap[0][0]) + hsScalarMul(fMap[3][1], b.fMap[1][0]) + hsScalarMul(fMap[3][2], b.fMap[2][0]) + hsScalarMul(fMap[3][3], b.fMap[3][0]);
c.fMap[3][1] = hsScalarMul(fMap[3][0], b.fMap[0][1]) + hsScalarMul(fMap[3][1], b.fMap[1][1]) + hsScalarMul(fMap[3][2], b.fMap[2][1]) + hsScalarMul(fMap[3][3], b.fMap[3][1]);
c.fMap[3][2] = hsScalarMul(fMap[3][0], b.fMap[0][2]) + hsScalarMul(fMap[3][1], b.fMap[1][2]) + hsScalarMul(fMap[3][2], b.fMap[2][2]) + hsScalarMul(fMap[3][3], b.fMap[3][2]);
c.fMap[3][3] = hsScalarMul(fMap[3][0], b.fMap[0][3]) + hsScalarMul(fMap[3][1], b.fMap[1][3]) + hsScalarMul(fMap[3][2], b.fMap[2][3]) + hsScalarMul(fMap[3][3], b.fMap[3][3]);
#endif
return c;
}
hsVector3 hsMatrix44::operator*(const hsVector3& p) const
{
if( fFlags & hsMatrix44::kIsIdent )
return p;
hsVector3 rVal;
#if HS_BUILD_FOR_PS2
MulVectorVU0(fMap, (MATRIX4) &p, (MATRIX4) &rVal);
#else
rVal.fX = hsScalarMul(p.fX, fMap[0][0]) + hsScalarMul(p.fY, fMap[0][1]) + hsScalarMul(p.fZ, fMap[0][2]);
rVal.fY = hsScalarMul(p.fX, fMap[1][0]) + hsScalarMul(p.fY, fMap[1][1]) + hsScalarMul(p.fZ, fMap[1][2]);
rVal.fZ = hsScalarMul(p.fX, fMap[2][0]) + hsScalarMul(p.fY, fMap[2][1]) + hsScalarMul(p.fZ, fMap[2][2]);
#endif
return rVal;
}
#endif // Havok reeks
#if 0 // Havok reeks
int operator==(const hsMatrix44& s, const hsMatrix44& t)
{
if( s.fFlags & t.fFlags & hsMatrix44::kIsIdent )
{
return true;
}
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
if (s.fMap[i][j] != t.fMap[i][j])
return false;
}
}
return true;
}
#else // Havok reeks
int hsMatrix44::operator==(const hsMatrix44& ss) const
{
if( ss.fFlags & fFlags & hsMatrix44::kIsIdent )
{
return true;
}
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
if (ss.fMap[i][j] != fMap[i][j])
return false;
}
}
return true;
}
#endif // Havok reeks
hsMatrix44& hsMatrix44::Scale(const hsVector3* scale)
{
#if HS_BUILD_FOR_PS2
MulScaleVU0(fMap, (MATRIX4 *) scale);
#else
fMap[0][0] *= scale->fX;
fMap[0][1] *= scale->fX;
fMap[0][2] *= scale->fX;
fMap[0][3] *= scale->fX;
fMap[1][0] *= scale->fY;
fMap[1][1] *= scale->fY;
fMap[1][2] *= scale->fY;
fMap[1][3] *= scale->fY;
fMap[2][0] *= scale->fZ;
fMap[2][1] *= scale->fZ;
fMap[2][2] *= scale->fZ;
fMap[2][3] *= scale->fZ;
#endif
NotIdentity();
return *this;
}
hsVector3 hsMatrix44::RemoveScale()
{
hsVector3 xCol(fMap[0][0], fMap[0][1], fMap[0][2]);
float xLen = xCol.Magnitude();
hsVector3 yCol(fMap[1][0], fMap[1][1], fMap[1][2]);
float yLen = yCol.Magnitude();
hsVector3 zCol(fMap[2][0], fMap[2][1], fMap[2][2]);
float zLen = zCol.Magnitude();
fMap[0][0] /= xLen;
fMap[0][1] /= xLen;
fMap[0][2] /= xLen;
fMap[1][0] /= yLen;
fMap[1][1] /= yLen;
fMap[1][2] /= yLen;
fMap[2][0] /= zLen;
fMap[2][1] /= zLen;
fMap[2][2] /= zLen;
hsVector3 oldScale(xLen, yLen, zLen);
return oldScale;
}
hsMatrix44& hsMatrix44::Translate(const hsVector3* pt)
{
#if HS_BUILD_FOR_PS2
TranslateVU0(fMap, (MATRIX4 *) pt); /* SUNSOFT */
#else
for (int i =0; i < 3; i++)
{
fMap[i][3] += (*pt)[i];
}
#endif
NotIdentity();
return *this;
}
hsMatrix44& hsMatrix44::SetTranslate(const hsScalarTriple* pt)
{
for (int i =0; i < 3; i++)
{
fMap[i][3] = (*pt)[i];
}
NotIdentity();
return *this;
}
hsMatrix44& hsMatrix44::MakeRotateMat(int axis, hsScalar radians)
{
Reset();
SetRotate(axis, radians);
NotIdentity();
return *this;
}
hsMatrix44& hsMatrix44::Rotate(int axis, hsScalar radians)
{
hsMatrix44 rMat;
rMat.MakeRotateMat(axis, radians);
*this = rMat * *this;
return *this;
}
hsMatrix44& hsMatrix44::SetRotate(int axis, hsScalar radians)
{
hsScalar s = hsSine(radians);
hsScalar c = hsCosine(radians);
int c1,c2;
switch (axis)
{
case 0:
c1 = 1;
c2 = 2;
break;
case 1:
c1 = 0;
c2 = 2;
break;
case 2:
c1 = 0;
c2 = 1;
break;
}
fMap[c1][c1] = c;
fMap[c2][c2] = c;
fMap[c1][c2] = s;
fMap[c2][c1] = -s;
NotIdentity();
return *this;
}
void hsMatrix44::MakeXRotation(hsScalar radians)
{
Reset();
hsScalar s = hsSine(radians);
hsScalar c = hsCosine(radians);
fMap[1][1] = c;
fMap[2][2] = c;
fMap[1][2] = s;
fMap[2][1] = -s;
NotIdentity();
}
void hsMatrix44::MakeYRotation(hsScalar radians)
{
Reset();
hsScalar s = hsSine(radians);
hsScalar c = hsCosine(radians);
fMap[0][0] = c;
fMap[2][2] = c;
fMap[0][2] = -s;
fMap[2][0] = s;
NotIdentity();
}
void hsMatrix44::MakeZRotation(hsScalar radians)
{
Reset();
hsScalar s = hsSine(radians);
hsScalar c = hsCosine(radians);
fMap[0][0] = c;
fMap[1][1] = c;
fMap[0][1] = s;
fMap[1][0] = -s;
NotIdentity();
}
//
// Not a camera matrix
//
hsMatrix44& hsMatrix44::Make(const hsPoint3* f, const hsPoint3* at, const hsVector3* up)
{
MakeTranslateMat(&hsVector3(f->fX, f->fY, f->fZ));
hsVector3 back (f,at); // Z
back.Normalize();
hsVector3 leftEar = *up % back; // X, LHS
leftEar.Normalize();
#if 1
// Ignore actual up vector
hsVector3 topHead = leftEar % back; // Y, RHS (should be flipped)
#else
hsVector3 topHead = *up;
#endif
topHead.Normalize();
for(int i = 0; i < 3; i++)
{
fMap[i][0] = leftEar[i];
fMap[i][1] = back[i];
fMap[i][2] = topHead[i];
}
NotIdentity();
return *this;
}
//
// Not a camera matrix
//
hsMatrix44& hsMatrix44::MakeUpPreserving(const hsPoint3* f, const hsPoint3* at, const hsVector3* up)
{
MakeTranslateMat(&hsVector3(f->fX, f->fY, f->fZ));
hsVector3 topHead = *up;
topHead.Normalize();
hsVector3 back (f,at); // Z
back = -back; // really front
hsVector3 leftEar = *up % back; // X
leftEar.Normalize();
back = (topHead % leftEar);
back.Normalize();
for(int i = 0; i < 3; i++)
{
fMap[i][0] = leftEar[i];
fMap[i][1] = back[i];
fMap[i][2] = topHead[i];
}
NotIdentity();
return *this;
}
//
// Get info from a non-camera matrix. Vectors are normalized.
//
void hsMatrix44::GetAxis(hsVector3* view, hsVector3 *up, hsVector3* right)
{
if (view)
view->Set(-fMap[0][1],-fMap[1][1],-fMap[2][1]);
if (right)
right->Set(-fMap[0][0],-fMap[1][0],-fMap[2][0]);
if (up)
up->Set(fMap[0][2], fMap[1][2], fMap[2][2]);
}
const hsVector3 hsMatrix44::GetAxis(int i) const
{
hsVector3 ret;
switch(i)
{
case kView:
{
ret.Set(-fMap[0][1],-fMap[1][1],-fMap[2][1]);
break;
}
case kUp:
{
ret.Set(fMap[0][2], fMap[1][2], fMap[2][2]);
break;
}
case kRight:
{
ret.Set(-fMap[0][0],-fMap[1][0],-fMap[2][0]);
break;
}
}
return ret;
}
//
// Camera matrix
//
hsMatrix44& hsMatrix44::MakeCamera(const hsPoint3* from, const hsPoint3* at,
const hsVector3* up)
{
hsVector3 dirZ(at, from);
hsVector3 trans( -from->fX, -from->fY, -from->fZ );
hsVector3 dirY, dirX;
hsMatrix44 rmat;
dirX = (*up) % dirZ; // Stop passing in down!!! // mf_flip_up - mf
if (dirX.MagnitudeSquared())
dirX.Normalize();
if (dirZ.MagnitudeSquared())
dirZ.Normalize();
dirY = dirZ % dirX;
if (dirY.MagnitudeSquared())
dirY.Normalize();
this->Reset();
this->Translate(&trans);
rmat.Reset();
for(int i = 0; i < 3; i++)
{
rmat.fMap[0][i] = -dirX[i];
rmat.fMap[1][i] = dirY[i];
rmat.fMap[2][i] = dirZ[i];
}
rmat.NotIdentity();
*this = rmat * *this;
return *this;
}
void hsMatrix44::MakeCameraMatrices(const hsPoint3& from, const hsPoint3& at, const hsVector3& up, hsMatrix44& worldToCamera, hsMatrix44& cameraToWorld)
{
hsVector3 dirZ(&at, &from);
hsVector3 dirX(dirZ % up);
dirX.Normalize();
hsVector3 dirY(dirX % dirZ);
dirY.Normalize();
worldToCamera.Reset(false);
cameraToWorld.Reset(false);
int i;
for( i = 0; i < 3; i++ )
{
worldToCamera.fMap[0][i] = dirX[i];
worldToCamera.fMap[1][i] = dirY[i];
worldToCamera.fMap[2][i] = dirZ[i];
cameraToWorld.fMap[i][0] = dirX[i];
cameraToWorld.fMap[i][1] = dirY[i];
cameraToWorld.fMap[i][2] = dirZ[i];
}
hsPoint3 trans = -from;
worldToCamera.fMap[0][3] = dirX.InnerProduct(trans);
worldToCamera.fMap[1][3] = dirY.InnerProduct(trans);
worldToCamera.fMap[2][3] = dirZ.InnerProduct(trans);
cameraToWorld.fMap[0][3] = from.fX;
cameraToWorld.fMap[1][3] = from.fY;
cameraToWorld.fMap[2][3] = from.fZ;
}
void hsMatrix44::MakeEnvMapMatrices(const hsPoint3& pos, hsMatrix44* worldToCameras, hsMatrix44* cameraToWorlds)
{
MakeCameraMatrices(pos, hsPoint3(pos.fX - 1.f, pos.fY, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[0], cameraToWorlds[0]);
MakeCameraMatrices(pos, hsPoint3(pos.fX + 1.f, pos.fY, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[1], cameraToWorlds[1]);
MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY + 1.f, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[2], cameraToWorlds[2]);
MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY - 1.f, pos.fZ), hsVector3(0, 0, 1.f), worldToCameras[3], cameraToWorlds[3]);
MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY, pos.fZ + 1.f), hsVector3(0, -1.f, 0), worldToCameras[4], cameraToWorlds[4]);
MakeCameraMatrices(pos, hsPoint3(pos.fX, pos.fY, pos.fZ - 1.f), hsVector3(0, 1.f, 0), worldToCameras[5], cameraToWorlds[5]);
}
//
// Vectors are normalized.
//
void hsMatrix44::GetAxisFromCamera(hsVector3* view, hsVector3 *up, hsVector3* right)
{
if (view)
view->Set(fMap[2][0],fMap[2][1],fMap[2][2]);
if (right)
right->Set(fMap[0][0],fMap[0][1],fMap[0][2]);
if (up)
up->Set(fMap[1][0], fMap[1][1], fMap[1][2]);
}
//
// Camera matrix
//
hsMatrix44& hsMatrix44::MakeCameraUpPreserving(const hsPoint3* from, const hsPoint3* at,
const hsVector3* up)
{
hsVector3 dirZ(at, from);
hsVector3 trans( -from->fX, -from->fY, -from->fZ );
hsVector3 dirY( up->fX, up->fY, up->fZ );
hsVector3 dirX;
hsMatrix44 rmat;
dirX = dirY % dirZ;
dirX.Normalize();
dirY.Normalize();
dirZ = dirX % dirY;
dirZ.Normalize();
this->Reset();
this->Translate(&trans);
rmat.Reset();
for(int i = 0; i < 3; i++)
{
rmat.fMap[0][i] = -dirX[i];
rmat.fMap[1][i] = dirY[i];
rmat.fMap[2][i] = dirZ[i];
}
rmat.NotIdentity();
*this = rmat * *this;
return *this;
}
///////////////////////////////////////////////////////
static hsScalar GetDeterminant33(const hsMatrix44* mat)
{
return hsScalarMul(hsScalarMul(mat->fMap[0][0], mat->fMap[1][1]), mat->fMap[2][2]) +
hsScalarMul(hsScalarMul(mat->fMap[0][1], mat->fMap[1][2]), mat->fMap[2][0]) +
hsScalarMul(hsScalarMul(mat->fMap[0][2], mat->fMap[1][0]), mat->fMap[2][1]) -
hsScalarMul(hsScalarMul(mat->fMap[0][2], mat->fMap[1][1]), mat->fMap[2][0]) -
hsScalarMul(hsScalarMul(mat->fMap[0][1], mat->fMap[1][0]), mat->fMap[2][2]) -
hsScalarMul(hsScalarMul(mat->fMap[0][0], mat->fMap[1][2]), mat->fMap[2][1]);
}
hsMatrix44* hsMatrix44::GetTranspose(hsMatrix44* transp) const
{
for(int i = 0 ; i < 4; i++)
for(int j=0; j < 4; j++)
transp->fMap[i][j] = fMap[j][i];
return transp;
}
static inline hsScalar Determinant2(hsScalar a, hsScalar b,hsScalar c, hsScalar d)
{
return hsScalarMul(a,d) - hsScalarMul(c,b);
}
static inline hsScalar Determinant3(hsScalar a, hsScalar b, hsScalar c,
hsScalar d, hsScalar e, hsScalar f,
hsScalar g, hsScalar h, hsScalar i)
{
return hsScalarMul(a, Determinant2(e, f, h, i))
- hsScalarMul(b, Determinant2(d, f, g, i))
+ hsScalarMul(c, Determinant2(d, e, g, h));
}
hsScalar hsMatrix44::GetDeterminant() const
{
#if HS_BUILD_FOR_PS2
return (GetDeterminantVU0(fMap));
#else
return (fMap[0][0]*Determinant3(fMap[1][1], fMap[2][1], fMap[3][1],
fMap[1][2], fMap[2][2], fMap[3][2],
fMap[1][3], fMap[2][3], fMap[3][3]) -
fMap[1][0]*Determinant3(fMap[0][1], fMap[2][1], fMap[3][1],
fMap[0][2], fMap[2][2], fMap[3][2],
fMap[0][3], fMap[2][3], fMap[3][3]) +
fMap[2][0]*Determinant3(fMap[0][1], fMap[1][1], fMap[3][1],
fMap[0][2], fMap[1][2], fMap[3][2],
fMap[0][3], fMap[1][3], fMap[3][3]) -
fMap[3][0]*Determinant3(fMap[0][1], fMap[1][1], fMap[2][1],
fMap[0][2], fMap[1][2], fMap[2][2],
fMap[0][3], fMap[1][3], fMap[2][3]));
#endif
}
hsMatrix44 *hsMatrix44::GetAdjoint(hsMatrix44 *adj) const
{
#if HS_BUILD_FOR_PS2
GetAdjointVU0(fMap, adj->fMap);
#else
float a1, a2, a3, a4, b1, b2, b3, b4;
float c1, c2, c3, c4, d1, d2, d3, d4;
/*
* calculate the adjoint of a 4x4 matrix
*
* Let a denote the minor determinant of matrix A obtained by
* ij
*
* deleting the ith row and jth column from A.
*
* i+j
* Let b = (-1) a
* ij ji
*
* The matrix B = (b ) is the adjoint of A
* ij
*/
/* assign to individual variable names to aid */
/* selecting correct values */
a1 = fMap[0][0];
b1 = fMap[0][1];
c1 = fMap[0][2];
d1 = fMap[0][3];
a2 = fMap[1][0];
b2 = fMap[1][1];
c2 = fMap[1][2];
d2 = fMap[1][3];
a3 = fMap[2][0];
b3 = fMap[2][1];
c3 = fMap[2][2];
d3 = fMap[2][3];
a4 = fMap[3][0];
b4 = fMap[3][1];
c4 = fMap[3][2];
d4 = fMap[3][3];
/*
* row column labeling reversed since we transpose rows & columns
*/
adj->fMap[0][0] = Determinant3(b2, b3, b4, c2, c3, c4, d2, d3, d4);
adj->fMap[1][0] = -Determinant3(a2, a3, a4, c2, c3, c4, d2, d3, d4);
adj->fMap[2][0] = Determinant3(a2, a3, a4, b2, b3, b4, d2, d3, d4);
adj->fMap[3][0] = -Determinant3(a2, a3, a4, b2, b3, b4, c2, c3, c4);
adj->fMap[0][1] = -Determinant3(b1, b3, b4, c1, c3, c4, d1, d3, d4);
adj->fMap[1][1] = Determinant3(a1, a3, a4, c1, c3, c4, d1, d3, d4);
adj->fMap[2][1] = -Determinant3(a1, a3, a4, b1, b3, b4, d1, d3, d4);
adj->fMap[3][1] = Determinant3(a1, a3, a4, b1, b3, b4, c1, c3, c4);
adj->fMap[0][2] = Determinant3(b1, b2, b4, c1, c2, c4, d1, d2, d4);
adj->fMap[1][2] = -Determinant3(a1, a2, a4, c1, c2, c4, d1, d2, d4);
adj->fMap[2][2] = Determinant3(a1, a2, a4, b1, b2, b4, d1, d2, d4);
adj->fMap[3][2] = -Determinant3(a1, a2, a4, b1, b2, b4, c1, c2, c4);
adj->fMap[0][3] = -Determinant3(b1, b2, b3, c1, c2, c3, d1, d2, d3);
adj->fMap[1][3] = Determinant3(a1, a2, a3, c1, c2, c3, d1, d2, d3);
adj->fMap[2][3] = -Determinant3(a1, a2, a3, b1, b2, b3, d1, d2, d3);
adj->fMap[3][3] = Determinant3(a1, a2, a3, b1, b2, b3, c1, c2, c3);
#endif
adj->NotIdentity();
return adj;
}
hsMatrix44* hsMatrix44::GetInverse(hsMatrix44* inverse) const
{
hsScalar det = GetDeterminant();
int i,j;
if (det == 0.0f)
{
inverse->Reset();
return inverse;
}
det = hsScalarInvert(det);
GetAdjoint(inverse);
#if HS_BUILD_FOR_PS2
MatMulVU0(inverse->fMap, det);
#else
for (i=0; i<4; i++)
for (j=0; j<4; j++)
inverse->fMap[i][j] *= det;
#endif
return inverse;
}
hsMatrix44& hsMatrix44::SetScale(const hsVector3* pt)
{
for (int i =0; i < 3; i++)
{
fMap[i][i] = (*pt)[i];
}
NotIdentity();
return *this;
}
hsMatrix44& hsMatrix44::MakeScaleMat(const hsVector3* pt)
{
Reset();
SetScale(pt);
return *this;
}
hsMatrix44 &hsMatrix44::MakeTranslateMat(const hsVector3 *trans)
{
Reset();
SetTranslate(trans);
return *this;
}
hsVector3* hsMatrix44::GetTranslate(hsVector3 *pt) const
{
for (int i =0; i < 3; i++)
{
(*pt)[i] = fMap[i][3];
}
return pt;
}
const hsPoint3 hsMatrix44::GetTranslate() const
{
hsPoint3 pt;
for (int i =0; i < 3; i++)
{
(pt)[i] = fMap[i][3];
}
return pt;
}
hsPoint3* hsMatrix44::MapPoints(long count, hsPoint3 points[]) const
{
if( !(fFlags & hsMatrix44::kIsIdent) )
{
int i;
for(i = 0; i < count; i++)
{
points[i] = *this * points[i];
}
}
return points;
}
hsBool hsMatrix44::IsIdentity(void)
{
hsBool retVal = true;
int i, j;
for( i = 0; i < 4; i++ )
{
for( j = 0; j < 4; j++ )
{
#if 0 // IDENTITY_CRISIS
if( i == j)
{
if (fMap[i][j] != hsScalar1)
{
NotIdentity();
retVal = false;
}
}
else
{
if( fMap[i][j] != 0 )
{
NotIdentity();
retVal = false;
}
}
#else // IDENTITY_CRISIS
const hsScalar kEPS = 1.e-5f;
if( i == j)
{
if( (fMap[i][j] < hsScalar1-kEPS) || (fMap[i][j] > hsScalar1+kEPS) )
{
NotIdentity();
retVal = false;
}
else
{
fMap[i][j] = hsScalar1;
}
}
else
{
if( (fMap[i][j] < -kEPS) || (fMap[i][j] > kEPS) )
{
NotIdentity();
retVal = false;
}
else
{
fMap[i][j] = 0;
}
}
#endif // IDENTITY_CRISIS
}
}
if( retVal )
fFlags |= kIsIdent;
return retVal;
}
hsBool hsMatrix44::GetParity() const
{
if( fFlags & kIsIdent )
return false;
hsVector3* rows[3];
rows[0] = (hsVector3*)&fMap[0][0];
rows[1] = (hsVector3*)&fMap[1][0];
rows[2] = (hsVector3*)&fMap[2][0];
hsVector3 zeroXone = *rows[0] % *rows[1];
return zeroXone.InnerProduct(rows[2]) < 0;
}
void hsMatrix44::Read(hsStream *stream)
{
if (stream->ReadBool())
{
int i,j;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
#if HS_SCALAR_IS_FIXED
fMap[i][j] = stream->ReadSwap32();
#endif
#if HS_SCALAR_IS_FLOAT
fMap[i][j] = stream->ReadSwapFloat();
#endif
IsIdentity();
}
else
Reset();
}
void hsMatrix44::Write(hsStream *stream)
{
hsBool ident = IsIdentity();
stream->WriteBool(!ident);
if (!ident)
{
int i,j;
for(i=0; i<4; i++)
for(j=0; j<4; j++)
#if HS_SCALAR_IS_FIXED
stream->WriteSwap32(fMap[i][j]);
#endif
#if HS_SCALAR_IS_FLOAT
stream->WriteSwapFloat(fMap[i][j]);
#endif
}
}

View File

@ -0,0 +1,186 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HSMATRIX44_inc
#define HSMATRIX44_inc
#include "hsTypes.h"
#include "hsGeometry3.h"
class hsQuat;
////////////////////////////////////////////////////////////////////////////
class hsStream;
struct hsMatrix44 {
enum {
kIsIdent = 0x1
};
enum {
kRight = 0,
kUp,
kView
};
hsScalar fMap[4][4];
UInt32 fFlags;
hsMatrix44() : fFlags(0) {}
hsMatrix44(const hsScalarTriple &translate, const hsQuat &rotate);
void DecompRigid(hsScalarTriple &translate, hsQuat &rotate) const;
static const hsMatrix44& IdentityMatrix();
// worldToCameras and cameraToWorlds are arrays of 6 matrices. Returned are LEFT,RIGHT,FRONT,BACK,TOP,BOTTOM.
static void MakeEnvMapMatrices(const hsPoint3& pos, hsMatrix44* worldToCameras, hsMatrix44* cameraToWorlds);
static void MakeCameraMatrices(const hsPoint3& from, const hsPoint3& at, const hsVector3& up, hsMatrix44& worldToCamera, hsMatrix44& cameraToWorld);
// Concat transform
hsMatrix44& Translate(const hsVector3 *);
hsMatrix44& Scale(const hsVector3 *);
hsMatrix44& Rotate(int axis, hsScalar radians);
hsMatrix44& Reset(hsBool asIdent=true)
{
fMap[0][0] = 1.0f; fMap[0][1] = 0.0f; fMap[0][2] = 0.0f; fMap[0][3] = 0.0f;
fMap[1][0] = 0.0f; fMap[1][1] = 1.0f; fMap[1][2] = 0.0f; fMap[1][3] = 0.0f;
fMap[2][0] = 0.0f; fMap[2][1] = 0.0f; fMap[2][2] = 1.0f; fMap[2][3] = 0.0f;
fMap[3][0] = 0.0f; fMap[3][1] = 0.0f; fMap[3][2] = 0.0f; fMap[3][3] = 1.0f;
fFlags = asIdent ? kIsIdent : 0;
return *this;
}
// Create matrix from scratch
hsMatrix44& MakeTranslateMat(const hsVector3 *trans);
hsMatrix44& MakeScaleMat(const hsVector3 *scale);
hsMatrix44& MakeRotateMat(int axis, hsScalar radians);
hsMatrix44& Make(const hsPoint3* from, const hsPoint3* at,
const hsVector3* up); // Not a camera matrix
hsMatrix44& MakeUpPreserving(const hsPoint3* from, const hsPoint3* at,
const hsVector3* up); // Not a camera matrix
// Camera matrix
hsMatrix44& MakeCamera(const hsPoint3* from, const hsPoint3* at,
const hsVector3* up);
hsMatrix44& MakeCameraUpPreserving(const hsPoint3* from, const hsPoint3* at,
const hsVector3* up);
hsBool GetParity() const;
hsScalar GetDeterminant() const;
hsMatrix44* GetInverse(hsMatrix44* inverse) const;
hsMatrix44* GetTranspose(hsMatrix44* inverse) const;
hsMatrix44* GetAdjoint(hsMatrix44* adjoint) const;
hsVector3* GetTranslate(hsVector3 *pt) const;
hsPoint3* GetTranslate(hsPoint3 *pt) const
{ return (hsPoint3*)GetTranslate((hsVector3*)pt); }
const hsPoint3 GetTranslate() const;
void GetAxis(hsVector3* view, hsVector3 *up, hsVector3* right);
void GetAxisFromCamera(hsVector3* view, hsVector3 *up, hsVector3* right);
const hsVector3 GetAxis(int i) const;
// Change component of matrix
hsMatrix44& SetTranslate(const hsScalarTriple *);
hsMatrix44& SetScale(const hsVector3 *);
hsMatrix44& SetRotate(int axis, hsScalar radians);
hsVector3 RemoveScale(); // returns old scale
void MakeXRotation(hsScalar radians);
void MakeYRotation(hsScalar radians);
void MakeZRotation(hsScalar radians);
#if 0 // Havok reeks
friend hsPoint3 operator*(const hsMatrix44& m, const hsPoint3& p)
{
if( m.fFlags & hsMatrix44::kIsIdent )
return p;
hsPoint3 rVal;
rVal.fX = hsScalarMul(p.fX, m.fMap[0][0]) + hsScalarMul(p.fY, m.fMap[0][1]) + hsScalarMul(p.fZ, m.fMap[0][2]) + m.fMap[0][3];
rVal.fY = hsScalarMul(p.fX, m.fMap[1][0]) + hsScalarMul(p.fY, m.fMap[1][1]) + hsScalarMul(p.fZ, m.fMap[1][2]) + m.fMap[1][3];
rVal.fZ = hsScalarMul(p.fX, m.fMap[2][0]) + hsScalarMul(p.fY, m.fMap[2][1]) + hsScalarMul(p.fZ, m.fMap[2][2]) + m.fMap[2][3];
return rVal;
}
friend hsVector3 operator*(const hsMatrix44& m, const hsVector3& p);
friend hsMatrix44 operator*(const hsMatrix44& a, const hsMatrix44& b);
#else // Havok reeks
hsPoint3 operator*(const hsPoint3& p) const
{
if( fFlags & hsMatrix44::kIsIdent )
return p;
hsPoint3 rVal;
rVal.fX = hsScalarMul(p.fX, fMap[0][0]) + hsScalarMul(p.fY, fMap[0][1]) + hsScalarMul(p.fZ, fMap[0][2]) + fMap[0][3];
rVal.fY = hsScalarMul(p.fX, fMap[1][0]) + hsScalarMul(p.fY, fMap[1][1]) + hsScalarMul(p.fZ, fMap[1][2]) + fMap[1][3];
rVal.fZ = hsScalarMul(p.fX, fMap[2][0]) + hsScalarMul(p.fY, fMap[2][1]) + hsScalarMul(p.fZ, fMap[2][2]) + fMap[2][3];
return rVal;
}
hsVector3 operator*(const hsVector3& p) const;
hsMatrix44 operator*(const hsMatrix44& b) const;
#endif // Havok reeks
hsPoint3* MapPoints(long count, hsPoint3 points[]) const;
hsBool IsIdentity(void);
void NotIdentity() { fFlags &= ~kIsIdent; }
#if 0 // Havok reeks
friend int operator==(const hsMatrix44& s, const hsMatrix44& t);
friend int operator!=(const hsMatrix44& s, const hsMatrix44& t);
#else // Havok reeks
hsBool operator==(const hsMatrix44& ss) const;
hsBool operator!=(const hsMatrix44& ss) const { return !(ss == *this); }
#endif // Havok reeks
void Read(hsStream *stream);
void Write(hsStream *stream);
} ATTRIBUTE_FOR_PS2; /* SUNSOFT */
#if 0 // Havok reeks
inline int operator!=(const hsMatrix44& s, const hsMatrix44& t)
{
return (!(s==t));
}
#endif // Havok reeks
////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,874 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#if HS_BUILD_FOR_MAC
#include <Memory.h>
#else
#include <string.h>
#endif
#include "hsMemory.h"
#include "hsExceptions.h"
#define DO_MEMORY_REPORTS // dumps memory reports upon start up of engine
///////////////////////////////////////////////////////////////////////////////////////////
#if HS_BUILD_FOR_MAC
void HSMemory::BlockMove(const void* src, void* dst, UInt32 length)
{
::BlockMoveData(src, dst, length);
}
#else
void HSMemory::BlockMove(const void* src, void* dst, UInt32 length)
{
memmove(dst, src, length);
}
#endif
hsBool HSMemory::EqualBlocks(const void* block1, const void* block2, UInt32 length)
{
const Byte* byte1 = (Byte*)block1;
const Byte* byte2 = (Byte*)block2;
while (length--)
if (*byte1++ != *byte2++)
return false;
return true;
}
void* HSMemory::New(UInt32 size)
{
return TRACKED_NEW UInt32[(size + 3) >> 2];
}
void HSMemory::Delete(void* block)
{
delete[] (UInt32*)block;
}
void* HSMemory::Copy(UInt32 length, const void* source)
{
void* destination = HSMemory::New(length);
HSMemory::BlockMove(source, destination, length);
return destination;
}
void HSMemory::Clear(void* m, UInt32 byteLen)
{
UInt8* mem = (UInt8*)m;
UInt8* memStop = mem + byteLen;
if (byteLen > 8)
{ while (UInt32(mem) & 3)
*mem++ = 0;
UInt32* mem32 = (UInt32*)mem;
UInt32* mem32Stop = (UInt32*)(UInt32(memStop) & ~3);
do {
*mem32++ = 0;
} while (mem32 < mem32Stop);
mem = (UInt8*)mem32;
// fall through to finish any remaining bytes (0..3)
}
while (mem < memStop)
*mem++ = 0;
hsAssert(mem == memStop, "oops");
}
//////////////////////////////////////////////////////////////////////////////////////
#if 0
template <class T> T* hsSoftNew(T*& obj)
{
try {
obj = TRACKED_NEW T;
}
catch (...) {
obj = nil;
}
return obj;
}
inline template <class T> T* hsSoftNew(T*& obj, unsigned count)
{
try {
obj = TRACKED_NEW T[count];
}
catch (...) {
obj = nil;
}
return obj;
}
#endif
void* HSMemory::SoftNew(UInt32 size)
{
UInt32* p;
hsTry {
p = TRACKED_NEW UInt32[(size + 3) >> 2];
} hsCatch(...) {
p = nil;
}
return p;
}
//////////////////////////////////////////////////////////////////////////////////////
struct hsPrivateChunk {
hsPrivateChunk* fNext;
char* fAvailableAddr;
UInt32 fAvailableSize;
hsDebugCode(UInt32 fSize;)
hsDebugCode(UInt32 fCount;)
static hsPrivateChunk* NewPrivateChunk(hsPrivateChunk* next, UInt32 chunkSize);
};
hsPrivateChunk* hsPrivateChunk::NewPrivateChunk(hsPrivateChunk* next, UInt32 chunkSize)
{
hsPrivateChunk* chunk = (hsPrivateChunk*)HSMemory::New(sizeof(hsPrivateChunk) + chunkSize);
chunk->fNext = next;
chunk->fAvailableAddr = (char*)chunk + sizeof(hsPrivateChunk);
chunk->fAvailableSize = chunkSize;
hsDebugCode(chunk->fSize = chunkSize;)
hsDebugCode(chunk->fCount = 0;)
return chunk;
}
hsChunkAllocator::hsChunkAllocator(UInt32 chunkSize) : fChunkSize(chunkSize), fChunk(nil)
{
hsDebugCode(fChunkCount = 0;)
}
hsChunkAllocator::~hsChunkAllocator()
{
this->Reset();
}
void hsChunkAllocator::Reset()
{
hsPrivateChunk* chunk = fChunk;
while (chunk)
{ hsPrivateChunk* next = chunk->fNext;
HSMemory::Delete(chunk);
chunk = next;
}
fChunk = nil;
hsDebugCode(fChunkCount = 0;)
}
void hsChunkAllocator::SetChunkSize(UInt32 chunkSize)
{
fChunkSize = chunkSize;
}
void* hsChunkAllocator::Allocate(UInt32 size, const void* data)
{
void* addr;
if (fChunk == nil || fChunk->fAvailableSize < size)
{ if (size > fChunkSize)
fChunkSize = size;
fChunk = hsPrivateChunk::NewPrivateChunk(fChunk, fChunkSize);
hsDebugCode(fChunkCount += 1;)
}
addr = fChunk->fAvailableAddr;
fChunk->fAvailableAddr += size;
fChunk->fAvailableSize -= size;
hsDebugCode(fChunk->fCount += 1;)
if (data)
HSMemory::BlockMove(data, addr, size);
return addr;
}
void* hsChunkAllocator::SoftAllocate(UInt32 size, const void* data)
{
void* addr;
hsTry {
addr = this->Allocate(size, data);
}
hsCatch(...) {
addr = nil;
}
return addr;
}
//////////////////////////////////////////////////////////////////////////////////////
struct hsAppenderHead {
struct hsAppenderHead* fNext;
struct hsAppenderHead* fPrev;
void* fFirst;
void* fStop;
void* fBottom;
void* GetTop() const { return (char*)this + sizeof(*this); }
void* GetBottom() const { return fBottom; }
void* GetStop() const { return fStop; }
void* GetFirst() const { return fFirst; }
void* GetLast(UInt32 elemSize) const { return (char*)fStop - elemSize; }
UInt32 GetSize() const { return (char*)fStop - (char*)fFirst; }
hsBool CanPrepend() const { return fFirst != this->GetTop(); }
int PrependSize() const { return (char*)fFirst - (char*)this->GetTop(); }
hsBool CanAppend() const { return fStop != this->GetBottom(); }
int AppendSize() const { return (char*)this->GetBottom() - (char*)fStop; }
void* Prepend(UInt32 elemSize)
{
hsAssert(this->CanPrepend(), "bad prepend");
fFirst = (char*)fFirst - elemSize;
hsAssert((char*)fFirst >= (char*)this->GetTop(), "bad elemSize");
return fFirst;
}
void* Append(UInt32 elemSize)
{
hsAssert(this->CanAppend(), "bad append");
void* data = fStop;
fStop = (char*)fStop + elemSize;
hsAssert((char*)fStop <= (char*)fBottom, "bad elemSize");
return data;
}
hsBool PopHead(UInt32 elemSize, void* data)
{
hsAssert(fFirst != fStop, "Empty");
if( data )
HSMemory::BlockMove(fFirst, data, elemSize);
fFirst = (char*)fFirst + elemSize;
return fFirst == fStop;
}
hsBool PopTail(UInt32 elemSize, void* data)
{
hsAssert(fFirst != fStop, "Empty");
fStop = (char*)fStop - elemSize;
if( data )
HSMemory::BlockMove(fStop, data, elemSize);
return fFirst == fStop;
}
static hsAppenderHead* NewAppend(UInt32 elemSize, UInt32 elemCount, hsAppenderHead* prev)
{
UInt32 dataSize = elemSize * elemCount;
hsAppenderHead* head = (hsAppenderHead*)HSMemory::New(sizeof(hsAppenderHead) + dataSize);
head->fNext = nil;
head->fPrev = prev;
head->fFirst = head->GetTop();
head->fStop = head->fFirst;
head->fBottom = (char*)head->fFirst + dataSize;
return head;
}
static hsAppenderHead* NewPrepend(UInt32 elemSize, UInt32 elemCount, hsAppenderHead* next)
{
UInt32 dataSize = elemSize * elemCount;
hsAppenderHead* head = (hsAppenderHead*)HSMemory::New(sizeof(hsAppenderHead) + dataSize);
head->fNext = next;
head->fPrev = nil;
head->fBottom = (char*)head->GetTop() + dataSize;
head->fFirst = head->fBottom;
head->fStop = head->fBottom;
return head;
}
};
////////////////////////////////////////////////////////////////////////////////////////
hsAppender::hsAppender(UInt32 elemSize, UInt32 elemCount)
: fFirstBlock(nil), fElemSize(elemSize), fElemCount(elemCount), fCount(0)
{
}
hsAppender::~hsAppender()
{
this->Reset();
}
UInt32 hsAppender::CopyInto(void* data) const
{
if (data)
{ const hsAppenderHead* head = fFirstBlock;
hsDebugCode(UInt32 totalSize = 0;)
while (head != nil)
{ UInt32 size = head->GetSize();
HSMemory::BlockMove(head->GetFirst(), data, size);
data = (char*)data + size;
head = head->fNext;
hsDebugCode(totalSize += size;)
}
hsAssert(totalSize == fCount * fElemSize, "bad size");
}
return fCount * fElemSize;
}
void hsAppender::Reset()
{
hsAppenderHead* head = fFirstBlock;
while (head != nil)
{ hsAppenderHead* next = head->fNext;
HSMemory::Delete(head);
head = next;
}
fCount = 0;
fFirstBlock = nil;
fLastBlock = nil;
}
void* hsAppender::PushHead()
{
if (fFirstBlock == nil)
{ fFirstBlock = hsAppenderHead::NewPrepend(fElemSize, fElemCount, nil);
fLastBlock = fFirstBlock;
}
else if (fFirstBlock->CanPrepend() == false)
fFirstBlock = hsAppenderHead::NewPrepend(fElemSize, fElemCount, fFirstBlock);
fCount += 1;
return fFirstBlock->Prepend(fElemSize);
}
void hsAppender::PushHead(const void* data)
{
void* addr = this->PushHead();
if (data)
HSMemory::BlockMove(data, addr, fElemSize);
}
void* hsAppender::PeekHead() const
{
if (fFirstBlock)
return (char*)fFirstBlock->fFirst;
else
return nil;
}
hsBool hsAppender::PopHead(void* data)
{
if (fCount == 0)
return false;
fCount -= 1;
if (fFirstBlock->PopHead(fElemSize, data))
{ hsAppenderHead* next = fFirstBlock->fNext;
if (next)
next->fPrev = nil;
HSMemory::Delete(fFirstBlock);
fFirstBlock = next;
if (next == nil)
fLastBlock = nil;
}
return true;
}
int hsAppender::PopHead(int count, void* data)
{
hsThrowIfBadParam(count >= 0);
int sizeNeeded = count * fElemSize;
int origCount = fCount;
while (fCount > 0)
{ int size = fFirstBlock->GetSize();
if (size > sizeNeeded)
size = sizeNeeded;
if (fFirstBlock->PopHead(size, data))
{ hsAppenderHead* next = fFirstBlock->fNext;
if (next)
next->fPrev = nil;
HSMemory::Delete(fFirstBlock);
fFirstBlock = next;
if (next == nil)
fLastBlock = nil;
}
if (data)
data = (void*)((char*)data + size);
sizeNeeded -= size;
fCount -= size / fElemSize;
hsAssert(int(fCount) >= 0, "bad fElemSize");
}
return origCount - fCount; // return number of elements popped
}
void* hsAppender::PushTail()
{
if (fFirstBlock == nil)
{ fFirstBlock = hsAppenderHead::NewAppend(fElemSize, fElemCount, nil);
fLastBlock = fFirstBlock;
}
else if (fLastBlock->CanAppend() == false)
{ fLastBlock->fNext = hsAppenderHead::NewAppend(fElemSize, fElemCount, fLastBlock);
fLastBlock = fLastBlock->fNext;
}
fCount += 1;
return fLastBlock->Append(fElemSize);
}
void hsAppender::PushTail(const void* data)
{
void* addr = this->PushTail();
if (data)
HSMemory::BlockMove(data, addr, fElemSize);
}
void hsAppender::PushTail(int count, const void* data)
{
hsThrowIfBadParam(count < 0);
int sizeNeeded = count * fElemSize;
while (sizeNeeded > 0)
{ if (fFirstBlock == nil)
{ hsAssert(fCount == 0, "uninited count");
fFirstBlock = hsAppenderHead::NewAppend(fElemSize, fElemCount, nil);
fLastBlock = fFirstBlock;
}
else if (fLastBlock->CanAppend() == false)
{ fLastBlock->fNext = hsAppenderHead::NewAppend(fElemSize, fElemCount, fLastBlock);
fLastBlock = fLastBlock->fNext;
}
int size = fLastBlock->AppendSize();
hsAssert(size > 0, "bad appendsize");
if (size > sizeNeeded)
size = sizeNeeded;
void* dst = fLastBlock->Append(size);
if (data)
{ HSMemory::BlockMove(data, dst, size);
data = (char*)data + size;
}
sizeNeeded -= size;
}
fCount += count;
}
void* hsAppender::PeekTail() const
{
if (fLastBlock)
return (char*)fLastBlock->fStop - fElemSize;
else
return nil;
}
hsBool hsAppender::PopTail(void* data)
{
if (fCount == 0)
return false;
fCount -= 1;
if (fLastBlock->PopTail(fElemSize, data))
{ hsAppenderHead* prev = fLastBlock->fPrev;
if (prev)
prev->fNext = nil;
HSMemory::Delete(fLastBlock);
fLastBlock = prev;
if (prev == nil)
fFirstBlock = nil;
}
return true;
}
//////////////////////////////////////////////////////////////////////////
hsAppenderIterator::hsAppenderIterator(const hsAppender* list)
{
this->ResetToHead(list);
}
void hsAppenderIterator::ResetToHead(const hsAppender* list)
{
fAppender = list;
fCurrBlock = nil;
if (fAppender)
{ fCurrBlock = fAppender->fFirstBlock;
if (fCurrBlock)
fCurrItem = fCurrBlock->GetFirst();
}
}
void hsAppenderIterator::ResetToTail(const hsAppender* list)
{
fAppender = list;
fCurrBlock = nil;
if (fAppender)
{ fCurrBlock = fAppender->fLastBlock;
if (fCurrBlock)
fCurrItem = fCurrBlock->GetLast(fAppender->fElemSize);
}
}
void* hsAppenderIterator::Next()
{
void* item = nil;
if (fCurrBlock)
{ item = fCurrItem;
fCurrItem = (char*)fCurrItem + fAppender->fElemSize;
if (fCurrItem == fCurrBlock->GetBottom())
{ fCurrBlock = fCurrBlock->fNext;
if (fCurrBlock)
fCurrItem = fCurrBlock->GetFirst();
}
else if (fCurrItem == fCurrBlock->GetStop())
{ hsAssert(fCurrBlock->fNext == nil, "oops");
fCurrBlock = nil;
}
}
return item;
}
hsBool hsAppenderIterator::Next(void* data)
{
void* addr = this->Next();
if (addr)
{ if (data)
HSMemory::BlockMove(addr, data, fAppender->fElemSize);
return true;
}
return false;
}
int hsAppenderIterator::Next(int count, void* data)
{
int origCount = count;
while (count > 0 && this->Next(data))
{ if (data)
data = (void*)((char*)data + fAppender->fElemSize);
count -= 1;
}
return origCount - count;
}
void* hsAppenderIterator::Prev()
{
void* item = nil;
if (fCurrBlock)
{ item = fCurrItem;
fCurrItem = (char*)fCurrItem - fAppender->fElemSize;
if (item == fCurrBlock->GetTop())
{ fCurrBlock = fCurrBlock->fPrev;
if (fCurrBlock)
fCurrItem = fCurrBlock->GetLast(fAppender->fElemSize);
}
else if (item == fCurrBlock->GetFirst())
{ hsAssert(fCurrBlock->fPrev == nil, "oops");
fCurrBlock = nil;
}
}
return item;
}
hsBool hsAppenderIterator::Prev(void* data)
{
void* addr = this->Prev();
if (addr)
{ if (data)
HSMemory::BlockMove(addr, data, fAppender->fElemSize);
return true;
}
return false;
}
//-------------------------------------------------------------
//
// MEMORY USE REPORTING CODE
//
//-------------------------------------------------------------
#if 1//!(defined(HS_DEBUGGING)&&(HS_BUILD_FOR_WIN32)&& defined(HS_FIND_MEM_LEAKS))
// EMPTY STUB
void SortNDumpUnfreedMemory(const char *, bool ) // file name base, and FULL report indicator
{
}
#else
typedef struct _CrtMemBlockHeader
{
// Pointer to the block allocated just before this one:
struct _CrtMemBlockHeader *pBlockHeaderNext;
// Pointer to the block allocated just after this one:
struct _CrtMemBlockHeader *pBlockHeaderPrev;
char *szFileName; // File name
int nLine; // Line number
size_t nDataSize; // Size of user block
int nBlockUse; // Type of block
long lRequest; // Allocation number
// Buffer just before (lower than) the user's memory:
unsigned char gap[4];
} _CrtMemBlockHeader;
/* In an actual memory block in the debug heap,
* this structure is followed by:
* unsigned char data[nDataSize];
* unsigned char anotherGap[4];
*/
//
// Dump formatted string to OutputDebugString
//
void __cdecl DebugMsg( LPSTR fmt, ... )
{
char buff[256];
wvsprintf(buff, fmt, (char *)(&fmt+1));
hsStatusMessage(buff);
}
char *TrimFileName(char *name) // Trim file name of leading Directories
{
int len = 0;
char *ptr;
if (!name) return NULL;
len = strlen(name);
ptr = name + len;
for ( ptr--; ptr > name; ptr--)
{
if (*ptr == '\\')
{
ptr++;
break;
}
}
return ptr;
}
//
// Loop thru all unfreed blocks in the heap and dump out detailed info
//
struct looktbl {
char * fName; // Name of file
// long fAllocs; // Number of Alloc calls
long fBytes; // Total Bytes Alloc'd
};
#define LTBLMAX 300
//---------------------------------------------------------------------------
// This routine will report on the memory used in the engine.
// If argument full is true, it gives a full dump from the start of the program
// if !full, then each time the routine is called it remembers where it finishes off, then the next
// call with !full, it will (attempt) to report on the newest allocations, backward to the last checkpoint
//--------------------------------------------------------------------------
void SortNDumpUnfreedMemory(const char *nm, bool full) // file name base, and FULL report indicator
{
#ifndef DO_MEMORY_REPORTS
if (!full) // full is launched by control M...partials are called each time the engine starts
return;
#endif
char fname[512];
sprintf(fname,"%s_dmp.txt",nm);
char *errStr = "";
_CrtMemState heap_state;
static UInt32 GrandTotal =0;
static _CrtMemBlockHeader *cmbh_last; // Remember this header for next incremental check DANGER this
// could break if this is freed...(gives bad report)
_CrtMemBlockHeader *cmbh_last_good;
_CrtMemBlockHeader *cmbh;
// Get Current heap state
_CrtMemCheckpoint(&heap_state);
cmbh = heap_state.pBlockHeader;
long totsize= 0; // Track Total Bytes
long normsize = 0; // Track total of NORMAL Blocks
looktbl *ltb = TRACKED_NEW looktbl[LTBLMAX];
long tblEnd=1; // first is "NULL";
memset((void *)ltb,0,sizeof(looktbl) * LTBLMAX); // clear table area
char *ftrim;
ltb[0].fName = "NULL"; // Use first Table Pos for NULL
long tblpos;
while (cmbh != NULL) // Accumulate Stats to table
{
if (cmbh == cmbh_last && !full) // full indicates ignore last "checkpoint", stop at last checkpoint if !full
break;
cmbh_last_good = cmbh;
totsize += cmbh->nDataSize;
if (cmbh->nBlockUse == _NORMAL_BLOCK)
{
normsize += cmbh->nDataSize;
if (cmbh->szFileName != NULL) // Shorten to just the file name, looks better, and strcmps faster
{
ftrim = TrimFileName(cmbh->szFileName);
for (tblpos = 1; tblpos < tblEnd; tblpos++) // find the name in the table
{
if (!strcmp(ftrim,ltb[tblpos].fName))
break; // found it
}
}
else
{
tblpos = 0; // Use "NULL", first pos of table
}
if (tblpos == tblEnd) // Did not find it...add it
{
tblEnd++;
if (tblEnd >= LTBLMAX)
{ DebugMsg("DumpUnfreedMemoryInfo: EXCEED MAX TABLE LENGTH\n");
tblEnd--;
break;
}
ltb[tblpos].fName = ftrim; // Add name
}
// Add Stats
// ltb[tblpos].fAllocs++;
ltb[tblpos].fBytes += cmbh->nDataSize;
}
cmbh = cmbh->pBlockHeaderNext;
}
// This Code relies on the _CrtMemBlockHeader *cmbh_last_good for the "last" checkpoint to still be around...
// If the following occurs, that chunk has been deleted. we could fix this by allocating our own
// chunk and keeping it (watch for mem leaks though) or figuring out an "approximat" re syncying routine
// that works before we run thru collecting data. PBG
if (cmbh_last && !full && cmbh == NULL)
{
//hsAssert(0,"Stats error: incremental mem check point has been deleted");
errStr = "CHECK POINT ERROR, Results Inacurate";
}
if (normsize) // Don't write out about nothing
{
CreateDirectory("Reports",NULL); // stick em in a sub directory
char fnm[512];
sprintf(fnm,"Reports\\%s",fname);
FILE * DumpLogFile = fopen( fnm, "w" );
// long allocs=0;
if ( DumpLogFile != NULL )
{
// Print Stats
fprintf(DumpLogFile, "Filename Total=%ld(k) %s\n",(normsize + 500)/1000,errStr);
for (int i = 0; i < tblEnd; i++)
{ //fprintf(DumpLogFile,"%s\t%ld\n",ltb[i].fName, (ltb[i].fBytes+500)/1000);//,ltb[i].fAllocs);
fprintf(DumpLogFile,"%s ",ltb[i].fName);
int len = strlen(ltb[i].fName);
for(int x=len; x < 25; x++)
fputc(' ',DumpLogFile); // make even columns
fprintf(DumpLogFile,"%5ld K\n",(UInt32)( ltb[i].fBytes+500)/1000);//,ltb[i].fAllocs);
//allocs += ltb[i].fAllocs;
}
DebugMsg("MEMORY USE FILE DUMPED TO %s \n",fname);
DebugMsg("MEMORY Check: Total size %ld, Normal Size: %ld\n",totsize,normsize);
fclose(DumpLogFile);
}
static int first=1;
if (!full) // if this is a partial mem dump, write to the ROOMS.txt file a summary
{
sprintf(fnm,"Reports\\%s","ROOMS.txt");
if (first)
{ DumpLogFile = fopen( fnm, "w" ); // first time clobber the old
if (DumpLogFile)
fprintf(DumpLogFile, "Filename Memory-Used(K) RunningTotal\n");// \tAllocation Calls \n" );
first = 0;
}
else
DumpLogFile = fopen( fnm, "a+" );
if( DumpLogFile)
{ fprintf(DumpLogFile,"%s ",nm);
int len = strlen(nm);
GrandTotal += (UInt32)(normsize+500)/1000;
for(int x=len; x < 25; x++)
fputc(' ',DumpLogFile); // make even columns
fprintf(DumpLogFile,"%5ld K %5ld %s\n",(UInt32)(normsize+500)/1000,GrandTotal,errStr);//, allocs);
fclose(DumpLogFile);
}
}
}
cmbh_last = heap_state.pBlockHeader;
delete ltb;
}
#endif

View File

@ -0,0 +1,251 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsMemoryDefined
#define hsMemoryDefined
#include "hsTypes.h"
//#include "hsTemplates.h"
class HSMemory {
public:
#if HS_BUILD_FOR_MAC
static void BlockMove(const void* src, void* dst, UInt32 length);
#else
static void BlockMove(const void* src, void* dst, UInt32 length);
#endif
static void Clear(void *m, UInt32 byteLen);
static void ClearMemory(void *m, UInt32 byteLen) { HSMemory::Clear(m, byteLen); }
static hsBool EqualBlocks(const void* block1, const void* block2, UInt32 length);
static void* New(UInt32 size);
static void Delete(void* block);
static void* Copy(UInt32 length, const void* source);
static void* SoftNew(UInt32 size); // returns nil if can't allocate
};
///////////////////////////////////////////////////////////////////////////////////////////
class hsAllocator {
public:
virtual void* Alloc(UInt32 size) = 0;
virtual void Free(void* addr) = 0;
};
class hsScratchMem {
enum {
kBufferSize = 32
};
UInt8* fMem;
UInt8 fMemBuffer[kBufferSize];
UInt32 fLength;
public:
hsScratchMem() : fLength(kBufferSize)
{
fMem = fMemBuffer;
}
~hsScratchMem()
{
if (fMem != fMemBuffer)
delete[] fMem;
}
UInt8* GetMem(UInt32 length)
{
if (length > fLength)
{ if (fMem != fMemBuffer)
delete[] fMem;
fMem = TRACKED_NEW UInt8[length];
fLength = length;
}
return fMem;
}
};
class hsChunkAllocator {
enum {
kDefaultChunkSize = 4096
};
UInt32 fChunkSize;
struct hsPrivateChunk* fChunk;
hsDebugCode(UInt32 fChunkCount;)
public:
hsChunkAllocator(UInt32 chunkSize = kDefaultChunkSize);
~hsChunkAllocator();
void Reset();
void SetChunkSize(UInt32 size);
void* Allocate(UInt32 size, const void* data = nil); // throws if fails
void* SoftAllocate(UInt32 size, const void* data = nil); // returns nil if fails
};
///////////////////////////////////////////////////////////////////////////////////////////
class hsAppender {
struct hsAppenderHead* fFirstBlock, *fLastBlock;
UInt32 fElemSize, fElemCount, fCount;
friend class hsAppenderIterator;
public:
hsAppender(UInt32 elemSize, UInt32 minCount = 16);
~hsAppender();
UInt32 ElemSize() const { return fElemSize; }
UInt32 Count() const { return fCount; }
hsBool IsEmpty() const { return fCount == 0; }
void Reset();
UInt32 CopyInto(void* data = nil) const; // return size of data array in bytes
void* PushHead();
void PushHead(const void* data);
void* PushTail();
void PushTail(const void* data);
void PushTail(int count, const void* data); // data[] = count * fElemSize
void* PeekHead() const;
void* PeekTail() const;
hsBool PopHead(void* data = nil);
int PopHead(int count, void* data = nil); // data[] = count * fElemSize
hsBool PopTail(void* data = nil);
// Alternate interfaces
void* Prepend() { return this->PushHead(); }
void* Append() { return this->PushTail(); }
void* Push() { return this->PushHead(); }
void Push(const void* data) { this->PushHead(data); }
hsBool Pop(void* data = nil) { return this->PopHead(data); }
void* Enqueue() { return this->PushTail(); };
void Enqueue(const void* data) { this->PushTail(data); }
void Enqueue(int count, const void* data) { this->PushTail(count, data); }
hsBool Dequeue(void* data = nil) { return this->PopHead(data); }
int Dequeue(int count, void* data = nil) { return this->PopHead(count, data); }
};
class hsAppenderIterator {
const hsAppender* fAppender;
const struct hsAppenderHead* fCurrBlock;
void* fCurrItem;
public:
hsAppenderIterator(const hsAppender* list = nil);
void ResetToHead(const hsAppender* list = nil);
void ResetToTail(const hsAppender* list = nil);
void* Next();
hsBool Next(void* data);
int Next(int count, void* data);
void* Prev();
hsBool Prev(void* data);
// Obsolete interface
void Reset(const hsAppender* list = nil) { this->ResetToHead(list); }
};
///////////////////////////////////////////////////////////////////////////////
template <class T> class hsTAppender : hsAppender {
public:
hsTAppender() : hsAppender(sizeof(T)) {}
hsTAppender(UInt32 minCount) : hsAppender(sizeof(T), minCount) {}
hsAppender* GetAppender() { return this; }
const hsAppender* GetAppender() const { return this; }
UInt32 Count() const { return hsAppender::Count(); }
hsBool IsEmpty() const { return hsAppender::IsEmpty(); }
void Reset() { hsAppender::Reset(); }
UInt32 CopyInto(T copy[]) const { return hsAppender::CopyInto(copy); }
T* PushHead() { return (T*)hsAppender::PushHead(); }
void PushHead(const T& item) { *this->PushHead() = item; }
T* PushTail() { return (T*)hsAppender::PushTail(); }
void PushTail(const T& item) { *this->PushTail() = item; };
void PushTail(int count, const T item[]) { this->hsAppender::PushTail(count, item); };
T* PeekHead() const { return (T*)hsAppender::PeekHead(); }
T* PeekTail() const { return (T*)hsAppender::PeekTail(); }
hsBool PopHead(T* item = nil) { return hsAppender::PopHead(item); }
int PopHead(int count, T item[] = nil) { return hsAppender::PopHead(count, item); }
hsBool PopTail(T* item = nil) { return hsAppender::PopTail(item); }
// Alternate intefaces
T* Prepend() { return this->PushHead(); }
T* Append() { return this->PushTail(); }
void PrependItem(const T& item) { this->PushHead(item); }
void AppendItem(const T& item) { this->PushTail(item); }
T* Push() { return this->PushHead(); }
void Push(const T& item) { this->PushHead(item); }
hsBool Pop(T* item = nil) { return this->PopHead(item); }
T* Enqueue() { return this->PushTail(); };
void Enqueue(const T& item) { this->PushTail(item); }
void Enqueue(int count, const T item[]) { this->PushTail(count, item); }
hsBool Dequeue(T* item = nil) { return this->PopHead(item); }
int Dequeue(int count, T item[] = nil) { return this->PopHead(count, item); }
};
template <class T> class hsTAppenderIterator : hsAppenderIterator {
public:
hsTAppenderIterator() : hsAppenderIterator() {}
hsTAppenderIterator(const hsTAppender<T>* list) : hsAppenderIterator(list->GetAppender()) {}
void ResetToHead() { hsAppenderIterator::ResetToHead(nil); }
void ResetToHead(const hsTAppender<T>* list) { hsAppenderIterator::ResetToHead(list->GetAppender()); }
void ResetToTail() { hsAppenderIterator::ResetToTail(nil); }
void ResetToTail(const hsTAppender<T>* list) { hsAppenderIterator::ResetToTail(list->GetAppender()); }
T* Next() { return (T*)hsAppenderIterator::Next(); }
hsBool Next(T* item) { return hsAppenderIterator::Next(item); }
T* Prev() { return (T*)hsAppenderIterator::Prev(); }
hsBool Prev(T* item) { return hsAppenderIterator::Prev(item); }
// Obsolete interfaces
void Reset() { this->ResetToHead(); }
void Reset(const hsTAppender<T>* list) { this->ResetToHead(list); }
};
#endif

View File

@ -0,0 +1,137 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsPoint2_Defined
#define hsPoint2_Defined
#include "hsScalar.h"
#if __MWERKS__
// This guy disables MetroWerks' desire to only include a file once, which obviously gets
// in the way of our little HS_POINT2.inc trick
#pragma once off
#endif
#define HS_POINT2_NAME hsIntPoint2
#define HS_POINT2_TYPE Int32
#include "HS_POINT2.inc"
};
#define HS_POINT2_NAME hsFixedPoint2
#define HS_POINT2_TYPE hsFixed
#include "HS_POINT2.inc"
hsFixedPoint2& operator=(const hsIntPoint2& src)
{
this->fX = hsIntToFixed(src.fX);
this->fY = hsIntToFixed(src.fY);
return *this;
}
hsFixed Magnitude() const { return hsMagnitude32(fX, fY); }
static hsFixed Magnitude(hsFixed x, hsFixed y)
{
return hsMagnitude32(x, y);
}
static hsFixed Distance(const hsFixedPoint2& p1, const hsFixedPoint2& p2)
{
return hsMagnitude32(p2.fX - p1.fX, p2.fY - p1.fY);
}
};
#if HS_CAN_USE_FLOAT
struct hsPolar {
float fRadius;
float fAngle;
};
#define HS_POINT2_NAME hsFloatPoint2
#define HS_POINT2_TYPE float
#include "HS_POINT2.inc"
hsFloatPoint2& operator=(const hsIntPoint2& src)
{
this->fX = float(src.fX);
this->fY = float(src.fY);
return *this;
}
friend hsFloatPoint2 operator*(const hsFloatPoint2& s, float t)
{
hsFloatPoint2 result;
result.Set(s.fX * t, s.fY * t);
return result;
}
friend hsFloatPoint2 operator*(float t, const hsFloatPoint2& s)
{
hsFloatPoint2 result;
result.Set(s.fX * t, s.fY * t);
return result;
}
hsFloatPoint2* Grid(float period);
hsBool CloseEnough(const hsFloatPoint2* p, float tolerance) const;
float Magnitude() const { return hsFloatPoint2::Magnitude(fX, fY); }
float MagnitudeSquared() const { return fX * fX + fY * fY; }
hsPolar* ToPolar(hsPolar* polar) const;
static float Magnitude(float x, float y) { return hsSquareRoot(x * x + y * y); }
static hsScalar Distance(const hsFloatPoint2& p1, const hsFloatPoint2& p2);
static hsFloatPoint2 Average(const hsFloatPoint2& a, const hsFloatPoint2& b)
{
hsFloatPoint2 result;
result.Set((a.fX + b.fX) * float(0.5), (a.fY + b.fY) * float(0.5));
return result;
}
static hsScalar ComputeAngle(const hsFloatPoint2& a, const hsFloatPoint2& b, const hsFloatPoint2& c);
};
#endif
#if HS_SCALAR_IS_FIXED
typedef hsFixedPoint2 hsPoint2;
#else
typedef hsFloatPoint2 hsPoint2;
#endif
#endif // hsPoint2_Defined

View File

@ -0,0 +1,427 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#include "hsQuat.h"
#include "hsMatrix44.h"
#include "hsStream.h"
#include "hsFastMath.h"
//
// Quaternion class.
// For conversion to and from euler angles, see hsEuler.cpp,h.
//
//
// Construct quat from angle (in radians) and axis of rotation
//
hsQuat::hsQuat(hsScalar rad, const hsVector3* axis)
{
// hsAssert(rad >= -hsScalarPI && rad <= hsScalarPI, "Quat: Angle should be between -PI and PI");
fW = hsCosine(rad*0.5f);
hsScalar s = hsSine(rad*0.5f);
fX = axis->fX*s;
fY = axis->fY*s;
fZ = axis->fZ*s;
}
hsQuat hsQuat::Inverse() const
{
hsQuat q2 = Conjugate();
hsScalar msInv = 1.0f/q2.MagnitudeSquared();
return (q2 * msInv);
}
hsPoint3 hsQuat::Rotate(const hsScalarTriple* v) const
{
hsQuat qInv = Inverse();
hsQuat qVec(v->fX, v->fY, v->fZ, 0);
hsQuat t = qInv * qVec;
hsQuat res = (t * (*this));
//hsAssert(hsABS(res.fW)<1e-5, "Error rotating vector");
return hsPoint3(res.fX, res.fY, res.fZ);
}
void hsQuat::SetAngleAxis(const hsScalar rad, const hsVector3 &axis)
{
fW = hsCosine(rad*0.5f);
hsScalar s = hsSine(rad*0.5f);
fX = axis.fX*s;
fY = axis.fY*s;
fZ = axis.fZ*s;
}
//
// Might want to Normalize before calling this
//
void hsQuat::GetAngleAxis(hsScalar *rad, hsVector3 *axis) const
{
hsAssert((fW >= -1) && (fW <= 1), "Invalid acos argument");
hsScalar ac = hsACosine(fW);
*rad = 2.0f * ac;
hsScalar s = hsSine(ac);
if (s != 0.0f)
{
hsScalar invS = 1.0f/s;
axis->Set(fX*invS, fY*invS, fZ*invS);
}
else
axis->Set(0,0,0);
}
//
//
//
hsScalar hsQuat::MagnitudeSquared()
{
return (fX*fX + fY*fY + fZ*fZ + fW*fW);
}
//
//
//
hsScalar hsQuat::Magnitude()
{
return hsSquareRoot(MagnitudeSquared());
}
//
//
//
void hsQuat::Normalize()
{
hsScalar invMag = 1.0f/Magnitude();
fX *= invMag;
fY *= invMag;
fZ *= invMag;
fW *= invMag;
}
//
//
//
void hsQuat::NormalizeIfNeeded()
{
hsScalar magSquared = MagnitudeSquared();
if (magSquared == 1.0f)
return;
hsScalar invMag = 1.0f/hsSquareRoot(magSquared);
fX *= invMag;
fY *= invMag;
fZ *= invMag;
fW *= invMag;
}
//
// This is for a RHS.
// The quat should be normalized first.
//
void hsQuat::MakeMatrix(hsMatrix44 *mat) const
{
// mf horse - this is transpose of both what
// Gems says and what i'm expecting to come
// out of it, so i'm flipping it.
mat->fMap[0][0] = 1.0f - 2.0f*fY*fY - 2.0f*fZ*fZ;
mat->fMap[0][1] = 2.0f*fX*fY - 2.0f*fW*fZ;
mat->fMap[0][2] = 2.0f*fX*fZ + 2.0f*fW*fY;
mat->fMap[0][3] = 0.0f;
mat->fMap[1][0] = 2.0f*fX*fY + 2.0f*fW*fZ;
mat->fMap[1][1] = 1.0f - 2.0f*fX*fX - 2.0f*fZ*fZ;
mat->fMap[1][2] = 2.0f*fY*fZ - 2.0f*fW*fX;
mat->fMap[1][3] = 0.0f;
mat->fMap[2][0] = 2.0f*fX*fZ - 2.0f*fW*fY;
mat->fMap[2][1] = 2.0f*fY*fZ + 2.0f*fW*fX;
mat->fMap[2][2] = 1.0f - 2.0f*fX*fX - 2.0f*fY*fY;
mat->fMap[2][3] = 0.0f;
mat->fMap[3][0] = 0.0f;
mat->fMap[3][1] = 0.0f;
mat->fMap[3][2] = 0.0f;
mat->fMap[3][3] = 1.0f;
#if 0
mat->fMap[0][0] = fW*fW + fX*fX - fY*fY - fZ*fZ;
mat->fMap[1][0] = 2.0f*fX*fY - 2.0f*fW*fZ;
mat->fMap[2][0] = 2.0f*fX*fZ + 2.0f*fW*fY;
mat->fMap[3][0] = 0.0f;
mat->fMap[0][1] = 2.0f*fX*fY + 2.0f*fW*fZ;
mat->fMap[1][1] = fW*fW - fX*fX + fY*fY - fZ*fZ;
mat->fMap[2][1] = 2.0f*fY*fZ - 2.0f*fW*fX;
mat->fMap[3][1] = 0.0f;
mat->fMap[0][2] = 2.0f*fX*fZ - 2.0f*fW*fY;
mat->fMap[1][2] = 2.0f*fY*fZ + 2.0f*fW*fX;
mat->fMap[2][2] = fW*fW - fX*fX - fY*fY + fZ*fZ;
mat->fMap[3][2] = 0.0f;
mat->fMap[0][3] = 0.0f;
mat->fMap[1][3] = 0.0f;
mat->fMap[2][3] = 0.0f;
mat->fMap[3][3] = fW*fW + fX*fX + fY*fY + fZ*fZ;
#endif
mat->NotIdentity();
}
// Binary operators
hsQuat hsQuat::operator-(const hsQuat &in) const
{
return hsQuat(fX-in.fX, fY-in.fY, fZ-in.fZ, fW-in.fW);
}
hsQuat hsQuat::operator+(const hsQuat &in) const
{
return hsQuat(fX+in.fX, fY+in.fY, fZ+in.fZ, fW+in.fW);
}
//
// Return quaternion product (this * in). Note: order is important!
// To combine rotations, use the product (qSecond * qFirst),
// which gives the effect of rotating by qFirst then qSecond.
//
hsQuat hsQuat::operator*(const hsQuat &in) const
{
hsQuat ret;
ret.fW = (fW*in.fW - fX*in.fX - fY*in.fY - fZ*in.fZ);
ret.fX = (fY*in.fZ - in.fY*fZ + fW*in.fX + in.fW*fX);
ret.fY = (fZ*in.fX - in.fZ*fX + fW*in.fY + in.fW*fY);
ret.fZ = (fX*in.fY - in.fX*fY + fW*in.fZ + in.fW*fZ);
return ret;
}
// I/O
void hsQuat::Read(hsStream *stream)
{
fX = stream->ReadSwapFloat();
fY = stream->ReadSwapFloat();
fZ = stream->ReadSwapFloat();
fW = stream->ReadSwapFloat();
}
void hsQuat::Write(hsStream *stream)
{
stream->WriteSwapFloat(fX);
stream->WriteSwapFloat(fY);
stream->WriteSwapFloat(fZ);
stream->WriteSwapFloat(fW);
}
#if 0
//
// Interpolate on a sphere.
//
void hsQuat::SetFromSlerp(hsQuat *q1, hsQuat *q2, hsScalar t)
{
hsAssert(t>=0.0 && t<= 1.0, "Quat slerp param must be between 0 an 1");
hsScalar theta = hsACosine(q1->Dot(*q2));
hsScalar st = hsSine(theta);
assert(st != 0.0);
hsScalar s1 = hsSine(1.0-t)*theta / st;
hsScalar s2 = hsSine(t)*theta / st;
*this = (*q1) * s1 + (*q2) * s2;
}
#else
/*
* Spherical linear interpolation of unit quaternions with spins
*/
#define EPSILON 1.0E-6 /* a tiny number */
void hsQuat::SetFromSlerp(const hsQuat &a, const hsQuat &b, hsScalar alpha, int spin)
// double alpha; /* interpolation parameter (0 to 1) */
// Quaternion *a, *b; /* start and end unit quaternions */
// int spin; /* number of extra spin rotations */
{
hsScalar beta; /* complementary interp parameter */
hsScalar theta; /* angle between A and B */
hsScalar sin_t, cos_t; /* sine, cosine of theta */
hsScalar phi; /* theta plus spins */
int bflip; /* use negation of B? */
/* cosine theta = dot product of A and B */
cos_t = a.Dot(b);
/* if B is on opposite hemisphere from A, use -B instead */
if (cos_t < 0.0)
{
cos_t = -cos_t;
bflip = true;
}
else
bflip = false;
/* if B is (within precision limits) the same as A,
* just linear interpolate between A and B.
* Can't do spins, since we don't know what direction to spin.
*/
if (1.0 - cos_t < EPSILON)
{
beta = 1.0f - alpha;
} else
{ /* normal case */
// hsAssert((cos_t >= -1) && (cos_t <= 1), "Invalid acos argument");
theta = hsACosine(cos_t);
phi = theta + spin * hsScalarPI;
sin_t = hsSine(theta);
hsAssert(sin_t != 0.0, "Invalid sin value in quat slerp");
beta = hsSine(theta - alpha*phi) / sin_t;
alpha = hsSine(alpha*phi) / sin_t;
}
if (bflip)
alpha = -alpha;
/* interpolate */
fX = beta*a.fX + alpha*b.fX;
fY = beta*a.fY + alpha*b.fY;
fZ = beta*a.fZ + alpha*b.fZ;
fW = beta*a.fW + alpha*b.fW;
}
#endif
//
//
//
void hsQuat::SetFromMatrix(const hsMatrix44* mat)
{
hsScalar wSq = 0.25f*(1 + mat->fMap[0][0] + mat->fMap[1][1] + mat->fMap[2][2]);
if (wSq > EPSILON)
{
fW = hsSquareRoot(wSq);
hsScalar iw4 = 1.0f/(4.0f*fW);
fX = (mat->fMap[2][1] - mat->fMap[1][2]) * iw4;
fY = (mat->fMap[0][2] - mat->fMap[2][0]) * iw4;
fZ = (mat->fMap[1][0] - mat->fMap[0][1]) * iw4;
return;
}
fW = 0;
hsScalar xSq = -0.5f*(mat->fMap[1][1] + mat->fMap[2][2]);
if (xSq > EPSILON)
{
fX = hsSquareRoot(xSq);
hsScalar ix2 = 1.0f/(2.0f*fX);
fY = mat->fMap[1][0] * ix2;
fZ = mat->fMap[2][0] * ix2;
return;
}
fX = 0;
hsScalar ySq = 0.5f * (1 - mat->fMap[2][2]);
if (ySq > EPSILON)
{
fY = hsSquareRoot(ySq);
fZ = mat->fMap[2][1] / (2.0f*fY);
return;
}
fY = 0;
fZ = 1;
}
// 9/15/03 - Colin
// Changed to not use hsFastMath::InvSqrt, due to errors occuring at some
// specific angles that caused Havok to blow up.
hsQuat hsQuat::QuatFromMatrix44(const hsMatrix44& mat)
{
/* This algorithm avoids near-zero divides by looking for a large component
* - first w, then x, y, or z. When the trace is greater than zero,
* |w| is greater than 1/2, which is as small as a largest component can be.
* Otherwise, the largest diagonal entry corresponds to the largest of |x|,
* |y|, or |z|, one of which must be larger than |w|, and at least 1/2. */
hsQuat qu;
float tr, s;
const int X = 0;
const int Y = 1;
const int Z = 2;
const int W = 3;
tr = mat.fMap[X][X] + mat.fMap[Y][Y]+ mat.fMap[Z][Z];
if (tr >= 0.0) {
s = float(sqrt(tr + 1.f));
qu.fW = 0.5f * s;
s = 0.5f / s;
qu.fX = (mat.fMap[Z][Y] - mat.fMap[Y][Z]) * s;
qu.fY = (mat.fMap[X][Z] - mat.fMap[Z][X]) * s;
qu.fZ = (mat.fMap[Y][X] - mat.fMap[X][Y]) * s;
} else {
int h = X;
if (mat.fMap[Y][Y] > mat.fMap[X][X])
h = Y;
if (mat.fMap[Z][Z] > mat.fMap[h][h])
h = Z;
switch (h) {
#define caseMacro(i,j,k,I,J,K) \
case I:\
s = float(sqrt( (mat.fMap[I][I] - (mat.fMap[J][J]+mat.fMap[K][K])) + 1.f )); \
qu.i = 0.5f * s; \
s = 0.5f / s; \
qu.j = (mat.fMap[I][J] + mat.fMap[J][I]) * s; \
qu.k = (mat.fMap[K][I] + mat.fMap[I][K]) * s; \
qu.fW = (mat.fMap[K][J] - mat.fMap[J][K]) * s; \
break
caseMacro(fX,fY,fZ,X,Y,Z);
caseMacro(fY,fZ,fX,Y,Z,X);
caseMacro(fZ,fX,fY,Z,X,Y);
}
}
return (qu);
}
hsQuat& hsQuat::SetFromMatrix44(const hsMatrix44& mat)
{
return (*this = QuatFromMatrix44(mat));
}

View File

@ -0,0 +1,116 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HSQUAT_inc
#define HSQUAT_inc
#include "hsGeometry3.h"
struct hsMatrix44;
//
// Quaternion class.
// For conversion to and from euler angles, see hsEuler.cpp,h.
//
class hsQuat {
public:
hsScalar fX,fY,fZ,fW;
// Constructors
hsQuat(){}
hsQuat(hsScalar X, hsScalar Y, hsScalar Z, hsScalar W) :
fX(X), fY(Y), fZ(Z), fW(W) {}
hsQuat(const hsQuat& a) { fX = a.fX; fY = a.fY; fZ = a.fZ; fW = a.fW; }
hsQuat(hsScalar af[4]) { fX = af[0]; fY = af[1]; fZ = af[2]; fW = af[3]; }
hsQuat(hsScalar rad, const hsVector3* axis);
static hsQuat QuatFromMatrix44(const hsMatrix44& mat);
hsQuat& SetFromMatrix44(const hsMatrix44& mat);
void SetFromMatrix(const hsMatrix44 *mat);
void SetFromSlerp(const hsQuat &q1, const hsQuat &q2, hsScalar t, int spin=0);
void Set(hsScalar X, hsScalar Y, hsScalar Z, hsScalar W)
{ fX = X; fY = Y; fZ = Z; fW = W; }
void GetAngleAxis(hsScalar *rad, hsVector3 *axis) const;
void SetAngleAxis(const hsScalar rad, const hsVector3 &axis);
hsPoint3 Rotate(const hsScalarTriple* v) const;
// Access operators
hsScalar& operator[](int i) { return (&fX)[i]; }
const hsScalar& operator[](int i) const { return (&fX)[i]; }
// Unary operators
hsQuat operator-() const { return(hsQuat(-fX,-fY,-fZ,-fW)); }
hsQuat operator+() const { return *this; }
// Comparison
int operator==(const hsQuat& a) const
{ return (fX==a.fX && fY==a.fY && fZ==a.fZ && fW==a.fW); }
void Identity() { fX = fY = fZ = (hsScalar)0.0; fW = (hsScalar) 1.0; }
int IsIdentity() const
{ return (fX==0.0 && fY==0.0 && fZ==0.0 && fW==1.0); }
void Normalize();
void NormalizeIfNeeded();
void MakeMatrix(hsMatrix44 *mat) const;
hsScalar Magnitude();
hsScalar MagnitudeSquared();
hsQuat Conjugate() const
{ return hsQuat(-fX,-fY,-fZ,fW); }
hsQuat Inverse() const;
// Binary operators
hsQuat operator-(const hsQuat&) const;
hsQuat operator+(const hsQuat&) const;
hsQuat operator*(const hsQuat&) const;
hsQuat operator*(hsScalar f) const
{ return hsQuat(fX*f,fY*f,fZ*f,fW*f); }
hsQuat operator/(hsScalar f) const
{ return hsQuat(fX/f,fY/f,fZ/f,fW/f); }
hsQuat operator/(const hsQuat&) const;
hsScalar Dot(const hsQuat &q2) const
{ return (fX*q2.fX + fY*q2.fY + fZ*q2.fZ + fW*q2.fW); }
// I/O
void Read(hsStream *stream);
void Write(hsStream *stream);
};
#endif

View File

@ -0,0 +1,369 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsQueue_Defined
#define hsQueue_Defined
#include "hsTypes.h"
template <class T> class hsQueue {
private:
int fArraySize;
T *fArray;
int fHead; // Index of first element in the queue
int fTail; // Index of next free spot in the queue
int fLook; // Index of look pointer
hsBool fFull; // Is queue full?
hsBool fEmpty; // Is queue empty?
void Inc(int *index);
int Inc(int index);
void Dec(int *index);
int Dec(int index);
public:
hsQueue( int size );
~hsQueue();
hsBool Append(const T &newTail); // Add to end of line
hsBool Remove(const T &someElement); // Find and remove element in the line
hsBool Pop(T *headElement); // Remove and return the head of the line
hsBool StartLook(T *headElement); // Return the head of the line w/out removing it
hsBool NextLook(T *nextElement); // Return the head of the line w/out removing it
hsBool IsEmpty(void) { return fEmpty; }
hsBool IsFull(void) { return fFull; }
};
//
// Constructor
// Allocate array, init head/tail indices
//
template <class T> hsQueue<T>::hsQueue( int size )
{
fArraySize = size;
fArray = TRACKED_NEW T[ size ];
fHead = -1;
fTail = -1;
fLook = -1;
fEmpty = true;
fFull = false;
}
//
// Destructor. free array
//
template <class T> hsQueue<T>::~hsQueue()
{
delete [] fArray;
}
//
// Wrap index on increment
//
template <class T> void hsQueue<T>::Inc( int *index )
{
(*index) ++;
if ((*index) == fArraySize) {
*index = 0;
}
}
//
// Wrap index on increment
//
template <class T> int hsQueue<T>::Inc( int index )
{
(index) ++;
if ((index) == fArraySize) {
index = 0;
}
return index;
}
//
// Wrap index on decrement
//
template <class T> void hsQueue<T>::Dec( int *index )
{
(*index) --;
if ((*index) < 0) {
*index = fArraySize-1;
}
}
//
// Wrap index on decrement
//
template <class T> int hsQueue<T>::Dec( int index )
{
(index) --;
if ((index) < 0) {
index = fArraySize-1;
}
return index;
}
//
// Add copy of item to the array.
//
template <class T> hsBool hsQueue<T>::Append(const T &thing)
{
if (fHead == -1 && fTail == -1) {
// init case
fHead = 0;
fTail = 0;
}
if (fFull) {
// Queue is full
return false;
}
if ( (fHead<0 || fHead>=fArraySize) ) {
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "Append: Illegal head pointer", fHead);
}
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "Append: Illegal tail pointer", fTail);
// Copy
fArray[fTail] = thing;
fEmpty = false;
// increment tail pointer
Inc(&fTail);
if (fTail == fHead) {
fFull = true;
}
return true;
}
//
// Get a copy of the head of the array
//
template <class T> hsBool hsQueue<T>::Pop(T *thing)
{
if (fEmpty) {
return false;
}
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "Pop: Illegal head pointer", fHead);
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "Pop: Illegal tail pointer", fTail);
// Copy
*thing = fArray[fHead];
fFull = false;
// Increment head pointer
Inc(&fHead);
if (fHead == fTail) {
fEmpty = true;
}
return true;
}
//
// Remove item from list
//
template <class T> hsBool hsQueue<T>::Remove(const T &thing)
{
if (fEmpty) {
return false;
}
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "Remove: Illegal head pointer", fHead);
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "Remove: Illegal tail pointer", fTail);
// loop through list, find item
int i = fHead;
do {
if (fArray[i] == thing) {
// Found it - now remove it by sliding everything down 1
int j=Inc(i);
while(j!= fTail) {
if (fLook==j)
Dec(&fLook);
fArray[Dec(j)] = fArray[j];
Inc(&j);
}
if (fLook==fTail)
Dec(&fLook);
Dec(&fTail);
if (fTail == fHead) {
fEmpty = true;
}
return true;
}
Inc(&i);
if (i==fTail) {
return false;
}
} while(true);
}
//
// Return pointer to first item in list, without popping it.
// Return false if nothing there.
//
template <class T> hsBool hsQueue<T>::StartLook(T *thing)
{
if (fEmpty) {
return false;
}
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "StartLook: Illegal head pointer", fHead);
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "StartLook: Illegal tail pointer", fTail);
fLook = fHead;
*thing = fArray[fLook];
// inc look pointer
Inc(&fLook);
// success
return true;
}
//
// Return pointer to next item in list, without popping it. Doesn't change head or tail.
// Should be called immediately after StartLook.
// Return false when at end of list.
//
template <class T> hsBool hsQueue<T>::NextLook(T *thing)
{
if (fEmpty || fLook == fTail) {
return false;
}
hsAssert(fLook != -1, "Must call StartLook first\n");
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "NextLook: Illegal head pointer", fHead);
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "NextLook: Illegal tail pointer", fTail);
// Return copy of item without removing it
*thing = fArray[fLook];
Inc(&fLook);
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// Code for threaded message queues - move to another file
//
#ifdef MQUEUE
#include "hsThread.h"
#if HS_BUILD_FOR_UNIX
#include <mqueue.h>
#endif
class hsListQue {
public:
struct Elem {
Elem* fNext;
};
private:
Elem* fHead;
Elem* fTail;
int fCount;
public:
hsListQue();
virtual ~hsListQue();
virtual int Count();
virtual void Enqueue(Elem* newItem);
virtual Elem* Dequeue();
};
class hsMutexQueue : public hsListQue {
hsMutex fMutex;
public:
hsMutexQueue() {}
virtual int Count();
virtual void Enqueue(Elem* newItem);
virtual Elem* Dequeue(); // will return nil if the queue is empty
};
class hsSemaphoreQueue : public hsMutexQueue {
hsSemaphore fSema;
public:
hsSemaphoreQueue() {}
virtual void Enqueue(Elem* newItem);
virtual Elem* Dequeue(); // never returns nil, it just waits
};
class hsMsgQueue {
int fMaxSize;
#if HS_BUILD_FOR_UNIX
mqd_t fMQ;
#else
class hsPrivateMQ* fMQ;
UInt32 fAccess;
#endif
public:
enum {
kRead = 0x0001,
kWrite = 0x0002,
kBlock = 0x0004
};
hsMsgQueue();
virtual ~hsMsgQueue();
hsBool Create(const char name[], int maxSize, UInt32 access);
hsBool Open(const char name[], UInt32 access);
void Close();
int GetMaxSize() const { return fMaxSize; }
hsBool Send(const void* data, int size = 0);
int Receive(void* data); // returns actual size or 0
static void Delete(const char name[]);
};
#endif // MQUEUE
#endif

View File

@ -0,0 +1,67 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsRefCnt_Defiend
#define hsRefCnt_Defiend
class hsRefCnt {
private:
int fRefCnt;
public:
hsRefCnt() : fRefCnt(1) {}
virtual ~hsRefCnt();
virtual int RefCnt() const { return fRefCnt; }
virtual void UnRef();
virtual void Ref();
};
#define hsRefCnt_SafeRef(obj) do { if (obj) (obj)->Ref(); } while (0)
#define hsRefCnt_SafeUnRef(obj) do { if (obj) (obj)->UnRef(); } while (0)
#define hsRefCnt_SafeAssign(dst, src) \
do { \
hsRefCnt_SafeRef(src); \
hsRefCnt_SafeUnRef(dst); \
dst = src; \
} while (0)
#endif

View File

@ -0,0 +1,393 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsSTLStream.h"
hsVectorStream::hsVectorStream() : fEnd(0)
{
}
hsVectorStream::hsVectorStream(UInt32 chunkSize)
{
fVector.reserve(chunkSize);
}
hsVectorStream::~hsVectorStream()
{
}
hsBool hsVectorStream::AtEnd()
{
return (fBytesRead >= fEnd);
}
UInt32 hsVectorStream::Read(UInt32 byteCount, void *buffer)
{
if (fBytesRead + byteCount > fEnd)
{
// hsStatusMessageF("Reading past end of hsVectorStream (read %u of %u requested bytes)", fEnd-fBytesRead, byteCount);
byteCount = fEnd - fBytesRead;
}
memcpy(buffer, &fVector[fBytesRead], byteCount);
fBytesRead += byteCount;
fPosition += byteCount;
return byteCount;
}
UInt32 hsVectorStream::Write(UInt32 byteCount, const void* buffer)
{
// If we are at the end of the vector, we can just do a block insert of the data
if (fPosition == fVector.size())
fVector.insert(fVector.end(), (Byte*)buffer, (Byte*)buffer+byteCount);
// If we are in the middle, I don't know how to just overwrite a block of the vector.
// So, we make sure there is enough space and copy the elements one by one
else
{
fVector.reserve(fPosition+byteCount);
for (UInt32 i = 0; i < byteCount; i++)
fVector[fPosition+i] = ((Byte*)buffer)[i];
}
fPosition += byteCount;
if (fPosition > fEnd)
fEnd = fPosition;
return byteCount;
}
void hsVectorStream::Skip(UInt32 deltaByteCount)
{
fBytesRead += deltaByteCount;
fPosition += deltaByteCount;
}
void hsVectorStream::Rewind()
{
fBytesRead = 0;
fPosition = 0;
}
void hsVectorStream::FastFwd()
{
fBytesRead = fPosition = fEnd;
}
void hsVectorStream::Truncate()
{
fVector.erase(fVector.begin()+fPosition, fVector.end());
fEnd = fPosition-1;
}
UInt32 hsVectorStream::GetEOF()
{
return fEnd;
}
void hsVectorStream::CopyToMem(void* mem)
{
memcpy(mem, &fVector[0], fEnd);
}
void hsVectorStream::Erase(UInt32 bytes)
{
hsAssert(fPosition+bytes <= fEnd, "Erasing past end of stream");
fVector.erase(fVector.begin()+fPosition, fVector.begin()+fPosition+bytes);
fEnd -= bytes;
}
void hsVectorStream::Reset()
{
fBytesRead = 0;
fPosition = 0;
fEnd = 0;
fVector.clear();
}
const void *hsVectorStream::GetData()
{
if (fVector.size() > 0)
return &fVector[0];
else
return nil;
}
/////////////////////////////////////////////////////////////////////////////////////////
#ifdef HS_BUILD_FOR_WIN32
hsNamedPipeStream::hsNamedPipeStream(UInt8 flags, UInt32 timeout) :
fFlags(flags),
fPipe(INVALID_HANDLE_VALUE),
fReadMode(false),
fTimeout(timeout)
{
memset(&fOverlap, 0, sizeof(OVERLAPPED));
fOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
}
hsNamedPipeStream::~hsNamedPipeStream()
{
CloseHandle(fOverlap.hEvent);
fOverlap.hEvent = INVALID_HANDLE_VALUE;
}
hsBool hsNamedPipeStream::WaitForClientConnect()
{
// Look for a client connect (this should return zero since it's overlapped)
BOOL ret = ConnectNamedPipe(fPipe, &fOverlap);
if (ret)
return true;
else
{
switch (GetLastError())
{
// Waiting for client to connect
case ERROR_IO_PENDING:
if (WaitForSingleObject(fOverlap.hEvent, fTimeout) == WAIT_OBJECT_0)
return true;
break;
// Client is already connected
case ERROR_PIPE_CONNECTED:
// if (SetEvent(fOverlap.hEvent))
return true;
break;
}
}
return false;
}
hsBool hsNamedPipeStream::Open(const char *name, const char *mode)
{
wchar* wName = hsStringToWString(name);
wchar* wMode = hsStringToWString(mode);
hsBool ret = Open(wName, wMode);
delete [] wName;
delete [] wMode;
return ret;
}
hsBool hsNamedPipeStream::Open(const wchar *name, const wchar *mode)
{
if (wcschr(mode, L'w'))
{
fReadMode = false;
// Try to create the pipe
fPipe = CreateNamedPipeW(name,
PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE,
1,
1024,
1024,
fTimeout,
NULL);
if (fPipe != INVALID_HANDLE_VALUE)
return true;
}
else if (wcschr(mode, L'r'))
{
fReadMode = true;
fPipe = CreateFileW(name,
GENERIC_READ,
0, // no sharing
NULL, // no security attributes
OPEN_EXISTING, // opens existing pipe
FILE_FLAG_OVERLAPPED, // default attributes
NULL); // no template file
if (fPipe != INVALID_HANDLE_VALUE)
return true;
}
return false;
}
hsBool hsNamedPipeStream::Close()
{
if (fPipe == INVALID_HANDLE_VALUE)
return false;
if (fReadMode)
{
CloseHandle(fPipe); // Close our end of the pipe
fPipe = INVALID_HANDLE_VALUE;
}
else
{
FlushFileBuffers(fPipe); // Make sure the client is done reading
DisconnectNamedPipe(fPipe); // Disconnect the pipe from the client
CloseHandle(fPipe); // Close our end of the pipe
fPipe = INVALID_HANDLE_VALUE;
}
return true;
}
hsBool hsNamedPipeStream::ICheckOverlappedResult(BOOL result, UInt32 &numTransferred)
{
// Read/Write succeeded, return now
if (result)
return true;
// Read failed because the operation is taking a while. Wait for it
else if (GetLastError() == ERROR_IO_PENDING)
{
if (WaitForSingleObject(fOverlap.hEvent, fTimeout) == WAIT_OBJECT_0)
{
BOOL oResult = GetOverlappedResult(fPipe, &fOverlap, &numTransferred, FALSE);
if (oResult)
return true;
hsAssert(oResult, "GetOverlappedResult failed");
}
else
hsAssert(0, "Wait failed");
}
else
hsAssert(0, "Read/Write failed");
return false;
}
hsBool hsNamedPipeStream::IRead(UInt32 byteCount, void *buffer, UInt32 &numRead)
{
numRead = 0;
if (fPipe != INVALID_HANDLE_VALUE && fReadMode)
{
BOOL result = ReadFile(fPipe, buffer, byteCount, &numRead, &fOverlap);
if (ICheckOverlappedResult(result, numRead))
return true;
}
// If we got here, the pipe is probably broken. Throw if it is enabled.
if (fFlags & kThrowOnError)
throw this;
return false;
}
hsBool hsNamedPipeStream::IWrite(UInt32 byteCount, const void *buffer, UInt32 &numWritten)
{
numWritten = 0;
if (fPipe != INVALID_HANDLE_VALUE && !fReadMode)
{
BOOL result = WriteFile(fPipe, buffer, byteCount, &numWritten, &fOverlap);
if (ICheckOverlappedResult(result, numWritten))
return true;
}
// If we got here, the pipe is probably broken. Throw if it is enabled.
if (fFlags & kThrowOnError)
throw this;
return false;
}
UInt32 hsNamedPipeStream::Read(UInt32 byteCount, void *buffer)
{
UInt32 totalRead = 0;
// Read until we get all our data or an error
UInt32 numRead = 0;
while (IRead(byteCount-totalRead, (void*)((UInt32)buffer+totalRead), numRead))
{
totalRead += numRead;
if (totalRead >= byteCount)
return totalRead;
}
return totalRead;
}
UInt32 hsNamedPipeStream::Write(UInt32 byteCount, const void *buffer)
{
UInt32 totalWritten = 0;
// Write until we get all our data or an error
UInt32 numWritten = 0;
while (IWrite(byteCount-totalWritten, (const void*)((UInt32)buffer+totalWritten), numWritten))
{
totalWritten += numWritten;
if (totalWritten >= byteCount)
return totalWritten;
}
return totalWritten;
}
#ifdef __SGI_STL_PORT
using std::min;
#endif
void hsNamedPipeStream::Skip(UInt32 deltaByteCount)
{
char buf[256];
// Read until we get all our data or an error
UInt32 totalRead = 0;
UInt32 numRead = 0;
while (IRead(min((UInt32)256L, deltaByteCount-totalRead), buf, numRead))
{
totalRead += numRead;
if (totalRead >= deltaByteCount)
return;
}
}
void hsNamedPipeStream::Rewind()
{
hsAssert(0, "Rewind not allowed on a pipe");
}
#endif // HS_BUILD_FOR_WIN32

View File

@ -0,0 +1,129 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsStream.h"
#include "hsStlUtils.h"
//
// In-memory only
// Erase function lets you cut a chunk out of the middle of the stream
//
class hsVectorStream : public hsStream
{
protected:
std::vector<Byte> fVector;
UInt32 fEnd; // End of file (one past the last byte)
public:
hsVectorStream();
hsVectorStream(UInt32 chunkSize);
virtual ~hsVectorStream();
virtual hsBool Open(const char *, const char *) { hsAssert(0, "hsVectorStream::Open Not Implemented"); return false; }
virtual hsBool Open(const wchar *, const wchar *) { hsAssert(0, "hsVectorStream::Open Not Implemented"); return false; }
virtual hsBool Close() { hsAssert(0, "hsVectorStream::Close Not Implemented"); return false; }
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void * buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void FastFwd();
virtual void Truncate();
virtual UInt32 GetEOF();
virtual void CopyToMem(void* mem);
virtual void Reset(); // clears the buffers
// Erase number of bytes at the current position
virtual void Erase(UInt32 bytes);
// A pointer to the beginning of the data in the stream. This is only valid
// until someone modifies the stream.
const void *GetData();
// In case you want to try and be efficient with your memory allocations
void Reserve(UInt32 bytes) { fVector.reserve(bytes); }
};
#ifdef HS_BUILD_FOR_WIN32
#include "hsWindows.h"
class hsNamedPipeStream : public hsStream
{
protected:
HANDLE fPipe;
OVERLAPPED fOverlap;
hsBool fReadMode; // True for read, false for write
UInt8 fFlags;
UInt32 fTimeout;
hsBool ICheckOverlappedResult(BOOL result, UInt32 &numTransferred);
hsBool IRead(UInt32 byteCount, void *buffer, UInt32 &numRead);
hsBool IWrite(UInt32 byteCount, const void *buffer, UInt32 &numWritten);
public:
enum { kThrowOnError = 1 }; // Throws if a read or write operation fails
hsNamedPipeStream(UInt8 flags=0, UInt32 timeout=INFINITE);
virtual ~hsNamedPipeStream();
// The server (writer) and client (reader) need to open the same file.
// The format is "\\.\pipe\pipeName". The '.' can be replaced with a
// computer name to do it over the network. 'pipeName' is whatever you
// want.
virtual hsBool Open(const char *name, const char *mode);
virtual hsBool Open(const wchar *name, const wchar *mode);
virtual hsBool Close();
virtual UInt32 Read(UInt32 byteCount, void *buffer);
virtual UInt32 Write(UInt32 byteCount, const void *buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
// - For the server (writer) only -
// After calling open, signal your client to start reading and call this function.
// If a client connects, this will return true and you can start writing. If it
// returns false, close the pipe, it ain't happening.
hsBool WaitForClientConnect();
};
#endif // HS_BUILD_FOR_WIN32

View File

@ -0,0 +1,44 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsSafeRefCnt.h"
hsMutex hsSafeRefCnt::fMutex;

View File

@ -0,0 +1,65 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HS_SAFE_REF_CNT_H
#define HS_SAFE_REF_CNT_H
#include "hsRefCnt.h"
#include "hsThread.h"
//
// Thread Safe RefCounter
//
class hsSafeRefCnt : public hsRefCnt
{
private:
static hsMutex fMutex;
protected:
virtual void IRef() { }
virtual void IUnRef() { };
public:
virtual int RefCnt() const { hsTempMutexLock temp(fMutex); return hsRefCnt::RefCnt(); }
void UnRef() { hsTempMutexLock temp(fMutex); IUnRef(); hsRefCnt::UnRef(); }
void Ref() { hsTempMutexLock temp(fMutex); IRef(); hsRefCnt::Ref(); }
};
#endif //HS_SAFE_REF_CNT_H

View File

@ -0,0 +1,229 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsScalarMacrosDefined
#define hsScalarMacrosDefined
#include "hsFixedTypes.h"
#ifndef HS_SCALAR_IS_FLOAT
#define HS_SCALAR_IS_FIXED 0
#define HS_SCALAR_IS_FLOAT 1
#define HS_NEVER_USE_FLOAT 0
#endif
#if HS_SCALAR_IS_FLOAT && HS_NEVER_USE_FLOAT
#error "can't define HS_SCALAR_IS_FLOAT and HS_NEVER_USE_FLOAT"
#endif
#if HS_SCALAR_IS_FLOAT
#include <math.h>
#endif
#define hsScalarDegToRad(deg) hsScalarMul(deg, hsScalarPI / 180)
#define hsScalarRadToDeg(rad) hsScalarMul(rad, 180 / hsScalarPI)
#if HS_SCALAR_IS_FIXED
typedef hsFixed hsScalar;
#define hsScalar1 hsFixed1
#define hsScalarHalf (hsFixed1 >> 1)
#define hsScalarPI (hsFixedPI)
#define hsScalarMax (0x7fffffff)
#if HS_CAN_USE_FLOAT
#define hsFloatToScalar(x) hsFixed((x) * float(hsFixed1))
#define hsScalarToFloat(x) ((x) / float(hsFixed1))
#endif
#define hsIntToScalar(x) hsIntToFixed(x)
#define hsScalarToInt(x) hsFixedToInt(x)
#define hsScalarRound(x) hsFixedRound(x)
#define hsFixedToScalar(x) (x)
#define hsScalarToFixed(x) (x)
#define hsFractToScalar(x) hsFractToFixed(x)
#define hsScalarToFract(x) hsFixedToFract(x)
#define hsScalarMul(a, b) hsFixMul(a, b)
#define hsScalarMul2(a) ((a) << 1)
#define hsScalarDiv(a, b) hsFixDiv(a, b)
#define hsScalarDiv2(a) ((a) >> 1)
#define hsScalarInvert(a) hsFixDiv(hsFixed1, a)
#define hsScalarMod(a,b) ((a) % (b))
#define hsScalarMulDiv(n1, n2, d) hsMulDiv32(n1, n2, d)
#define hsScalarMulAdd(a, b, c) (hsFixMul(a, b) + (c))
#define hsSquareRoot(scalar) hsFixSqrt(scalar)
#define hsSine(angle) hsFixedSin(angle)
#define hsCosine(angle) hsFixedCos(angle)
#define hsTan(angle) (hsSine(angle)/hsCosine(angle))
#define hsASine(value) hsFixedASin(value)
#define hsACosine(value) hsFixedACos(value)
#ifdef __cplusplus
inline hsScalar hsScalarAverage(hsScalar a, hsScalar b) { return a + b >> 1; }
inline hsScalar hsScalarAverage(hsScalar a, hsScalar b, hsScalar t)
{
return a + hsFixMul(t, b - a);
}
#if HS_CAN_USE_FLOAT
inline hsScalar hsPow(hsScalar base, hsScalar exponent)
{
return hsFloatToScalar(powf(hsScalarToFloat(base), hsScalarToFloat(exponent)));
}
inline hsScalar hsATan2(hsScalar y, hsScalar x)
{
return hsFloatToScalar(atan2f(hsScalarToFloat(y), hsScalarToFloat(x)));
}
#endif
inline hsScalar hsCeil(hsScalar x) { return (x + 0xFFFF) & 0xFFFF0000; }
inline hsScalar hsFloor(hsScalar x) { return x & 0xFFFF0000; }
#endif
#endif
#if HS_SCALAR_IS_FLOAT
typedef float hsScalar;
#define hsScalar1 float(1)
#define hsScalarHalf float(0.5)
#define hsScalarPI float(HS_PI)
#define hsScalarMax float(3.402823466e+38F)
#define hsFloatToScalar(x) float(x)
#define hsScalarToFloat(x) float(x)
#define hsIntToScalar(x) float(x)
#define hsScalarToInt(x) Int32(x)
#define hsFixedToScalar(x) ((hsScalar)(x) / float(hsFixed1))
#define hsScalarToFixed(x) hsFixed((x) * float(hsFixed1))
#define hsFractToScalar(x) ((x) / float(hsFract1))
#define hsScalarToFract(x) hsFract((x) * float(hsFract1))
#ifdef __cplusplus
#define hsScalarMod(a,b) fmodf(a, b)
#define hsScalarMulAdd(a, b, c) ((a) * (b) + (c))
#define hsScalarMul(a,b) ((a) * (b))
#define hsScalarMul2(a) ((a) * 2)
#define hsScalarDiv(a,b) ((a) / (b))
#define hsScalarDiv2(a) ((a) * float(0.5))
#define hsScalarInvert(a) (float(1) / (a))
#define hsScalarMulDiv(n1,n2,d) ((n1) * (n2) / (d))
#ifndef HS_DEBUGGING /* mf horse testing defines vs inlines for VC++5.0 performance */
#define hsScalarRound(x) Int32((x) + ((x) < 0 ? -hsScalarHalf : hsScalarHalf))
#else /* HS_DEBUGGING - use inlines for type-checking etc...and all */
inline Int32 hsScalarRound(float x)
{
float half = hsScalarHalf;
if (x < 0)
half = -half;
return Int32(x + half);
}
#endif /* HS_DEBUGGING - use inlines for type-checking etc...and all */
inline float hsScalarAverage(float a, float b) { return (a + b) * float(0.5); }
inline float hsScalarAverage(float a, float b, float t) { return a + t * (b - a); }
#if (HS_BUILD_FOR_BE || (HS_BUILD_FOR_UNIX && !HS_BUILD_FOR_GCC322))
#define acosf(x) (float)acos(x)
#define asinf(x) (float)asin(x)
#define atanf(x) (float)atan(x)
#define atan2f(x, y) (float)atan2(x, y)
#define ceilf(x) (float)ceil(x)
#define cosf(x) (float)cos(x)
#define coshf(x) (float)cosh(x)
#define expf(x) (float)exp(x)
#define fabsf(x) (float)fabs(x)
#define floorf(x) (float)floor(x)
#define fmodf(x, y) (float)fmod(x, y)
#define logf(x) (float)log(x)
#define log10f(x) (float)log10(x)
#define powf(x, y) (float)pow(x, y)
#define sinf(x) (float)sin(x)
#define sinhf(x) (float)sinh(x)
#define sqrtf(x) (float)sqrt(x)
#define tanf(x) (float)tan(x)
#define tanhf(x) (float)tanh(x)
inline float modff(float x, float* y)
{
double _Di, _Df = modf(x, &_Di);
*y = (float)_Di;
return ((float)_Df);
}
#endif
inline hsScalar hsSquareRoot(hsScalar scalar) { return sqrtf(scalar); }
inline hsScalar hsSine(hsScalar angle) { return sinf(angle); }
inline hsScalar hsCosine(hsScalar angle) { return cosf(angle); }
inline hsScalar hsTan(hsScalar rads) { return tanf(rads); }
inline hsScalar hsASine(hsScalar value) { return asinf(value); }
inline hsScalar hsACosine(hsScalar value) { return acosf(value); }
inline hsScalar hsPow(hsScalar base, hsScalar exponent) { return powf(base, exponent); }
inline hsScalar hsATan2(hsScalar y, hsScalar x) { return atan2f(y, x); }
inline hsScalar hsCeil(hsScalar x) { return ceilf(x); }
inline hsScalar hsFloor(hsScalar x) { return floorf(x); }
#endif /* HS_SCALAR_IS_FLOAT */
#endif /* __CPLUSPLUS */
//
// Macros for enabling double precision math ops
// require #include <float.h>
//
#if HS_BUILD_FOR_WIN32
#define hsDoublePrecBegin \
unsigned int fpc=_controlfp( 0, 0); \
_controlfp( _PC_64, MCW_PC );
#define hsDoublePrecEnd \
_controlfp( fpc, 0xfffff );
#else
#define hsDoublePrecBegin
#define hsDoublePrecEnd
#endif
#endif

View File

@ -0,0 +1,65 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsStlSortUtils_inc
#define hsStlSortUtils_inc
// These get used a lot in char * STL maps, so lets just have them in one place
class stringSorter
{
public:
bool operator() (const char *s1, const char *s2) const
{
return (strcmp(s1,s2) < 0);
}
};
class stringISorter
{
public:
bool operator() (const char *s1, const char *s2) const
{
return (stricmp(s1,s2) < 0);
}
};
#endif // hsStlSortUtils_inc

View File

@ -0,0 +1,447 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsStlUtils.h"
// stl extensions
namespace xtl {
//std::string
std::string & trimleft(std::string & s, const char * charset)
{
s.erase(0, s.find_first_not_of(charset));
return s;
}
std::wstring & trimleft(std::wstring & s, const wchar_t * charset)
{
s.erase(0, s.find_first_not_of(charset));
return s;
}
std::string & trimright(std::string & s, const char * charset)
{
int idx = s.find_last_not_of(charset);
if (std::string::npos == idx)
{
s.erase();
}
else
{
char c = s.at(idx);
s.erase(idx, std::string::npos);
s.append(1, c);
}
return s;
}
std::wstring & trimright(std::wstring & s, const wchar_t * charset)
{
int idx = s.find_last_not_of(charset);
if (std::wstring::npos == idx)
{
s.erase();
}
else
{
wchar_t c = s.at(idx);
s.erase(idx, std::string::npos);
s.append(1, c);
}
return s;
}
std::string & trim(std::string & s, const char * charset)
{
trimleft(s,charset);
trimright(s,charset);
return s;
}
std::wstring & trim(std::wstring & s, const wchar_t * charset)
{
trimleft(s,charset);
trimright(s,charset);
return s;
}
//xtl::istring
xtl::istring & trimleft(xtl::istring & s, const char * charset)
{
s.erase(0, s.find_first_not_of(charset));
return s;
}
xtl::iwstring & trimleft(xtl::iwstring & s, const wchar_t * charset)
{
s.erase(0, s.find_first_not_of(charset));
return s;
}
xtl::istring & trimright(xtl::istring & s, const char * charset)
{
int idx = s.find_last_not_of(charset);
if (xtl::istring::npos == idx)
{
s.erase();
}
else
{
char c = s.at(idx);
s.erase(idx, xtl::istring::npos);
s.append(1, c);
}
return s;
}
xtl::iwstring & trimright(xtl::iwstring & s, const wchar_t * charset)
{
int idx = s.find_last_not_of(charset);
if (xtl::iwstring::npos == idx)
{
s.erase();
}
else
{
wchar_t c = s.at(idx);
s.erase(idx, xtl::iwstring::npos);
s.append(1, c);
}
return s;
}
xtl::istring & trim(xtl::istring & s, const char * charset)
{
trimleft(s,charset);
trimright(s,charset);
return s;
}
xtl::iwstring & trim(xtl::iwstring & s, const wchar_t * charset)
{
trimleft(s,charset);
trimright(s,charset);
return s;
}
// c-string
std::string trim(const char * s, const char * charset)
{
std::string result = s;
trimleft(result,charset);
trimright(result,charset);
return result;
}
std::wstring trim(const wchar_t * s, const wchar_t * charset)
{
std::wstring result = s;
trimleft(result,charset);
trimright(result,charset);
return result;
}
// format
std::string format(const char * fmt, ...)
{
std::string result;
va_list args;
va_start(args,fmt);
formatv(result,fmt,args);
va_end(args);
return result;
}
std::wstring format(const wchar_t * fmt, ...)
{
std::wstring result;
va_list args;
va_start(args,fmt);
formatv(result,fmt,args);
va_end(args);
return result;
}
std::string formatv(const char * fmt, va_list args)
{
std::string result;
formatv( result, fmt, args );
return result;
}
std::wstring formatv(const wchar_t * fmt, va_list args)
{
std::wstring result;
formatv( result, fmt, args );
return result;
}
bool format(std::string & out, const char * fmt, ...)
{
va_list args;
va_start(args,fmt);
bool r = formatv(out,fmt,args);
va_end(args);
return r;
}
bool format(std::wstring & out, const wchar_t * fmt, ...)
{
va_list args;
va_start(args,fmt);
bool r = formatv(out,fmt,args);
va_end(args);
return r;
}
bool formatv(std::string & out, const char * fmt, va_list args)
{
#define kBufSz 2048
char buf[kBufSz];
char * pbuf = buf;
int len = 0;
int attempts = 0;
bool success = false;
const int kMaxAttempts = 40;
do
{
int maxlen = kBufSz*attempts+kBufSz-1;
len = hsVsnprintf(pbuf,maxlen,fmt,args);
attempts++;
success = (len>=0 && len<maxlen);
if (!success)
{
if (pbuf!=buf)
delete [] pbuf;
pbuf = TRACKED_NEW char[kBufSz+kBufSz*attempts];
}
}
while (!success && attempts<kMaxAttempts);
if (success)
{
pbuf[len] = '\0';
out = pbuf;
}
if (success)
{
pbuf[len] = '\0';
out = pbuf;
}
else
{
out = "";
if ( attempts==kMaxAttempts )
{
hsDebugMessage( "xtl::formatv - Max reallocs occurred while formatting string. Result is likely truncated!", 0 );
}
}
if (pbuf!=buf)
delete [] pbuf;
return success;
}
bool formatv(std::wstring & out, const wchar_t * fmt, va_list args)
{
#define kBufSz 2048
wchar_t buf[kBufSz];
wchar_t * pbuf = buf;
int len = 0;
int attempts = 0;
bool success = false;
const int kMaxAttempts = 40;
do
{
int maxlen = kBufSz*attempts+kBufSz-1;
len = hsVsnwprintf(pbuf,maxlen,fmt,args);
attempts++;
success = (len>=0 && len<maxlen);
if (!success)
{
if (pbuf!=buf)
delete [] pbuf;
pbuf = TRACKED_NEW wchar_t[kBufSz+kBufSz*attempts];
}
}
while (!success && attempts<kMaxAttempts);
if (success)
{
pbuf[len] = L'\0';
out = pbuf;
}
if (success)
{
pbuf[len] = L'\0';
out = pbuf;
}
else
{
out = L"";
if ( attempts==kMaxAttempts )
{
hsDebugMessage( "xtl::formatv - Max reallocs occurred while formatting wstring. Result is likely truncated!", 0 );
}
}
if (pbuf!=buf)
delete [] pbuf;
return success;
}
typedef std::vector<std::string> StringVector;
typedef std::vector<std::wstring> WStringVector;
typedef std::list<std::string> StringList;
typedef std::list<std::wstring> WStringList;
typedef std::set<std::string> StringSet;
typedef std::set<std::wstring> WStringSet;
template bool GetStringGroup<StringList>(const std::string& s, StringList& group, char sep);
template bool GetStringGroup<WStringList>(const std::wstring& s, WStringList& group, wchar_t sep);
template bool GetStringGroup<StringVector>(const std::string& s, StringVector& group, char sep);
template bool GetStringGroup<WStringVector>(const std::wstring& s, WStringVector& group, wchar_t sep);
template bool GetStringGroup<StringSet>(const std::string& s, StringSet& group, char sep);
template bool GetStringGroup<WStringSet>(const std::wstring& s, WStringSet& group, wchar_t sep);
template <typename T> bool GetStringGroup(const std::string& s, T& group, char sep)
{
bool ret = false;
std::string::size_type oldpos = 0, newpos = 0;
if (!(s.empty()))
{
do
{
newpos = s.find(',',oldpos);
group.insert(group.end(),s.substr(oldpos,newpos));
if (newpos != s.npos)
oldpos = newpos+1;
}
while(newpos != s.npos);
ret = true;
}
return ret;
}
template <typename T> bool GetStringGroup(const std::wstring& s, T& group, wchar_t sep)
{
bool ret = false;
std::wstring::size_type oldpos = 0, newpos = 0;
if (!(s.empty()))
{
do
{
newpos = s.find(L',',oldpos);
group.insert(group.end(),s.substr(oldpos,newpos));
if (newpos != s.npos)
oldpos = newpos+1;
} while(newpos != s.npos);
ret = true;
}
return ret;
}
template bool GetStringGroupAsString<StringList>(const StringList& group, std::string& s, char sep);
template bool GetStringGroupAsString<WStringList>(const WStringList& group, std::wstring& s, wchar_t sep);
template bool GetStringGroupAsString<StringVector>(const StringVector& group, std::string& s, char sep);
template bool GetStringGroupAsString<WStringVector>(const WStringVector& group, std::wstring& s, wchar_t sep);
template bool GetStringGroupAsString<StringSet>(const StringSet& group, std::string& s, char sep);
template bool GetStringGroupAsString<WStringSet>(const WStringSet& group, std::wstring& s, wchar_t sep);
template <typename T> bool GetStringGroupAsString(const T& group, std::string& s, char sep)
{
typename T::const_iterator it = group.begin();
bool fst = true;
while (it != group.end())
{
if (!fst)
s += ",";
else
fst = false;
s+= (*it).c_str();
it++;
}
return true;
}
template <typename T> bool GetStringGroupAsString(const T& group, std::wstring& s, wchar_t sep)
{
typename T::const_iterator it = group.begin();
bool fst = true;
while (it != group.end())
{
if (!fst)
s += L",";
else
fst = false;
s+= (*it).c_str();
it++;
}
return true;
}
} // namespace std

View File

@ -0,0 +1,389 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsStlUtils_h_inc
#define hsStlUtils_h_inc
#include "hsUtils.h"
#include <xmemory>
#include <functional>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <set>
/*****************************************************************************
*
* derived stl classes that use our heap manager
*
***/
// TEMPLATE CLASS cyallocator
template<class _Ty>
class cyallocator
: public std::_Allocator_base<_Ty>
{ // generic cyallocator for objects of class _Ty
public:
typedef std::_Allocator_base<_Ty> _Mybase;
typedef typename _Mybase::value_type value_type;
typedef value_type _FARQ *pointer;
typedef value_type _FARQ& reference;
typedef const value_type _FARQ *const_pointer;
typedef const value_type _FARQ& const_reference;
typedef _SIZT size_type;
typedef _PDFT difference_type;
template<class _Other>
struct rebind
{ // convert an cyallocator<_Ty> to an cyallocator <_Other>
typedef cyallocator<_Other> other;
};
pointer address(reference _Val) const
{ // return address of mutable _Val
return (&_Val);
}
const_pointer address(const_reference _Val) const
{ // return address of nonmutable _Val
return (&_Val);
}
cyallocator()
{ // construct default cyallocator (do nothing)
}
cyallocator(const cyallocator<_Ty>&)
{ // construct by copying (do nothing)
}
template<class _Other>
cyallocator(const cyallocator<_Other>&)
{ // construct from a related cyallocator (do nothing)
}
template<class _Other>
cyallocator<_Ty>& operator=(const cyallocator<_Other>&)
{ // assign from a related cyallocator (do nothing)
return (*this);
}
void deallocate(pointer _Ptr, size_type)
{ // deallocate object at _Ptr, ignore size
FREE(_Ptr);
}
pointer allocate(size_type _Count)
{ // allocate array of _Count elements
return (pointer)ALLOC(_Count * sizeof(_Ty));
}
pointer allocate(size_type _Count, const void _FARQ *)
{ // allocate array of _Count elements, ignore hint
return (allocate(_Count));
}
void construct(pointer _Ptr, const _Ty& _Val)
{ // construct object at _Ptr with value _Val
std::_Construct(_Ptr, _Val);
}
void destroy(pointer _Ptr)
{ // destroy object at _Ptr
std::_Destroy(_Ptr);
}
_SIZT max_size() const
{ // estimate maximum array size
_SIZT _Count = (_SIZT)(-1) / sizeof (_Ty);
return (0 < _Count ? _Count : 1);
}
};
// cyallocator TEMPLATE OPERATORS
template<class _Ty,
class _Other> inline
bool operator==(const cyallocator<_Ty>&, const cyallocator<_Other>&)
{ // test for cyallocator equality (always true)
return (true);
}
template<class _Ty,
class _Other> inline
bool operator!=(const cyallocator<_Ty>&, const cyallocator<_Other>&)
{ // test for cyallocator inequality (always false)
return (false);
}
// CLASS cyallocator<void>
template<> class _CRTIMP2 cyallocator<void>
{ // generic cyallocator for type void
public:
typedef void _Ty;
typedef _Ty _FARQ *pointer;
typedef const _Ty _FARQ *const_pointer;
typedef _Ty value_type;
template<class _Other>
struct rebind
{ // convert an cyallocator<void> to an cyallocator <_Other>
typedef cyallocator<_Other> other;
};
cyallocator()
{ // construct default cyallocator (do nothing)
}
cyallocator(const cyallocator<_Ty>&)
{ // construct by copying (do nothing)
}
template<class _Other>
cyallocator(const cyallocator<_Other>&)
{ // construct from related cyallocator (do nothing)
}
template<class _Other>
cyallocator<_Ty>& operator=(const cyallocator<_Other>&)
{ // assign from a related cyallocator (do nothing)
return (*this);
}
};
/*****************************************************************************
*
* Drop-in replacements for stl classes. Uses our allocator instead of the default one.
*
***/
typedef std::basic_string<char, std::char_traits<char>, cyallocator<char> > cystring;
typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, cyallocator<wchar_t> > cywstring;
// cyistring and cyiwstring declared later in this file
// TEMPLATE CLASS cyvector
template<class _Ty>
class cyvector : public std::vector<_Ty, cyallocator<_Ty> > {
};
// TEMPLATE CLASS cymap
template<class _Kty, class _Ty, class _Pr=std::less<_Kty> >
class cymap : public std::map<_Kty, _Ty, _Pr, cyallocator<std::pair<_Kty, _Ty > > > {
};
// TEMPLATE CLASS cylist
template<class _Ty>
class cylist : public std::list<_Ty, cyallocator<_Ty> > {
};
// TEMPLATE CLASS cyset
template<class _Kty, class _Pr = std::less<_Kty> >
class cyset : public std::set<_Kty, _Pr, cyallocator< _Kty > > {
};
/*****************************************************************************
*
* stl extensions
*
***/
namespace xtl
{
// Why oh why doesn't stl have copy_if?
// See Effective STL [Meyers 2001] Item 36.
template< typename InIt, typename OutIt, typename Pred >
OutIt copy_if( InIt srcBegin, InIt srcEnd, OutIt dstBegin, Pred pred )
{
while ( srcBegin!=srcEnd )
{
if ( pred( *srcBegin ) )
*dstBegin++ = *srcBegin;
++srcBegin;
}
return dstBegin;
}
// useful when clearing a vector/list/set of pointers that need to be deleted.
// use like:
// std::vector<foo*> vec;
// std::for_each(vec.begin(),vec.end(),xtl::delete_ptr());
// vec.clear();
struct delete_ptr
{
template< class T > void operator()( T * p ) const { delete p;}
};
// useful when clearing a map of pointers that need to be deleted.
// use like:
// typedef std::map<int,foo*> foomap;
// foomap m;
// std::for_each(m.begin(),m.end(),xtl::delete_map_ptr_T<foomap>());
// m.clear();
template< class A >
struct delete_map_ptr_T
{
void operator()( typename A::value_type & pair ) const { delete pair.second;}
};
// case insensitive string comparer
// useful in maps that use strings
struct stricmp_less : public std::binary_function<std::string, std::string, bool>
{
bool operator()(const std::string & _X, const std::string & _Y) const
{return ( _stricmp(_X.c_str(),_Y.c_str()) < 0); }
};
struct wstricmp_less : public std::binary_function<std::wstring, std::wstring, bool>
{
bool operator()(const std::wstring & _X, const std::wstring & _Y) const
{return ( _wcsicmp(_X.c_str(),_Y.c_str()) < 0); }
};
// struct stricmp_char_traits
// case insensitive char_traits. used in creating istring class below
#ifdef __SGI_STL_PORT
struct stricmp_char_traits : public __std_alias::char_traits< char >
#else
struct stricmp_char_traits : public std::char_traits< char >
#endif
{
static int compare(const char * A, const char * B, size_t N)
{
for (size_t I=0; I<N; ++I, ++A,++B)
if (tolower(*A)!=tolower(*B))
return (lt(tolower(*A),tolower(*B))?-1:+1);
return (0);
}
static const char * find(const char * S, size_t N, const char & C)
{
char c = tolower(C);
for (; 0<N; --N, ++S)
if (c==tolower(*S))
return S;
return NULL;
}
};
#ifdef __SGI_STL_PORT
struct wstricmp_char_traits : public __std_alias::char_traits< wchar_t >
#else
struct wstricmp_char_traits : public std::char_traits< wchar_t >
#endif
{
static int compare(const wchar_t * A, const wchar_t * B, size_t N)
{
for (size_t I=0; I<N; ++I, ++A,++B)
if (tolower(*A)!=tolower(*B))
return (lt(tolower(*A),tolower(*B))?-1:+1);
return (0);
}
static const wchar_t * find(const wchar_t * S, size_t N, const wchar_t & C)
{
wchar_t c = tolower(C);
for (; 0<N; --N, ++S)
if (c==tolower(*S))
return S;
return NULL;
}
};
// class istring
// A string with case insensitive char_traits.
// Calls to its find* methods are case insensitive.
typedef std::basic_string<char, stricmp_char_traits> istring;
typedef std::basic_string<wchar_t, wstricmp_char_traits> iwstring;
// cyallocator version of istring
typedef std::basic_string<char, stricmp_char_traits, cyallocator<char> > cyistring;
typedef std::basic_string<wchar_t, wstricmp_char_traits, cyallocator<wchar_t> > cyiwstring;
// std::string trim
std::string & trimleft(std::string & s, const char * charset=" \t\n\r");
std::wstring & trimleft(std::wstring & s, const wchar_t * charset=L" \t\n\r");
std::string & trimright(std::string & s, const char * charset=" \t\n\r");
std::wstring & trimright(std::wstring & s, const wchar_t * charset=L" \t\n\r");
std::string & trim(std::string & s, const char * charset=" \t\n\r");
std::wstring & trim(std::wstring & s, const wchar_t * charset=L" \t\n\r");
// xtl::istring trim
xtl::istring & trimleft(xtl::istring & s, const char * charset=" \t\n\r");
xtl::iwstring & trimleft(xtl::iwstring & s, const wchar_t * charset=L" \t\n\r");
xtl::istring & trimright(xtl::istring & s, const char * charset=" \t\n\r");
xtl::iwstring & trimright(xtl::iwstring & s, const wchar_t * charset=L" \t\n\r");
xtl::istring & trim(xtl::istring & s, const char * charset=" \t\n\r");
xtl::iwstring & trim(xtl::iwstring & s, const wchar_t * charset=L" \t\n\r");
// c-string trim
std::string trim(const char * s, const char * charset=" \t\n\r");
std::wstring trim(const wchar_t * s, const wchar_t * charset=L" \t\n\r");
// format
std::string format(const char * fmt, ...);
std::wstring format(const wchar_t * fmt, ...);
std::string formatv(const char * fmt, va_list args);
std::wstring formatv(const wchar_t * fmt, va_list args);
bool format(std::string & out, const char * fmt, ...);
bool format(std::wstring & out, const wchar_t * fmt, ...);
bool formatv(std::string & out, const char * fmt, va_list args);
bool formatv(std::wstring & out, const wchar_t * fmt, va_list args);
template <typename T> bool GetStringGroup(const std::string& s, T& group, char sep = ',');
template <typename T> bool GetStringGroup(const std::wstring& s, T& group, wchar_t sep = L',');
template <typename T> bool GetStringGroupAsString(const T& group, std::string& s, char sep = ',');
template <typename T> bool GetStringGroupAsString(const T& group, std::wstring& s, wchar_t sep = L',');
} // namespace xtd
#endif // hsStlUtils_h_inc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,584 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsStream_Defined
#define hsStream_Defined
#include <stdarg.h> // Included for GCC 3.2.2+
#include "hsTypes.h"
#include "hsMemory.h"
namespace hsPackFileSys {
struct FileEntry;
}
// Define this for use of Streams with Logging (commonly used w/ a packet sniffer)
// These streams log their reads to an event list
//#define STREAM_LOGGER
#ifndef STREAM_LOGGER
#define hsReadOnlyLoggingStream hsReadOnlyStream
#define LogRead(byteCount, buffer, desc) Read(byteCount, buffer)
#define LogReadSafeString() ReadSafeString();
#define LogReadSafeStringLong() ReadSafeStringLong();
#define LogSkip(deltaByteCount, desc) Skip(deltaByteCount)
#define LogReadSwap(value, desc) ReadSwap(value)
#define LogReadSwapArray(count, values, desc) ReadSwap(count, values)
#define LogSubStreamStart(desc) LogVoidFunc()
#define LogSubStreamPushDesc(desc) LogVoidFunc()
#define LogSubStreamEnd() LogVoidFunc()
#define LogStringString(s) LogVoidFunc()
#endif
class hsStream {
public:
enum {
kEolnCode = '\n',
kComment = '#'
};
enum VDB_Type {// Virtual Database type
kVDB_GroupObject,
kVDB_Mesh
};
protected:
UInt32 fBytesRead;
UInt32 fPosition;
hsBool IsTokenSeparator(char c);
public:
hsStream() : fBytesRead(0), fPosition(0) {}
virtual ~hsStream();
virtual hsBool Open(const char *, const char * = "rb")=0;
virtual hsBool Open(const wchar *, const wchar * = L"rb")=0;
virtual hsBool Close()=0;
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void * buffer) = 0;
virtual UInt32 Write(UInt32 byteCount, const void* buffer) = 0;
virtual void Skip(UInt32 deltaByteCount) = 0;
virtual void Rewind() = 0;
virtual void FastFwd();
virtual UInt32 GetPosition() const;
virtual void SetPosition(UInt32 position);
virtual void Truncate();
virtual void Flush() {}
#ifdef STREAM_LOGGER
// Logging Reads & Skips
virtual UInt32 LogRead(UInt32 byteCount, void * buffer, const char* desc) { return Read(byteCount,buffer); }
virtual char* LogReadSafeString() { return ReadSafeString(); }
virtual char* LogReadSafeStringLong() { return ReadSafeStringLong(); }
virtual void LogSkip(UInt32 deltaByteCount, const char* desc) { Skip(deltaByteCount); }
// Stream Notes for Logging
virtual void LogStringString(const char* s) { }
virtual void LogSubStreamStart(const char* desc) { }
virtual void LogSubStreamEnd() { }
virtual void LogSubStreamPushDesc(const char* desc) { }
#endif
void LogVoidFunc() { }
// Optimization for small Reads
virtual UInt8 ReadByte();
virtual hsBool Read4Bytes(void *buffer); // Reads 4 bytes, return true if success
virtual hsBool Read8Bytes(void *buffer); // Reads 8 bytes, return true if success
virtual hsBool Read12Bytes(void *buffer); // Reads 12 bytes, return true if success
virtual UInt32 GetEOF();
UInt32 GetSizeLeft();
virtual void CopyToMem(void* mem);
virtual hsBool IsCompressed() { return false; }
UInt32 WriteString(const char cstring[]);
UInt32 WriteFmt(const char * fmt, ...);
UInt32 WriteFmtV(const char * fmt, va_list av);
UInt32 WriteSafeStringLong(const char *string); // uses 4 bytes for length
UInt32 WriteSafeWStringLong(const wchar_t *string);
char * ReadSafeStringLong();
wchar_t * ReadSafeWStringLong();
UInt32 WriteSafeString(const char *string); // uses 2 bytes for length
UInt32 WriteSafeWString(const wchar_t *string);
char * ReadSafeString();
wchar_t * ReadSafeWString();
hsBool GetToken(char *s, UInt32 maxLen=UInt32(-1), const char beginComment=kComment, const char endComment=kEolnCode);
hsBool ReadLn(char* s, UInt32 maxLen=UInt32(-1), const char beginComment=kComment, const char endComment=kEolnCode);
bool Readbool();
hsBool ReadBool();
void ReadBool(int count, hsBool values[]);
UInt16 ReadSwap16();
void ReadSwap16(int count, UInt16 values[]);
UInt32 ReadSwap32();
void ReadSwap32(int count, UInt32 values[]);
UInt32 ReadUnswap32();
void Writebool(bool value);
void WriteBool(hsBool value);
void WriteBool(int count, const hsBool values[]);
void WriteByte(UInt8 value);
void WriteSwap16(UInt16 value);
void WriteSwap16(int count, const UInt16 values[]);
void WriteSwap32(UInt32 value);
void WriteSwap32(int count, const UInt32 values[]);
void WriteUnswap32(UInt32 value);
/* Overloaded Begin (8 & 16 & 32 int)*/
/* yes, swapping an 8 bit value does nothing, just useful*/
void ReadSwap(bool* value) { *value = this->ReadByte() ? true : false; }
void ReadSwap(UInt8* value) { *value = this->ReadByte(); }
void ReadSwap(int count, UInt8 values[]) { this->Read(count, values); }
void ReadSwap(UInt16* value) { *value = this->ReadSwap16(); }
void ReadSwap(int count, UInt16 values[]) { this->ReadSwap16(count, values); }
void ReadSwap(UInt32* value) { *value = this->ReadSwap32(); }
void ReadSwap(int count, UInt32 values[]) { this->ReadSwap32(count, values); }
#ifdef STREAM_LOGGER
// Begin LogReadSwaps
virtual void LogReadSwap(bool* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwap(UInt8* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwapArray(int count, UInt8 values[], const char* desc) { this->ReadSwap(count, values); }
virtual void LogReadSwap(UInt16* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwapArray(int count, UInt16 values[], const char* desc) { this->ReadSwap(count, values); }
virtual void LogReadSwap(UInt32* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwapArray(int count, UInt32 values[], const char* desc) { this->ReadSwap(count, values); }
// End LogReadSwaps
#endif
void WriteSwap(bool value) { this->Write(1,&value); }
void WriteSwap(UInt8 value) { this->Write(1,&value); }
void WriteSwap(int count, const UInt8 values[]) { this->Write(count, values); }
void WriteSwap(UInt16 value) { this->WriteSwap16(value); }
void WriteSwap(int count, const UInt16 values[]) { this->WriteSwap16(count, values); }
void WriteSwap(UInt32 value) { this->WriteSwap32(value); }
void WriteSwap(int count, const UInt32 values[]) { this->WriteSwap32(count, values); }
void ReadSwap(Int8* value) { *value = this->ReadByte(); }
void ReadSwap(int count, Int8 values[]) { this->Read(count, values); }
void ReadSwap(char* value) { *value = (char)this->ReadByte(); }
void ReadSwap(int count, char values[]) { this->Read(count, values); }
void ReadSwap(Int16* value) { *value = (Int16)this->ReadSwap16(); }
void ReadSwap(int count, Int16 values[]) { this->ReadSwap16(count, (UInt16*)values); }
void ReadSwap(Int32* value) { *value = (Int32)this->ReadSwap32(); }
void ReadSwap(int count, Int32 values[]) { this->ReadSwap32(count, (UInt32*)values); }
void ReadSwap(int* value) { *value = (Int32)this->ReadSwap32(); }
void ReadSwap(int count, int values[]) { this->ReadSwap32(count, (UInt32*)values); }
#ifdef STREAM_LOGGER
// Begin LogReadSwaps
virtual void LogReadSwap(Int8* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwapArray(int count, Int8 values[], const char* desc) { this->ReadSwap(count, values); }
virtual void LogReadSwap(char* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwapArray(int count, char values[], const char* desc) { this->ReadSwap(count, values); }
virtual void LogReadSwap(Int16* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwapArray(int count, Int16 values[], const char* desc) { this->ReadSwap(count, (UInt16*)values); }
virtual void LogReadSwap(Int32* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwapArray(int count, Int32 values[], const char* desc) { this->ReadSwap(count, (UInt32*)values); }
virtual void LogReadSwap(int* value, const char* desc) { this->ReadSwap(value); }
virtual void LogReadSwapArray(int count, int values[], const char* desc) { this->ReadSwap(count, (UInt32*)values); }
// End LogReadSwaps
#endif
void WriteSwap(Int8 value) { this->Write(1,&value); }
void WriteSwap(int count, const Int8 values[]) { this->Write(count, values); }
void WriteSwap(char value) { this->Write(1,(UInt8*)&value); }
void WriteSwap(int count, const char values[]) { this->Write(count, (UInt8*)values); }
void WriteSwap(Int16 value) { this->WriteSwap16((UInt16)value); }
void WriteSwap(int count, const Int16 values[]) { this->WriteSwap16(count, (UInt16*)values); }
void WriteSwap(Int32 value) { this->WriteSwap32((UInt32)value); }
void WriteSwap(int count, const Int32 values[]) { this->WriteSwap32(count, (UInt32*)values); }
void WriteSwap(int value) { this->WriteSwap32((UInt32)value); }
void WriteSwap(int count, const int values[]) { this->WriteSwap32(count, (UInt32*)values); }
/* Overloaded End */
#if HS_CAN_USE_FLOAT
float ReadSwapFloat();
void ReadSwapFloat(int count, float values[]);
double ReadSwapDouble();
void ReadSwapDouble(int count, double values[]);
float ReadUnswapFloat();
void WriteSwapFloat(float value);
void WriteSwapFloat(int count, const float values[]);
void WriteSwapDouble(double value);
void WriteSwapDouble(int count, const double values[]);
void WriteUnswapFloat(float value);
/* Overloaded Begin (Float)*/
void ReadSwap(float* value) { *value = ReadSwapFloat(); }
void ReadSwap(int count, float values[]) { ReadSwapFloat(count, values); }
void ReadSwap(double* value) { *value = ReadSwapDouble(); }
void ReadSwap(int count, double values[]) { ReadSwapDouble(count, values); }
#ifdef STREAM_LOGGER
// Begin LogReadSwaps
virtual void LogReadSwap(float* value, const char* desc) { ReadSwap(value); }
virtual void LogReadSwapArray(int count, float values[], const char* desc) { ReadSwap(count, values); }
virtual void LogReadSwap(double* value, const char* desc) { ReadSwap(value); }
virtual void LogReadSwapArray(int count, double values[], const char* desc) { ReadSwap(count, values); }
// End LogReadSwaps
#endif
void WriteSwap(float value) { WriteSwapFloat(value); }
void WriteSwap(int count, const float values[]) { WriteSwapFloat(count, values); }
void WriteSwap(double value) { WriteSwapDouble(value); }
void WriteSwap(int count, const double values[]) { WriteSwapDouble(count, values); }
/* Overloaded End */
#endif
#if HS_SCALAR_IS_FIXED
hsFixed ReadSwapScalar() { return (hsFixed)this->ReadSwap32(); }
void ReadSwapScalar(int count, hsFixed values[])
{
this->ReadSwap32(count, (UInt32*)values);
}
hsFixed ReadUnswapScalar() { return (hsFixed)this->ReadUnswap32(); }
void WriteSwapScalar(hsFixed value) { this->WriteSwap32(value); }
void WriteSwapScalar(int count, const hsFixed values[])
{
this->WriteSwap32(count, (UInt32*)values);
}
void WriteUnswapScalar(hsFixed value) { this->WriteUnswap32(value); }
/* Overloaded Begin (Scalar) */
void ReadSwap(hsFixed* value) { this->ReadSwap((UInt32*)value); }
void ReadSwap(int count, hsFixed values[]) { this->ReadSwap(count, (UInt32*)values); }
void WriteSwap(hsFixed value) { this->WriteSwap((UInt32)value); }
void WriteSwap(int count, const hsFixed values[]) { this->WriteSwap(count, (UInt32*)values); }
/* Overloaded End */
#else
float ReadSwapScalar() { return (float)this->ReadSwapFloat(); }
void ReadSwapScalar(int count, float values[])
{
this->ReadSwapFloat(count, (float*)values);
}
float ReadUnswapScalar() { return (float)this->ReadUnswapFloat(); }
void WriteSwapScalar(float value) { this->WriteSwapFloat(value); }
void WriteSwapScalar(int count, const float values[])
{
this->WriteSwapFloat(count, (float*)values);
}
void WriteUnswapScalar(float value) { this->WriteUnswapFloat(value); }
#endif
void WriteSwapAtom(UInt32 tag, UInt32 size);
UInt32 ReadSwapAtom(UInt32* size);
/* Overloaded Begin (Atom)*/
void WriteSwap(UInt32* tag, UInt32 size) { WriteSwapAtom(*tag, size); }
void ReadSwap(UInt32* tag, UInt32 *size) { *tag = ReadSwapAtom(size); }
/* Overloaded End */
virtual void VirtualSetPosition(UInt32 pos, VDB_Type ){ SetPosition(pos); };
virtual hsPackFileSys::FileEntry *GetFileEntry() { return nil; } // Streams from Packfiles can return a FileEntry
};
class hsStreamable {
public:
virtual void Read(hsStream* stream) = 0;
virtual void Write(hsStream* stream) = 0;
virtual UInt32 GetStreamSize() = 0;
};
class hsFileStream: public hsStream
{
UInt32 fRef;
#if HS_BUILD_FOR_PS2
enum {
kBufferSize = 2*1024
};
UInt32 fFileSize;
char fBuffer[kBufferSize];
Int32 fVirtualFilePointer;
Int32 fBufferBase; // offset to top of fBuffer
hsBool fBufferIsEmpty;
hsBool fWriteBufferUsed; // In write mode. fBuffer must be flush, when file was closed.
#endif
public:
hsFileStream();
virtual ~hsFileStream();
virtual hsBool Open(const char *name, const char *mode = "rb");
virtual hsBool Open(const wchar *name, const wchar *mode = L"rb");
virtual hsBool Close();
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void* buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void Truncate();
virtual UInt32 GetFileRef();
virtual void SetFileRef(UInt32 refNum);
};
#if !HS_BUILD_FOR_PS2
#if !(HS_BUILD_FOR_REFERENCE)
class hsUNIXStream: public hsStream
{
FILE* fRef;
char* fBuff;
public:
hsUNIXStream(): fRef(0), fBuff(nil) {}
~hsUNIXStream();
virtual hsBool Open(const char* name, const char* mode = "rb");
virtual hsBool Open(const wchar *name, const wchar *mode = L"rb");
virtual hsBool Close();
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void* buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void SetPosition(UInt32 position);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void FastFwd();
virtual void Truncate();
virtual void Flush();
FILE* GetFILE() { return fRef; }
void SetFILE(FILE* file) { fRef = file; }
virtual UInt32 GetEOF();
};
// Small substream class: give it a base stream, an offset and a length, and it'll
// treat all ops as if you had a chunk from the base stream as a separate, vanilla
// stream of the given length.
class plReadOnlySubStream: public hsStream
{
hsStream *fBase;
UInt32 fOffset, fLength;
void IFixPosition( void );
public:
plReadOnlySubStream(): fBase( nil ), fOffset( 0 ), fLength( 0 ) {}
~plReadOnlySubStream();
virtual hsBool Open(const char *, const char *) { hsAssert(0, "plReadOnlySubStream::Open NotImplemented"); return false; }
virtual hsBool Open(const wchar *, const wchar *) { hsAssert(0, "plReadOnlySubStream::Open NotImplemented"); return false; }
void Open( hsStream *base, UInt32 offset, UInt32 length );
virtual hsBool Close() { fBase = nil; fOffset = 0; fLength = 0; return true; }
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void* buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void FastFwd();
virtual void Truncate();
virtual UInt32 GetEOF();
};
#endif
#endif
class hsRAMStream : public hsStream {
hsAppender fAppender;
hsAppenderIterator fIter;
public:
hsRAMStream();
hsRAMStream(UInt32 chunkSize);
virtual ~hsRAMStream();
virtual hsBool Open(const char *, const char *) { hsAssert(0, "hsRAMStream::Open NotImplemented"); return false; }
virtual hsBool Open(const wchar *, const wchar *) { hsAssert(0, "hsRAMStream::Open NotImplemented"); return false; }
virtual hsBool Close() { hsAssert(0, "hsRAMStream::Close NotImplemented"); return false; }
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void * buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void Truncate();
virtual UInt32 GetEOF();
virtual void CopyToMem(void* mem);
void Reset(); // clears the buffers
};
class hsNullStream : public hsStream {
public:
virtual hsBool Open(const char *, const char *) { return true; }
virtual hsBool Open(const wchar *, const wchar *) { return true; }
virtual hsBool Close() { return true; }
virtual UInt32 Read(UInt32 byteCount, void * buffer); // throw's exception
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void Truncate();
UInt32 GetBytesWritten() const { return fBytesRead; }
void Reset( ) { fBytesRead = 0; }
};
// read only mem stream
class hsReadOnlyStream : public hsStream {
protected:
char* fStart;
char* fData;
char* fStop;
public:
hsReadOnlyStream(int size, const void* data) { Init(size, data); }
hsReadOnlyStream() {}
virtual void Init(int size, const void* data) { fStart=((char*)data); fData=((char*)data); fStop=((char*)data + size); }
virtual hsBool Open(const char *, const char *) { hsAssert(0, "hsReadOnlyStream::Open NotImplemented"); return false; }
virtual hsBool Open(const wchar *, const wchar *) { hsAssert(0, "hsReadOnlyStream::Open NotImplemented"); return false; }
virtual hsBool Close() { hsAssert(0, "hsReadOnlyStream::Close NotImplemented"); return false; }
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void * buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer); // throws exception
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void Truncate();
virtual UInt32 GetBytesRead() const { return fBytesRead; }
virtual UInt32 GetEOF() { return (UInt32)(fStop-fStart); }
virtual void CopyToMem(void* mem);
};
// write only mem stream
class hsWriteOnlyStream : public hsReadOnlyStream {
public:
hsWriteOnlyStream(int size, const void* data) : hsReadOnlyStream(size, data) {}
hsWriteOnlyStream() {}
virtual hsBool Open(const char *, const char *) { hsAssert(0, "hsWriteOnlyStream::Open NotImplemented"); return false; }
virtual hsBool Open(const wchar *, const wchar *) { hsAssert(0, "hsWriteOnlyStream::Open NotImplemented"); return false; }
virtual hsBool Close() { hsAssert(0, "hsWriteOnlyStream::Close NotImplemented"); return false; }
virtual UInt32 Read(UInt32 byteCount, void * buffer); // throws exception
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual UInt32 GetBytesRead() const { return 0; }
virtual UInt32 GetBytesWritten() const { return fBytesRead; }
};
// circular queue stream
class hsQueueStream : public hsStream {
private:
char* fQueue;
UInt32 fReadCursor;
UInt32 fWriteCursor;
UInt32 fSize;
public:
hsQueueStream(Int32 size);
~hsQueueStream();
virtual hsBool Open(const char *, const char *) { hsAssert(0, "hsQueueStream::Open NotImplemented"); return false; }
virtual hsBool Open(const wchar *, const wchar *) { hsAssert(0, "hsQueueStream::Open NotImplemented"); return false; }
virtual hsBool Close() { hsAssert(0, "hsQueueStream::Close NotImplemented"); return false; }
virtual UInt32 Read(UInt32 byteCount, void * buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void FastFwd();
virtual hsBool AtEnd();
UInt32 GetSize() { return fSize; }
const char* GetQueue() { return fQueue; }
UInt32 GetReadCursor() { return fReadCursor; }
UInt32 GetWriteCursor() { return fWriteCursor; }
};
class hsBufferedStream : public hsStream
{
FILE* fRef;
UInt32 fFileSize;
enum { kBufferSize = 2*1024 };
char fBuffer[kBufferSize];
// If the buffer is empty, this is zero. Otherwise it is the size of the
// buffer (if we read a full block), or something less than that if we read
// a partial block at the end of the file.
UInt32 fBufferLen;
hsBool fWriteBufferUsed;
#ifdef HS_DEBUGGING
// For doing statistics on how efficient we are
int fBufferHits, fBufferMisses;
UInt32 fBufferReadIn, fBufferReadOut, fReadDirect, fLastReadPos;
char* fFilename;
const char* fCloseReason;
#endif
public:
hsBufferedStream();
virtual ~hsBufferedStream();
virtual hsBool Open(const char* name, const char* mode = "rb");
virtual hsBool Open(const wchar* name, const wchar* mode = L"rb");
virtual hsBool Close();
virtual hsBool AtEnd();
virtual UInt32 Read(UInt32 byteCount, void* buffer);
virtual UInt32 Write(UInt32 byteCount, const void* buffer);
virtual void Skip(UInt32 deltaByteCount);
virtual void Rewind();
virtual void Truncate();
virtual UInt32 GetEOF();
FILE* GetFileRef();
void SetFileRef(FILE* file);
// Something optional for when we're doing stats. Will log the reason why
// the file was closed. Really just for plRegistryPageNode.
void SetCloseReason(const char* reason)
{
#ifdef HS_DEBUGGING
fCloseReason = reason;
#endif
}
};
#endif

View File

@ -0,0 +1,309 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// hsStringTokenizer.cpp
#include "hsStringTokenizer.h"
#include "hsUtils.h"
// String Tokenizer routines
hsStringTokenizer::hsStringTokenizer(const char *string, const char *seps) :
fQAsTok(true),
fInQuote(false),
fString(nil),
fSeps(nil),
fLastTerminator(nil)
{
Reset(string,seps);
}
hsStringTokenizer::~hsStringTokenizer()
{
delete [] fString;
delete [] fSeps;
}
hsBool hsStringTokenizer::HasMoreTokens()
{
return (*fTok != 0);
}
inline hsBool hsStringTokenizer::IsSep(char c)
{
if (!fQAsTok || !fInQuote)
{
if ( fCheckAlphaNum || !isalnum(c) )
{
for (Int32 i=0; i<fNumSeps; i++)
{
if (fSeps[i] == c)
return true;
}
}
}
if (fQAsTok && c=='\"')
{
fInQuote = !fInQuote;
return true;
}
return false;
}
char *hsStringTokenizer::next()
{
if (*fTok == 0)
return nil;
char *cur = fTok;
while (*fTok != 0 && !IsSep(*fTok))
fTok++;
if (*fTok != 0)
{
fLastRep = *fTok;
fLastTerminator = fTok;
*fTok = 0;
fTok++;
}
while (*fTok != 0 && IsSep(*fTok))
fTok++;
return cur;
}
// Slightly more loop-friendly version of next
hsBool hsStringTokenizer::Next( char *token, UInt32 maxTokLen )
{
char *t = next();
if( t == nil )
return false;
hsStrncpy( token, t, maxTokLen );
return true;
}
// Restores the last character replaced to generate a terminator
void hsStringTokenizer::RestoreLastTerminator( void )
{
if( fLastTerminator != nil )
{
*fLastTerminator = fLastRep;
fLastTerminator = nil;
}
}
void hsStringTokenizer::Reset(const char *string, const char *seps)
{
if (fString)
delete [] fString;
fString = string ? hsStrcpy(string) : nil;
if (fSeps)
delete [] fSeps;
fSeps = seps ? hsStrcpy(seps) : nil;
fNumSeps = fSeps ? strlen(fSeps) : 0;
fCheckAlphaNum = false;
for (Int32 i=0; i<fNumSeps; i++)
{
if (isalnum(fSeps[i]))
{
fCheckAlphaNum=true;
break;
}
}
fTok = fString;
fLastTerminator = nil;
fLastRep = 0;
// don't skip empty fields.
// if (fTok && IsSep(*fTok))
// next();
}
void hsStringTokenizer::ParseQuotes(hsBool qAsTok)
{
fQAsTok = qAsTok;
}
///////////////////////////////////////////////////////////////////////////////
// String Tokenizer routines
hsWStringTokenizer::hsWStringTokenizer(const wchar *string, const wchar *seps) :
fQAsTok(true),
fInQuote(false),
fString(nil),
fSeps(nil),
fLastTerminator(nil)
{
Reset(string,seps);
}
hsWStringTokenizer::~hsWStringTokenizer()
{
delete [] fString;
delete [] fSeps;
}
hsBool hsWStringTokenizer::HasMoreTokens()
{
return (*fTok != L'\0');
}
inline hsBool hsWStringTokenizer::IsSep(wchar c)
{
if (!fQAsTok || !fInQuote)
{
if ( fCheckAlphaNum || !iswalnum(c) )
{
for (Int32 i=0; i<fNumSeps; i++)
{
if (fSeps[i] == c)
return true;
}
}
}
if (fQAsTok && c==L'\"')
{
fInQuote = !fInQuote;
return true;
}
return false;
}
wchar *hsWStringTokenizer::next()
{
if (*fTok == L'\0')
return nil;
wchar *cur = fTok;
while (*fTok != L'\0' && !IsSep(*fTok))
fTok++;
if (*fTok != L'\0')
{
fLastRep = *fTok;
fLastTerminator = fTok;
*fTok = L'\0';
fTok++;
}
while (*fTok != L'\0' && IsSep(*fTok))
fTok++;
return cur;
}
// Slightly more loop-friendly version of next
hsBool hsWStringTokenizer::Next( wchar *token, UInt32 maxTokLen )
{
wchar *t = next();
if( t == nil )
return false;
wcsncpy( token, t, maxTokLen - 1 );
token[maxTokLen - 1] = L'\0';
return true;
}
// Restores the last character replaced to generate a terminator
void hsWStringTokenizer::RestoreLastTerminator( void )
{
if( fLastTerminator != nil )
{
*fLastTerminator = fLastRep;
fLastTerminator = nil;
}
}
void hsWStringTokenizer::Reset(const wchar *string, const wchar *seps)
{
if (fString)
delete [] fString;
if (string)
{
int count = wcslen(string);
fString = TRACKED_NEW(wchar[count + 1]);
wcscpy(fString, string);
fString[count] = L'\0';
}
else
fString = nil;
if (fSeps)
delete [] fSeps;
if (seps)
{
int count = wcslen(seps);
fSeps = TRACKED_NEW(wchar[count + 1]);
wcscpy(fSeps, seps);
fSeps[count] = L'\0';
}
else
fSeps = nil;
fNumSeps = fSeps ? wcslen(fSeps) : 0;
fCheckAlphaNum = false;
for (Int32 i=0; i<fNumSeps; i++)
{
if (iswalnum(fSeps[i]))
{
fCheckAlphaNum=true;
break;
}
}
fTok = fString;
fLastTerminator = nil;
fLastRep = 0;
// don't skip empty fields.
// if (fTok && IsSep(*fTok))
// next();
}
void hsWStringTokenizer::ParseQuotes(hsBool qAsTok)
{
fQAsTok = qAsTok;
}

View File

@ -0,0 +1,110 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
// hsStringTokenizer.h
#ifndef _hsStringTokenizer_Included_
#define _hsStringTokenizer_Included_
#include "hsTypes.h"
class hsStringTokenizer
{
private:
char *fSeps;
char *fTok;
char *fLastTerminator;
char fLastRep;
Int32 fNumSeps;
hsBool fQAsTok;
hsBool fInQuote;
hsBool fCheckAlphaNum;
public:
hsStringTokenizer(const char *string=nil, const char *seps=nil);
~hsStringTokenizer();
char *next();
hsBool Next( char *token, UInt32 maxTokLen );
hsBool HasMoreTokens();
void Reset(const char *string, const char *seps);
void ParseQuotes(hsBool qAsTok);
char *GetRestOfString( void ) const { return fTok; }
char *fString;
void RestoreLastTerminator( void );
private:
hsBool IsSep(char c);
};
class hsWStringTokenizer
{
private:
wchar *fSeps;
wchar *fTok;
wchar *fLastTerminator;
wchar fLastRep;
Int32 fNumSeps;
hsBool fQAsTok;
hsBool fInQuote;
hsBool fCheckAlphaNum;
public:
hsWStringTokenizer(const wchar *string=nil, const wchar *seps=nil);
~hsWStringTokenizer();
wchar *next();
hsBool Next( wchar *token, UInt32 maxTokLen );
hsBool HasMoreTokens();
void Reset(const wchar *string, const wchar *seps);
void ParseQuotes(hsBool qAsTok);
wchar *GetRestOfString( void ) const { return fTok; }
wchar *fString;
void RestoreLastTerminator( void );
private:
hsBool IsSep(wchar c);
};
#endif // _hsStringTokenizer_Included_

View File

@ -0,0 +1,174 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsTempPointer_inc
#define hsTempPointer_inc
#include "hsMemory.h"
#include "hsExceptions.h"
template <class T> class hsTempPointer {
private:
T** fArray;
UInt32 fCurrBlock;
UInt32 fNumBlockAlloc;
UInt32 fCurrElem;
UInt32 fNumElemAlloc;
UInt32 fGrowBy; // def = 0, to double
UInt32 fMinSize; // def = 1
hsTempPointer<T>& operator=(const hsTempPointer<T>&);
void IConsolidate();
void IGrow();
public:
hsTempPointer(UInt32 minSize = 1, UInt32 growBy = 0);
~hsTempPointer();
void Reset();
T* Next();
T* Array(int n);
};
template <class T>
hsTempPointer<T>::~hsTempPointer()
{
int i;
for( i = 0; i <= fCurrBlock; i++ )
delete [] fArray[i];
delete [] fArray;
}
template <class T>
hsTempPointer<T>::hsTempPointer(UInt32 minSize, UInt32 growBy)
{
fGrowBy = growBy;
fMinSize = minSize;
fArray = TRACKED_NEW T*[2];
fNumBlockAlloc = 2;
fCurrBlock = 0;
fArray[fCurrBlock] = TRACKED_NEW T[fMinSize];
fNumElemAlloc = minSize;
fCurrElem = 0;
}
template <class T>
void hsTempPointer<T>::IConsolidate()
{
hsAssert(fCurrBlock > 0, "Shouldn't consolidate when nothing to do");
UInt32 numUsed = fCurrBlock * fNumElemAlloc + fCurrElem;
UInt32 newSize = fNumElemAlloc;
if( !fGrowBy )
{
while( newSize <= numUsed )
newSize <<= 1;
}
else
{
while( newSize <= numUsed )
newSize += fGrowBy;
}
int i;
for( i = 0; i <= fCurrBlock; i++ )
delete [] fArray[i];
fArray[0] = TRACKED_NEW T[newSize];
fNumElemAlloc = newSize;
fCurrElem = 0;
fCurrBlock = 0;
}
template <class T>
void hsTempPointer<T>::IGrow()
{
if( ++fCurrBlock >= fNumBlockAlloc )
{
T** newBlockArray = TRACKED_NEW T*[fNumBlockAlloc <<= 1];
HSMemory::BlockMove(fArray, newBlockArray, fCurrBlock * sizeof(*fArray));
delete [] fArray;
fArray = newBlockArray;
}
fArray[fCurrBlock] = TRACKED_NEW T[fNumElemAlloc];
fCurrElem = 0;
}
template <class T>
T* hsTempPointer<T>::Next()
{
if( fCurrElem >= fNumElemAlloc )
IGrow();
return fArray[fCurrBlock] + fCurrElem++;
}
template <class T>
T* hsTempPointer<T>::Array(int n)
{
// minSize (on constructor) should be greater than max n
hsDebugCode(hsThrowIfBadParam((UInt32)n > (UInt32)fNumElemAlloc);)
if( fCurrElem + n >= fNumElemAlloc )
IGrow();
int idx = fCurrElem;
fCurrElem += n;
return fArray[fCurrBlock] + idx;
}
template <class T>
void hsTempPointer<T>::Reset()
{
if( fCurrBlock > 0 )
IConsolidate();
fCurrElem = 0;
}
#endif // hsTempPointer_inc

View File

@ -0,0 +1,336 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTemplates.h"
#include "hsUtils.h"
////////////////////////////////////////////////////////////////////////////////
//
//hsTempString::hsTempString(KStringFormatConstructor, char * fmt, ...)
//{
// va_list args;
// va_start(args,fmt);
// fStr = hsFormatStrV(fmt,args);
// va_end(args);
//}
//
//hsTempString::hsTempString(KStringFormatVConstructor, char * fmt, va_list args)
//{
// fStr = hsFormatStrV(fmt,args);
//}
//
////////////////////////////////////////////////////////////////////////////////
//void hsTempStringF::Format(char * fmt, ...)
//{
// delete [] fStr;
// va_list args;
// va_start(args,fmt);
// fStr = hsFormatStrV(fmt,args);
// va_end(args);
//}
//
//hsTempStringF::hsTempStringF(char * fmt, ...)
//{
// va_list args;
// va_start(args,fmt);
// fStr = hsFormatStrV(fmt,args);
// va_end(args);
//}
//////////////////////////////////////////////////////////////////////////////
#ifdef HS_DEBUGTARRAY
hsDlistNode *hsDlistNode::fpFirst=0;
hsDlistNode *hsDlistNode::fpLast=0;
UInt32 hsDlistNode::fcreated=0;
UInt32 hsDlistNode::fdestroyed=0;
static int NodeKnt = 0;
void RemoveNode(void *pthing)
{
hsDlistNode * pNode = hsDlistNode::fpFirst;
while (pNode)
{
if (pNode->fpThing == pthing)
{
pNode->RemoveNode();//
delete pNode;
return;
}
pNode = pNode->GetNext();
}
}
void hsDlistNode::AddNode()
{
fcreated++;
if (!fpFirst) fpFirst = this;
fpPrev = fpLast;
if (fpLast)
fpLast->fpNext = this;
fpLast = this;
}
void hsDlistNode::RemoveNode()
{
fdestroyed++;
/*
if (!NodeKnt)
{ fpFirst = 0;
fpLast = 0;
return;
}
*/
if (fpPrev)
fpPrev->fpNext = fpNext;
if (fpNext)
fpNext->fpPrev = fpPrev;
if (this == fpFirst)
fpFirst = fpNext;
if (this == fpLast)
fpLast = fpPrev;
/*
if (NodeKnt == 1)
{
if (fpLast) fpFirst = fpLast;
if (fpFirst) fpLast = fpFirst;
fpFirst->fpNext = 0;
fpFirst->fpPrev = 0;
}
*/
}
void TArrayStats()
{
char *GetTypeName();
char *GetSizeOf();
hsDlistNode * pNode = hsDlistNode::fpFirst;
char fnm[512];
sprintf(fnm,"Reports\\%s.txt","TArray");
FILE * DumpLogFile = fopen( fnm, "w" );
if (!DumpLogFile) return;
int i=0;
int totWaste=0;
int totUse =0;
fprintf(DumpLogFile,"TArray Stats, Total Created: %d, Currently Used %d\n-----------------------\n", hsDlistNode::fcreated , hsDlistNode::fcreated - hsDlistNode::fdestroyed);
int notUsed =0;
int used = 0;
int totCount=0;
while (pNode)
{
i++;
if (pNode->fpThing)
{
if (((hsTArrayBase *)(pNode->fpThing))->fTotalCount)
{
used++;
totCount += ((hsTArrayBase *)(pNode->fpThing))->fUseCount;
int siz = ((hsTArrayBase *)(pNode->fpThing))->GetSizeOf();
int use = ((hsTArrayBase *)(pNode->fpThing))->fUseCount;
int tot = ((hsTArrayBase *)(pNode->fpThing))->fTotalCount;
int waste =0;
waste = (tot - use) * siz;
totUse += (use * siz);
totWaste += waste;
fprintf(DumpLogFile,"[%d] SizeObject %d, Uses %d, Allocs %d, Waste %d\n", i, siz, use, tot, waste);
}
else
notUsed++;
}
pNode = pNode->GetNext();
// if (pNode ==hsDlistNode::fpFirst) // dont loop
}
fprintf(DumpLogFile,"TOTAL use %d, waste %d\n", totUse,totWaste);
fprintf(DumpLogFile,"Empty Ones %d, waste %d\n", notUsed, notUsed * 12 ); // 12 aprox size of TArray
if (used)
fprintf(DumpLogFile,"Average Use %d\n", totCount / used);
fclose(DumpLogFile);
}
void LargeArrayStats()
{
char *GetTypeName();
char *GetSizeOf();
hsDlistNode * pNode = hsDlistNode::fpFirst;
char fnm[512];
sprintf(fnm,"Reports\\%s.txt","TArray");
FILE * DumpLogFile = fopen( fnm, "w" );
if (!DumpLogFile) return;
int i=0;
int totWaste=0;
int totUse =0;
fprintf(DumpLogFile,"TArray Stats, Total Created: %d, Currently Used %d\n-----------------------\n", hsDlistNode::fcreated , hsDlistNode::fcreated - hsDlistNode::fdestroyed);
int notUsed =0;
int used = 0;
int totCount=0;
while (pNode)
{
i++;
if (pNode->fpThing)
{
if (((hsLargeArrayBase *)(pNode->fpThing))->fTotalCount)
{
used++;
totCount += ((hsLargeArrayBase *)(pNode->fpThing))->fUseCount;
int siz = ((hsLargeArrayBase *)(pNode->fpThing))->GetSizeOf();
int use = ((hsLargeArrayBase *)(pNode->fpThing))->fUseCount;
int tot = ((hsLargeArrayBase *)(pNode->fpThing))->fTotalCount;
int waste =0;
waste = (tot - use) * siz;
totUse += (use * siz);
totWaste += waste;
fprintf(DumpLogFile,"[%d] SizeObject %d, Uses %d, Allocs %d, Waste %d\n", i, siz, use, tot, waste);
}
else
notUsed++;
}
pNode = pNode->GetNext();
// if (pNode ==hsDlistNode::fpFirst) // dont loop
}
fprintf(DumpLogFile,"TOTAL use %d, waste %d\n", totUse,totWaste);
fprintf(DumpLogFile,"Empty Ones %d, waste %d\n", notUsed, notUsed * 12 ); // 12 aprox size of TArray
if (used)
fprintf(DumpLogFile,"Average Use %d\n", totCount / used);
fclose(DumpLogFile);
}
char * hsTArrayBase::GetTypeName() { return ""; }
int hsTArrayBase::GetSizeOf(void) { return 0; }
hsTArrayBase::hsTArrayBase():fUseCount(0), fTotalCount(0)
{
self = TRACKED_NEW hsDlistNode(this);
}
hsTArrayBase::~hsTArrayBase()
{
if (self)
{ self->RemoveNode();
delete self;
}
else
RemoveNode(this); // Self got clobbered find it the hard way
}
char * hsLargeArrayBase::GetTypeName() { return ""; }
int hsLargeArrayBase::GetSizeOf(void) { return 0; }
hsLargeArrayBase::hsLargeArrayBase():fUseCount(0), fTotalCount(0)
{
self = TRACKED_NEW hsDlistNode(this);
}
hsLargeArrayBase::~hsLargeArrayBase()
{
if (self)
{ self->RemoveNode();
delete self;
}
else
RemoveNode(this); // Self got clobbered find it the hard way
}
#else
void TArrayStats() {}
void LargeArrayStats() {}
#endif //HS_DEBUGTARRAY
void hsTArrayBase::GrowArraySize(UInt16 newCount)
{
#if 1
if (newCount < 8)
fTotalCount = newCount; // Hey its small don't loose sleep over the copy time
else if( newCount & 0x8000 ) // Hey, its huge, give it half way to maxed out
fTotalCount = newCount + ((0xffff - newCount) >> 1);
else
fTotalCount = newCount + (newCount /2); // Give it Half again as much
#endif
#if 0
do {
fTotalCount <<= 1;
} while (fTotalCount < newCount);
#endif
}
void hsLargeArrayBase::GrowArraySize(UInt32 newCount)
{
#if 1
if (newCount < 8)
fTotalCount = newCount; // Hey its small don't loose sleep over the copy time
else
fTotalCount = newCount + (newCount >> 1); // Give it Half again as much
#endif
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef CoreLib_Thread
#define CoreLib_Thread
#include "hsThread.h"
#include "hsUtils.h"
//////////////////////////////////////////////////////////////////////////////
hsReaderWriterLock::hsReaderWriterLock( const char * name, Callback * cb )
: fReaderCount( 0 )
, fWriterSema( 1 )
, fCallback( cb )
, fName( nil )
{
fName = hsStrcpy( name );
}
hsReaderWriterLock::~hsReaderWriterLock()
{
delete [] fName;
}
void hsReaderWriterLock::LockForReading()
{
if ( fCallback )
fCallback->OnLockingForRead( this );
fReaderCountLock.Lock();
fReaderLock.Lock();
fReaderCount++;
if ( fReaderCount==1 )
fWriterSema.Wait();
fReaderLock.Unlock();
fReaderCountLock.Unlock();
if ( fCallback )
fCallback->OnLockedForRead( this );
}
void hsReaderWriterLock::UnlockForReading()
{
if ( fCallback )
fCallback->OnUnlockingForRead( this );
fReaderLock.Lock();
fReaderCount--;
if ( fReaderCount==0 )
fWriterSema.Signal();
fReaderLock.Unlock();
if ( fCallback )
fCallback->OnUnlockedForRead( this );
}
void hsReaderWriterLock::LockForWriting()
{
if ( fCallback )
fCallback->OnLockingForWrite( this );
fReaderCountLock.Lock();
fWriterSema.Wait();
hsAssert( fReaderCount==0, "Locked for writing, but fReaderCount>0" );
if ( fCallback )
fCallback->OnLockedForWrite( this );
}
void hsReaderWriterLock::UnlockForWriting()
{
if ( fCallback )
fCallback->OnUnlockingForWrite( this );
fWriterSema.Signal();
fReaderCountLock.Unlock();
if ( fCallback )
fCallback->OnUnlockedForWrite( this );
}
#endif // CoreLib_Thread

View File

@ -0,0 +1,301 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsThread_Defined
#define hsThread_Defined
#include "hsTypes.h"
typedef UInt32 hsMilliseconds;
#if HS_BUILD_FOR_MAC
#include <Multiprocessing.h>
#elif HS_BUILD_FOR_WIN32
#include "hsWindows.h"
#elif HS_BUILD_FOR_UNIX
#include <pthread.h>
#include <semaphore.h>
// We can't wait with a timeout with semas
#define USE_SEMA
// Linux kernel 2.4 w/ NTPL threading patch and O(1) scheduler
// seems to have a problem in it's cond_t implementation that
// causes a hang under heavy load. This is a workaround that
// uses select() and pipes.
// #define PSEUDO_EVENT
#endif
class hsThread
{
public:
#if HS_BUILD_FOR_MAC
typedef MPTaskId ThreadId;
#elif HS_BUILD_FOR_WIN32
typedef DWORD ThreadId;
#elif HS_BUILD_FOR_UNIX
typedef pthread_t ThreadId;
#endif
private:
hsBool fQuit;
UInt32 fStackSize;
#if HS_BUILD_FOR_MAC
ThreadId fTaskId;
MPQueueId fNotifyQ;
#elif HS_BUILD_FOR_WIN32
ThreadId fThreadId;
HANDLE fThreadH;
HANDLE fQuitSemaH;
#elif HS_BUILD_FOR_UNIX
ThreadId fPThread;
hsBool fIsValid;
pthread_mutex_t fMutex;
#endif
protected:
hsBool GetQuit() const { return hsBool(fQuit); }
void SetQuit(hsBool value) { fQuit = value; }
public:
hsThread(UInt32 stackSize = 0);
virtual ~hsThread(); // calls Stop()
#if HS_BUILD_FOR_MAC
ThreadId GetThreadId() { return fTaskId; }
#error "Mac is Depricated"
#elif HS_BUILD_FOR_WIN32
ThreadId GetThreadId() { return fThreadId; }
static ThreadId GetMyThreadId() { return GetCurrentThreadId(); }
#elif HS_BUILD_FOR_UNIX
ThreadId GetThreadId() { return fPThread; }
static ThreadId GetMyThreadId() { return pthread_self(); }
pthread_mutex_t* GetStartupMutex() { return &fMutex; }
#endif
virtual hsError Run() = 0; // override this to do your work
virtual void Start(); // initializes stuff and calls your Run() method
virtual void Stop(); // sets fQuit = true and the waits for the thread to stop
// Static functions
static void* Alloc(size_t size); // does not call operator::new(), may return nil
static void Free(void* p); // does not call operator::delete()
static void ThreadYield();
#if HS_BUILD_FOR_WIN32
DWORD WinRun();
#endif
};
//////////////////////////////////////////////////////////////////////////////
class hsMutex {
#if HS_BUILD_FOR_MAC
MPCriticalRegionId fCriticalRegion;
#elif HS_BUILD_FOR_WIN32
HANDLE fMutexH;
#elif HS_BUILD_FOR_UNIX
pthread_mutex_t fPMutex;
#endif
public:
hsMutex();
virtual ~hsMutex();
void Lock();
hsBool TryLock();
void Unlock();
};
class hsTempMutexLock {
hsMutex* fMutex;
public:
hsTempMutexLock(hsMutex* mutex) : fMutex(mutex)
{
fMutex->Lock();
}
hsTempMutexLock(hsMutex& mutex) : fMutex(&mutex)
{
fMutex->Lock();
}
~hsTempMutexLock()
{
fMutex->Unlock();
}
};
//////////////////////////////////////////////////////////////////////////////
class hsSemaphore {
#if HS_BUILD_FOR_MAC
MPSemaphoreId fSemaId;
#elif HS_BUILD_FOR_WIN32
HANDLE fSemaH;
#elif HS_BUILD_FOR_UNIX
#ifdef USE_SEMA
sem_t fPSema;
#else
pthread_mutex_t fPMutex;
pthread_cond_t fPCond;
Int32 fCounter;
#endif
#endif
public:
#ifdef HS_BUILD_FOR_WIN32
hsSemaphore(int initialValue=0, const char *name=nil);
#else
hsSemaphore(int initialValue=0);
#endif
~hsSemaphore();
hsBool Wait(hsMilliseconds timeToWait = kPosInfinity32);
void Signal();
};
//////////////////////////////////////////////////////////////////////////////
#if !HS_BUILD_FOR_MAC
class hsEvent
{
#if HS_BUILD_FOR_UNIX
#ifndef PSEUDO_EVENT
pthread_mutex_t fMutex;
pthread_cond_t fCond;
hsBool fTriggered;
#else
enum { kRead, kWrite };
int fFds[2];
hsMutex fWaitLock;
hsMutex fSignalLock;
#endif // PSEUDO_EVENT
#elif HS_BUILD_FOR_WIN32
HANDLE fEvent;
#endif
public:
hsEvent();
~hsEvent();
hsBool Wait(hsMilliseconds timeToWait = kPosInfinity32);
void Signal();
};
#endif // HS_BUILD_FOR_MAC
//////////////////////////////////////////////////////////////////////////////
#if !HS_BUILD_FOR_MAC
class hsSleep
{
public:
#if HS_BUILD_FOR_UNIX
static void Sleep(UInt32 millis);
#elif HS_BUILD_FOR_WIN32
static void Sleep(UInt32 millis) { ::Sleep(millis); }
#endif
};
#endif // HS_BUILD_FOR_MAC
//////////////////////////////////////////////////////////////////////////////
// Allows multiple readers, locks out readers for writing.
class hsReaderWriterLock
{
public:
struct Callback
{
virtual void OnLockingForRead( hsReaderWriterLock * lock ) {}
virtual void OnLockedForRead( hsReaderWriterLock * lock ) {}
virtual void OnUnlockingForRead( hsReaderWriterLock * lock ) {}
virtual void OnUnlockedForRead( hsReaderWriterLock * lock ) {}
virtual void OnLockingForWrite( hsReaderWriterLock * lock ) {}
virtual void OnLockedForWrite( hsReaderWriterLock * lock ) {}
virtual void OnUnlockingForWrite( hsReaderWriterLock * lock ) {}
virtual void OnUnlockedForWrite( hsReaderWriterLock * lock ) {}
};
hsReaderWriterLock( const char * name="<unnamed>", Callback * cb=nil );
~hsReaderWriterLock();
void LockForReading();
void UnlockForReading();
void LockForWriting();
void UnlockForWriting();
const char * GetName() const { return fName; }
private:
int fReaderCount;
hsMutex fReaderCountLock;
hsMutex fReaderLock;
hsSemaphore fWriterSema;
Callback * fCallback;
char * fName;
};
class hsLockForReading
{
hsReaderWriterLock * fLock;
public:
hsLockForReading( hsReaderWriterLock & lock ): fLock( &lock )
{
fLock->LockForReading();
}
hsLockForReading( hsReaderWriterLock * lock ): fLock( lock )
{
fLock->LockForReading();
}
~hsLockForReading()
{
fLock->UnlockForReading();
}
};
class hsLockForWriting
{
hsReaderWriterLock * fLock;
public:
hsLockForWriting( hsReaderWriterLock & lock ): fLock( &lock )
{
fLock->LockForWriting();
}
hsLockForWriting( hsReaderWriterLock * lock ): fLock( lock )
{
fLock->LockForWriting();
}
~hsLockForWriting()
{
fLock->UnlockForWriting();
}
};
#endif

View File

@ -0,0 +1,179 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsThread.h"
#include "hsExceptions.h"
extern "C" {
static OSStatus gEntryPoint(void* param)
{
return ((hsThread*)param)->Run();
}
}
hsThread::hsThread(UInt32 stackSize) : fTaskId(0), fStackSize(stackSize), fQuit(false)
{
if (MPLibraryIsLoaded() == false)
throw "MPLibraryIsLoaded() returned false";
}
hsThread::~hsThread()
{
this->Stop();
}
void hsThread::Start()
{
if (fTaskId == 0)
{ OSStatus status = ::MPCreateQueue(&fNotifyQ);
hsThrowIfOSErr(status);
status = ::MPCreateTask(gEntryPoint, this, fStackSize, fNotifyQ, nil, nil, 0, &fTaskId);
if (status)
{ ::MPDeleteQueue(fNotifyQ);
throw hsOSException(status);
}
}
else
hsDebugMessage("Calling hsThread::Start() more than once", 0);
}
void hsThread::Stop()
{
if (fTaskId)
{ this->fQuit = true;
OSStatus status = ::MPTerminateTask(fTaskId, 0);
hsThrowIfOSErr(status);
// Wait for the task to tell us that its actually quit
status = ::MPWaitOnQueue(fNotifyQ, nil, nil, nil, kDurationForever);
hsThrowIfOSErr(status);
status = ::MPDeleteQueue(fNotifyQ);
hsThrowIfOSErr(status);
fTaskId = 0;
}
}
//////////////////////////////////////////////////////////////////////////////
void* hsThread::Alloc(size_t size)
{
return ::MPAllocate(size);
}
void hsThread::Free(void* p)
{
if (p)
::MPFree(p);
}
void hsThread::ThreadYield()
{
::MPYield();
}
//////////////////////////////////////////////////////////////////////////////
hsMutex::hsMutex()
{
OSStatus status = ::MPCreateCriticalRegion(&fCriticalRegion);
hsThrowIfOSErr(status);
}
hsMutex::~hsMutex()
{
OSStatus status = ::MPDeleteCriticalRegion(fCriticalRegion);
hsThrowIfOSErr(status);
}
void hsMutex::Lock()
{
OSStatus status = ::MPEnterCriticalRegion(fCriticalRegion, kDurationForever);
hsThrowIfOSErr(status);
}
void hsMutex::Unlock()
{
OSStatus status = ::MPExitCriticalRegion(fCriticalRegion);
hsThrowIfOSErr(status);
}
//////////////////////////////////////////////////////////////////////////////
hsSemaphore::hsSemaphore(int initialValue)
{
OSStatus status = MPCreateSemaphore(kPosInfinity32, initialValue, &fSemaId);
hsThrowIfOSErr(status);
}
hsSemaphore::~hsSemaphore()
{
OSStatus status = MPDeleteSemaphore(fSemaId);
hsThrowIfOSErr(status);
}
hsBool hsSemaphore::Wait(hsMilliseconds timeToWait)
{
Duration duration;
if (timeToWait == kPosInfinity32)
duration = kDurationForever;
else
duration = 0; // THEY DON'T IMPLEMENT delay times yet !!!
OSStatus status = MPWaitOnSemaphore(fSemaId, duration);
/*
if (status == kMPTimeoutErr)
return false;
*/
hsThrowIfOSErr(status);
return true;
}
void hsSemaphore::Signal()
{
OSStatus status = MPSignalSemaphore(fSemaId);
hsThrowIfOSErr(status);
}

View File

@ -0,0 +1,553 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsThread.h"
#include "hsExceptions.h"
#include <sys/errno.h>
#include <string.h>
#define NO_POSIX_CLOCK 1
#if NO_POSIX_CLOCK
#include <sys/time.h>
#include <unistd.h>
#define CLOCK_REALTIME 0
//
// A linux hack b/c we're not quite POSIX
//
int clock_gettime(int clocktype, struct timespec* ts)
{
struct timezone tz;
struct timeval tv;
int result = gettimeofday(&tv, &tz);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000 + 500; // sice we're losing accuracy round up by 500 nanos
return result;
}
#endif
extern "C" {
static void* gEntryPoint(void* param)
{
pthread_mutex_lock(((hsThread*)param)->GetStartupMutex());
void* ret = (void*)((hsThread*)param)->Run();
pthread_mutex_unlock(((hsThread*)param)->GetStartupMutex());
pthread_exit(ret);
return ret;
}
}
#define kInvalidStackSize UInt32(~0)
hsThread::hsThread(UInt32 stackSize) : fStackSize(stackSize), fQuit(false)
{
fIsValid = false;
pthread_mutex_init(&fMutex,nil);
}
hsThread::~hsThread()
{
this->Stop();
}
void hsThread::Start()
{
if (fIsValid == false)
{
pthread_mutex_lock(GetStartupMutex());
int status = ::pthread_create(&fPThread, nil, gEntryPoint, this);
pthread_mutex_unlock(GetStartupMutex());
hsThrowIfOSErr(status);
fIsValid = true;
}
else
hsDebugMessage("Calling hsThread::Start() more than once", 0);
}
void hsThread::Stop()
{
if (fIsValid)
{ this->fQuit = true;
int status = ::pthread_join(fPThread, nil);
hsThrowIfOSErr(status);
fIsValid = false;
}
}
//////////////////////////////////////////////////////////////////////////////
void* hsThread::Alloc(size_t size)
{
return ::malloc(size);
}
void hsThread::Free(void* p)
{
if (p)
::free(p);
}
void hsThread::ThreadYield()
{
// ::sched_yield();
}
//////////////////////////////////////////////////////////////////////////////
//#define MUTEX_TIMING
#ifdef MUTEX_TIMING
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "hsWide.h"
static FILE * gMutexTimerFile = nil;
static void InitMutexTimerFile()
{
if ( !gMutexTimerFile )
{
gMutexTimerFile = fopen( "log/MutexTimes.log", "wt" );
if ( gMutexTimerFile )
fprintf( gMutexTimerFile, "------------------------------------\n" );
}
}
#endif
//#define EVENT_LOGGING
#ifdef EVENT_LOGGING
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include "../NucleusLib/inc/hsTimer.h"
static FILE * gEventLoggingFile = nil;
static void InitEventLoggingFile()
{
if ( !gEventLoggingFile )
{
char fname[256];
sprintf(fname,"log/Events-%u.log",getpid());
gEventLoggingFile = fopen( fname, "wt" );
if ( gEventLoggingFile )
fprintf( gEventLoggingFile, "------------------------------------\n" );
}
}
#endif
hsMutex::hsMutex()
{
#ifdef MUTEX_TIMING
InitMutexTimerFile();
#endif
// create mutex attributes
pthread_mutexattr_t attr;
int status = ::pthread_mutexattr_init(&attr);
hsThrowIfOSErr(status);
// make the mutex attributes recursive
status = ::pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
hsThrowIfOSErr(status);
//init the mutex
status = ::pthread_mutex_init(&fPMutex, &attr);
hsThrowIfOSErr(status);
// destroy the attributes
status = ::pthread_mutexattr_destroy(&attr);
hsThrowIfOSErr(status);
}
hsMutex::~hsMutex()
{
int status = ::pthread_mutex_destroy(&fPMutex);
hsThrowIfOSErr(status);
}
void hsMutex::Lock()
{
#ifdef MUTEX_TIMING
# ifndef HS_DEBUGGING
timeval tv;
hsWide start;
gettimeofday( &tv, nil );
start.Mul( tv.tv_sec, 1000000 )->Add( tv.tv_usec );
# endif
#endif
int status = ::pthread_mutex_lock(&fPMutex);
hsThrowIfOSErr(status);
#ifdef MUTEX_TIMING
# ifndef HS_DEBUGGING
hsWide diff;
gettimeofday( &tv, nil );
diff.Mul( tv.tv_sec, 1000000 )->Add( tv.tv_usec )->Sub( &start )->Div( 1000000 );
double duration = diff.AsDouble();
if ( gMutexTimerFile && duration>0.005 )
{
time_t t;
time( &t );
struct tm *now = localtime( &t );
char tmp[30];
strftime( tmp, 30, "%c", now );
fprintf( gMutexTimerFile, "[%s] [%lu:%lu] %f\n", tmp, getpid(), hsThread::GetMyThreadId(), duration );
}
# endif
#endif
}
hsBool hsMutex::TryLock()
{
int status = ::pthread_mutex_trylock(&fPMutex);
hsThrowIfOSErr(status);
return status==EBUSY?false:true;
}
void hsMutex::Unlock()
{
int status = ::pthread_mutex_unlock(&fPMutex);
hsThrowIfOSErr(status);
}
/////////////////////////////////////////////////////////////////////////////
hsSemaphore::hsSemaphore(int initialValue)
{
#ifdef USE_SEMA
int shared = 0; // 1 if sharing between processes
int status = ::sem_init(&fPSema, shared, initialValue);
hsThrowIfOSErr(status);
#else
int status = ::pthread_mutex_init(&fPMutex, nil);
hsThrowIfOSErr(status);
status = ::pthread_cond_init(&fPCond, nil);
hsThrowIfOSErr(status);
fCounter = initialValue;
#endif
}
hsSemaphore::~hsSemaphore()
{
#ifdef USE_SEMA
int status = ::sem_destroy(&fPSema);
hsThrowIfOSErr(status);
#else
int status = ::pthread_cond_destroy(&fPCond);
hsThrowIfOSErr(status);
status = ::pthread_mutex_destroy(&fPMutex);
hsThrowIfOSErr(status);
#endif
}
hsBool hsSemaphore::Wait(hsMilliseconds timeToWait)
{
#ifdef USE_SEMA // SHOULDN'T THIS USE timeToWait??!?!? -rje
hsAssert( timeToWait==kPosInfinity32, "sem_t does not support wait with timeout. #undef USE_SEMA and recompile." );
int status = ::sem_wait(&fPSema);
hsThrowIfOSErr(status);
return true;
#else
hsBool retVal = true;
int status = ::pthread_mutex_lock(&fPMutex);
hsThrowIfOSErr(status);
if (timeToWait == kPosInfinity32)
{ while (fCounter == 0)
{ status = ::pthread_cond_wait(&fPCond, &fPMutex);
hsThrowIfOSErr(status);
}
}
else
{ timespec spec;
int result;
result = ::clock_gettime(CLOCK_REALTIME, &spec);
hsThrowIfFalse(result == 0);
spec.tv_sec += timeToWait / 1000;
spec.tv_nsec += (timeToWait % 1000) * 1000 * 1000;
while (spec.tv_nsec >= 1000 * 1000 * 1000)
{ spec.tv_sec += 1;
spec.tv_nsec -= 1000 * 1000 * 1000;
}
while (fCounter == 0)
{ status = ::pthread_cond_timedwait(&fPCond, &fPMutex, &spec);
if (status == ETIMEDOUT)
{ retVal = false;
goto EXIT;
}
hsThrowIfOSErr(status);
}
}
hsAssert(fCounter > 0, "oops");
fCounter -= 1;
EXIT:
status = ::pthread_mutex_unlock(&fPMutex);
hsThrowIfOSErr(status);
return retVal;
#endif
}
void hsSemaphore::Signal()
{
#ifdef USE_SEMA
int status = ::sem_post(&fPSema);
hsThrowIfOSErr(status);
#else
int status = ::pthread_mutex_lock(&fPMutex);
hsThrowIfOSErr(status);
fCounter += 1;
status = ::pthread_mutex_unlock(&fPMutex);
hsThrowIfOSErr(status);
status = ::pthread_cond_signal(&fPCond);
hsThrowIfOSErr(status);
#endif
}
///////////////////////////////////////////////////////////////
#ifndef PSEUDO_EVENT
hsEvent::hsEvent() : fTriggered(false)
{
#ifdef EVENT_LOGGING
InitEventLoggingFile();
#endif
int status = ::pthread_mutex_init(&fMutex, nil);
hsAssert(status == 0, "hsEvent Mutex Init");
hsThrowIfOSErr(status);
// fCond = PTHREAD_COND_INITIALIZER;
status = ::pthread_cond_init(&fCond, nil);
hsAssert(status == 0, "hsEvent Cond Init");
hsThrowIfOSErr(status);
}
hsEvent::~hsEvent()
{
int status = ::pthread_cond_destroy(&fCond);
hsAssert(status == 0, "hsEvent Cond De-Init");
hsThrowIfOSErr(status);
status = ::pthread_mutex_destroy(&fMutex);
hsAssert(status == 0, "hsEvent Mutex De-Init");
hsThrowIfOSErr(status);
}
hsBool hsEvent::Wait(hsMilliseconds timeToWait)
{
hsBool retVal = true;
int status = ::pthread_mutex_lock(&fMutex);
hsAssert(status == 0, "hsEvent Mutex Lock");
hsThrowIfOSErr(status);
#ifdef EVENT_LOGGING
fprintf(gEventLoggingFile,"Event: %p - In Wait (pre trig check), Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
#endif
if ( !fTriggered )
{
if (timeToWait == kPosInfinity32)
{
status = ::pthread_cond_wait(&fCond, &fMutex);
hsAssert(status == 0, "hsEvent Cond Wait");
hsThrowIfOSErr(status);
}
else
{ timespec spec;
int result;
result = ::clock_gettime(CLOCK_REALTIME, &spec);
hsThrowIfFalse(result == 0);
spec.tv_sec += timeToWait / 1000;
spec.tv_nsec += (timeToWait % 1000) * 1000 * 1000;
while (spec.tv_nsec >= 1000 * 1000 * 1000)
{ spec.tv_sec += 1;
spec.tv_nsec -= 1000 * 1000 * 1000;
}
status = ::pthread_cond_timedwait(&fCond, &fMutex, &spec);
if (status == ETIMEDOUT)
{
// It's a conditional paired with a variable!
// Pthread docs all use a variable in conjunction with the conditional
retVal = fTriggered;
status = 0;
#ifdef EVENT_LOGGING
fprintf(gEventLoggingFile,"Event: %p - In Wait (wait timed out), Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
#endif
}
else
{
#ifdef EVENT_LOGGING
fprintf(gEventLoggingFile,"Event: %p - In Wait (wait recvd signal), Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
#endif
}
hsAssert(status == 0, "hsEvent Cond Wait");
hsThrowIfOSErr(status);
}
}
else
{
#ifdef EVENT_LOGGING
fprintf(gEventLoggingFile,"Event: %p - In Wait (post triggerd), Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
#endif
}
fTriggered = false;
status = ::pthread_mutex_unlock(&fMutex);
hsAssert(status == 0, "hsEvent Mutex Unlock");
hsThrowIfOSErr(status);
return retVal;
}
void hsEvent::Signal()
{
int status = ::pthread_mutex_lock(&fMutex);
hsAssert(status == 0, "hsEvent Mutex Lock");
hsThrowIfOSErr(status);
#ifdef EVENT_LOGGING
fprintf(gEventLoggingFile,"Event: %p - In Signal, Triggered: %d, t=%f\n",this,fTriggered,hsTimer::GetSeconds());
#endif
fTriggered = true;
status = ::pthread_cond_broadcast(&fCond);
hsAssert(status == 0, "hsEvent Cond Broadcast");
hsThrowIfOSErr(status);
status = ::pthread_mutex_unlock(&fMutex);
hsAssert(status == 0, "hsEvent Mutex Unlock");
hsThrowIfOSErr(status);
}
#else
hsEvent::hsEvent()
{
pipe( fFds );
}
hsEvent::~hsEvent()
{
close( fFds[kRead] );
close( fFds[kWrite] );
}
hsBool hsEvent::Wait( hsMilliseconds timeToWait )
{
hsTempMutexLock lock( fWaitLock );
fd_set fdset;
FD_ZERO( &fdset );
FD_SET( fFds[kRead], &fdset );
int ans;
if( timeToWait==kPosInfinity32 )
{
ans = select( fFds[kRead]+1, &fdset, nil, nil, nil );
}
else
{
struct timeval tv;
tv.tv_sec = timeToWait / 1000;
tv.tv_usec = ( timeToWait % 1000 ) * 1000;
ans = select( fFds[kRead]+1, &fdset, nil, nil, &tv );
}
bool signaled = false;
if ( ans>0 )
{
char buf[2];
int n = read( fFds[kRead], buf, 1 );
signaled = ( n==1 );
}
return signaled;
}
void hsEvent::Signal()
{
hsTempMutexLock lock( fSignalLock );
write( fFds[kWrite], "*", 1 );
}
#endif
void hsSleep::Sleep(UInt32 millis)
{
UInt32 secs = millis / 1000;
if (secs > 0)
{
millis %= 1000;
::sleep(secs);
}
usleep(millis*1000);
}

View File

@ -0,0 +1,234 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include <process.h>
#include "hsThread.h"
#include "hsExceptions.h"
#include "hsMemory.h"
// typedef unsigned int __stdcall (*EntryPtCB)(void*);
static DWORD __stdcall gEntryPoint(void* param)
{
return ((hsThread*)param)->WinRun();
}
static unsigned int __stdcall gEntryPointBT(void* param)
{
return ((hsThread*)param)->WinRun();
}
hsThread::hsThread(UInt32 stackSize) : fStackSize(stackSize), fQuit(false), fThreadH(nil), fQuitSemaH(nil)
{
}
hsThread::~hsThread()
{
this->Stop();
}
void hsThread::Start()
{
if (fThreadH == nil)
{
fQuitSemaH = ::CreateSemaphore(nil, 0, kPosInfinity32, nil);
if (fQuitSemaH == nil)
throw hsOSException(-1);
#if 0
fThreadH = ::CreateThread(nil, fStackSize, gEntryPoint, this, 0, &fThreadId);
#else
fThreadH = (HANDLE)_beginthreadex(nil, fStackSize, gEntryPointBT, this, 0, (unsigned int*)&fThreadId);
#endif
if (fThreadH == nil)
throw hsOSException(-1);
}
}
void hsThread::Stop()
{
if (fThreadH != nil)
{ this->fQuit = true;
if (fQuitSemaH != nil)
::WaitForSingleObject(fQuitSemaH, INFINITE); // wait for the thread to quit
::CloseHandle(fThreadH);
fThreadH = nil;
::CloseHandle(fQuitSemaH);
fQuitSemaH = nil;
}
}
DWORD hsThread::WinRun()
{
DWORD result = this->Run();
::ReleaseSemaphore(fQuitSemaH, 1, nil); // signal that we've quit
return result;
}
/////////////////////////////////////////////////////////////////////////////////////////
void* hsThread::Alloc(size_t size)
{
return HSMemory::New(size);
}
void hsThread::Free(void* p)
{
HSMemory::Delete(p);
}
void hsThread::ThreadYield()
{
// Don't know how to explicitly yield on WIN32
}
//////////////////////////////////////////////////////////////////////////////
hsMutex::hsMutex()
{
fMutexH = ::CreateMutex(nil, false, nil);
if (fMutexH == nil)
throw hsOSException(-1);
}
hsMutex::~hsMutex()
{
::CloseHandle(fMutexH);
}
void hsMutex::Lock()
{
DWORD state = ::WaitForSingleObject(fMutexH, INFINITE);
hsAssert(state != WAIT_FAILED,"hsMutex::Lock -> Wait Failed");
hsAssert(state != WAIT_ABANDONED,"hsMutex::Lock -> Abandoned Mutex");
hsAssert(state != WAIT_TIMEOUT,"hsMutex::Lock -> Infinite Timeout expired?");
}
hsBool hsMutex::TryLock()
{
DWORD state = ::WaitForSingleObject(fMutexH, 0);
hsAssert(state != WAIT_ABANDONED,"hsMutex::TryLock -> Abandoned Mutex");
return state == WAIT_OBJECT_0?true:false;
}
void hsMutex::Unlock()
{
BOOL result = ::ReleaseMutex(fMutexH);
hsAssert(result != 0, "hsMutex::Unlock Failed!");
}
//////////////////////////////////////////////////////////////////////////////
hsSemaphore::hsSemaphore(int initialValue, const char *name)
{
fSemaH = ::CreateSemaphore(nil, initialValue, kPosInfinity32, name);
if (fSemaH == nil)
throw hsOSException(-1);
}
hsSemaphore::~hsSemaphore()
{
::CloseHandle(fSemaH);
}
hsBool hsSemaphore::Wait(hsMilliseconds timeToWait)
{
if (timeToWait == kPosInfinity32)
timeToWait = INFINITE;
DWORD result =::WaitForSingleObject(fSemaH, timeToWait);
if (result == WAIT_OBJECT_0)
return true;
else
{ hsThrowIfFalse(result == WAIT_TIMEOUT);
return false;
}
}
void hsSemaphore::Signal()
{
::ReleaseSemaphore(fSemaH, 1, nil);
}
///////////////////////////////////////////////////////////////
hsEvent::hsEvent()
{
fEvent = ::CreateEvent(nil,true,false,nil);
if (fEvent == nil)
throw hsOSException(-1);
}
hsEvent::~hsEvent()
{
::CloseHandle(fEvent);
}
hsBool hsEvent::Wait(hsMilliseconds timeToWait)
{
if (timeToWait == kPosInfinity32)
timeToWait = INFINITE;
DWORD result =::WaitForSingleObject(fEvent, timeToWait);
if (result == WAIT_OBJECT_0)
{
::ResetEvent(fEvent);
return true;
}
else
{ hsThrowIfFalse(result == WAIT_TIMEOUT);
return false;
}
}
void hsEvent::Signal()
{
::SetEvent(fEvent);
}

View File

@ -0,0 +1,614 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "HeadSpin.h"
#ifndef hsTypes_Defined
#define hsTypes_Defined
/************************** Other Includes *****************************/
#if !(HS_BUILD_FOR_REFERENCE)
#if HS_BUILD_FOR_MAC
#include <Types.h>
#include <string.h>
#include <ctype.h>
#include <memory.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#endif
#if HS_CAN_USE_FLOAT
#include <math.h>
#endif
/************************** Basic Macros *****************************/
#ifdef __cplusplus
#define hsCTypeDefStruct(foo)
#else
#define hsCTypeDefStruct(foo) typedef struct foo foo;
#endif
/************************** Basic Types *****************************/
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
#ifdef _MSC_VER
typedef unsigned __int64 qword;
#else
typedef unsigned long long qword;
#endif
typedef size_t unsigned_ptr;
typedef wchar_t wchar;
#define kPosInfinity16 (32767)
#define kNegInfinity16 (-32768)
#define kPosInfinity32 (0x7fffffff)
#define kNegInfinity32 (0x80000000)
#if HS_BUILD_FOR_PS2
typedef int Int32;
#else
typedef long Int32;
#endif
typedef short Int16;
typedef signed char Int8;
#if !(HS_BUILD_FOR_MAC)
typedef unsigned char UInt8;
typedef unsigned short UInt16;
#if HS_BUILD_FOR_PS2
typedef unsigned int UInt32;
#else
typedef unsigned long UInt32;
#endif
#ifndef Byte
typedef UInt8 Byte;
#endif
#ifndef false
#define false 0
#endif
#ifndef true
#define true 1
#endif
#ifndef Boolean
#if HS_BUILD_FOR_UNIX
typedef char Boolean;
#else
typedef UInt8 Boolean;
#endif
#endif
#endif
#if HS_BUILD_FOR_WIN32
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#else
typedef long long Int64;
typedef unsigned long long UInt64;
#endif
typedef Int32 hsFixed;
typedef Int32 hsFract;
#ifdef __cplusplus
typedef int hsBool;
#endif
#include "hsScalar.h"
#if HS_CAN_USE_FLOAT
#define HS_PI 3.1415927
#endif
#ifndef nil
#define nil (0)
#endif
typedef Int32 hsError;
typedef UInt32 hsGSeedValue;
#define hsOK 0
#define hsFail -1
#define hsFailed(r) ((hsError)(r)<hsOK)
#define hsSucceeded(r) ((hsError)(r)>=hsOK)
#define hsLongAlign(n) (((n) + 3) & ~3L)
#define hsMaximum(a, b) ((a) > (b) ? (a) : (b))
#define hsMinimum(a, b) ((a) < (b) ? (a) : (b))
#define hsABS(x) ((x) < 0 ? -(x) : (x))
#define hsSGN(x) (((x) < 0) ? -1 : ( ((x) > 0) ? 1 : 0 ))
#define hsBitTst2Bool(value, mask) (((value) & (mask)) != 0)
#define hsFourByteTag(a, b, c, d) (((UInt32)(a) << 24) | ((UInt32)(b) << 16) | ((UInt32)(c) << 8) | (d))
/************************** Swap Macros *****************************/
#ifdef __cplusplus
inline UInt16 hsSwapEndian16(UInt16 value)
{
return (value >> 8) | (value << 8);
}
inline UInt32 hsSwapEndian32(UInt32 value)
{
return (value << 24) |
((value & 0xFF00) << 8) |
((value >> 8) & 0xFF00) |
(value >> 24);
}
#if HS_CAN_USE_FLOAT
inline float hsSwapEndianFloat(float fvalue)
{
UInt32 value = *(UInt32*)&fvalue;
value = hsSwapEndian32(value);
return *(float*)&value;
}
#endif
#if HS_CPU_LENDIAN
#define hsUNSWAP16(n) hsSwapEndian16(n)
#define hsUNSWAP32(n) hsSwapEndian32(n)
#define hsSWAP16(n) (n)
#define hsSWAP32(n) (n)
#else
#define hsUNSWAP16(n) (n)
#define hsUNSWAP32(n) (n)
#define hsSWAP16(n) hsSwapEndian16(n)
#define hsSWAP32(n) hsSwapEndian32(n)
#endif
inline void hsSwap(Int32& a, Int32& b)
{
Int32 c = a;
a = b;
b = c;
}
inline void hsSwap(UInt32& a, UInt32& b)
{
UInt32 c = a;
a = b;
b = c;
}
#if HS_CAN_USE_FLOAT
inline void hsSwap(float& a, float& b)
{
float c = a;
a = b;
b = c;
}
#endif
#endif
/************************** Color32 Type *****************************/
struct hsColor32 {
#if 1 // hsColor32 fixed-format optimization
UInt8 b, g, r, a;
#else
#if (HS_BUILD_FOR_WIN32 || HS_BUILD_FOR_BE)
UInt8 b, g, r, a;
#elif (HS_BUILD_FOR_UNIX && HS_CPU_BENDIAN)
UInt8 a, b, g, r;
#else
UInt8 a, r, g, b;
#endif
#endif
#ifdef __cplusplus
void SetARGB(UInt8 aa, UInt8 rr, UInt8 gg, UInt8 bb)
{
this->a = aa; this->r = rr; this->g = gg; this->b = bb;
}
// Compatibility inlines, should be depricated
void Set(UInt8 rr, UInt8 gg, UInt8 bb)
{
this->r = rr; this->g = gg; this->b = bb;
}
void Set(UInt8 aa, UInt8 rr, UInt8 gg, UInt8 bb)
{
this->SetARGB(aa, rr, gg, bb);
}
#if 0
friend int operator==(const hsColor32& a, const hsColor32& b)
{
return *(UInt32*)&a == *(UInt32*)&b;
}
friend int operator!=(const hsColor32& a, const hsColor32& b) { return !(a == b); }
#else
int operator==(const hsColor32& aa) const
{
return *(UInt32*)&aa == *(UInt32*)this;
}
int operator!=(const hsColor32& aa) { return !(aa == *this); }
#endif
#endif
};
hsCTypeDefStruct(hsColor32)
typedef hsColor32 hsRGBAColor32;
/****************************************************************************
*
* NULL_STMT
* Declares a null statement
*
* Example:
*
* for (; *str && (*str != ch); ++str)
* NULL_STMT;
*
***/
#if _MSC_VER >= 7
# define NULL_STMT __noop
#else
# define NULL_STMT ((void)0)
#endif
/****************************************************************************
*
* REF
* References a variable to prevent compiler warnings
*
***/
#define REF(a) ((void *)&(a))
#if _MSC_VER < 1400
// For compatibility only, deprecated - use REF instead
#define ref(a) REF(a)
#endif
/****************************************************************************
*
* UNIQUE_SYMBOL
* Creates a symbol that is unique within a file
*
***/
#define UNIQUE_SYMBOL_EXPAND_1(prefix,line) UNIQUE_SYMBOL_##prefix##_##line
#define UNIQUE_SYMBOL_EXPAND_0(prefix,line) UNIQUE_SYMBOL_EXPAND_1(prefix,line)
#define UNIQUE_SYMBOL(prefix) UNIQUE_SYMBOL_EXPAND_0(prefix,__LINE__)
/****************************************************************************
*
* COMPILER_ASSERT
* Performs a "compile-time" assertion
* Can be used at function or file scope
* Upon assertion failure, creates a negative subscript error
* Use COMPILER_ASSERT_HEADER in header files to prevent symbol collision
*
***/
#define COMPILER_ASSERT(expr) static char UNIQUE_SYMBOL(a)[(expr) ? 1 : -1]
#define COMPILER_ASSERT_HEADER(prefix,expr) static char UNIQUE_SYMBOL(prefix)[(expr) ? 1 : -1]
#define COMPILER_ASSERT_SYMBOL(symbol,expr) static char symbol[(expr) ? 1 : -1]
/****************************************************************************
*
* max/min inline functions
*
***/
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
//===========================================================================
template<class T>
inline T max (const T & a, const T & b) {
return (a > b) ? a : b;
}
//===========================================================================
inline unsigned max (int a, unsigned b) {
return ((unsigned)a > b) ? a : b;
}
//===========================================================================
inline unsigned max (unsigned a, int b) {
return (a > (unsigned)b) ? a : b;
}
//===========================================================================
template<class T>
inline T min (const T & a, const T & b) {
return (a < b) ? a : b;
}
//===========================================================================
inline unsigned min (int a, unsigned b) {
return ((unsigned)a < b) ? a : b;
}
//===========================================================================
inline unsigned min (unsigned a, int b) {
return (a < (unsigned)b) ? a : b;
}
/****************************************************************************
*
* MAX/MIN macros
* These are less safe than the inline function versions, since they
* evaluate parameters twice. However, they can be used to produce
* compile-time constants.
*
***/
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
/****************************************************************************
*
* SWAP
* Swaps the values of two variables
*
***/
//===========================================================================
template<class T>
void SWAP (T & a, T & b) {
T temp = a;
a = b;
b = temp;
}
/****************************************************************************
*
* AUTO_INIT_FUNC
* Declares a function that is automatically called at program startup time
*
* Example:
*
* AUTO_INIT_FUNC(BuildLookupTables) {
* ...
* }
*
***/
#define AUTO_INIT_FUNC(name) namespace { struct name { name (); } name##_instance; } name::name ()
/****************************************************************************
*
* Calculate the address to the base of a structure given its type, and the
* address of a field within the structure.
*
* Example:
*
* CONTAINING_STRUCT(trans, INetTrans, m_trans);
*
***/
#define CONTAINING_STRUCT(a, t, f) ((t *) ((byte *)(a) - (unsigned_ptr)(&((t *)0)->f)))
/****************************************************************************
*
* arrsize/marrsize
* arrsize returns the number of elements in an array variable
* marrsize returns the number of elements in an array field in a structure
*
* Example:
*
* StrPrintf(buffer, arrsize(buffer), "%u", value);
*
***/
#define arrsize(a) (sizeof(a) / sizeof((a)[0]))
#define marrsize(c,a) (arrsize(((c *)0)->a))
/****************************************************************************
*
* offsetof/moffsetof
* offsetof returns the offset in bytes of a field inside a structure based on a type
* moffsetof returns the offset in bytes of a field inside a structure based on a variable
*
***/
#ifndef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif // ifndef offsetof
#define moffsetof(v,f) (((byte *) &((v)->f)) - ((byte *) v))
/****************************************************************************
*
* msizeof
* Returns the size of a field in a structure
*
* Example:
*
* unsigned bufferSize = msizeof(CommandStruct, buffer);
*
***/
#define msizeof(c,a) (sizeof(((c *)0)->a))
/****************************************************************************
*
* ONCE
* Shortcut to create a 'for' loop that executes only once
*
* for (ONCE) {
* ...
* }
*
***/
#ifndef ONCE
#define ONCE bool UNIQUE_SYMBOL(ONCE) = true; UNIQUE_SYMBOL(ONCE); UNIQUE_SYMBOL(ONCE) = false
#endif
/****************************************************************************
*
* IS_POW2
*
***/
#define IS_POW2(val) (!((val) & ((val) - 1)))
/************************ Debug/Error Macros **************************/
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*hsDebugMessageProc)(const char message[]);
extern hsDebugMessageProc gHSDebugProc;
#define HSDebugProc(m) { if (gHSDebugProc) gHSDebugProc(m); }
hsDebugMessageProc hsSetDebugMessageProc(hsDebugMessageProc newProc);
extern hsDebugMessageProc gHSStatusProc;
hsDebugMessageProc hsSetStatusMessageProc(hsDebugMessageProc newProc);
void __cdecl ErrorAssert (int line, const char file[], const char fmt[], ...);
void __cdecl ErrorFatal (int line, const char file[], const char fmt[], ...);
void ErrorMinimizeAppWindow ();
enum EErrorOption {
kErrOptNonGuiAsserts,
kErrOptDisableMemLeakChecking,
kNumErrorOptions
};
bool ErrorSetOption (EErrorOption option, bool on);
bool ErrorGetOption (EErrorOption option);
bool DebugIsDebuggerPresent ();
void DebugBreakIfDebuggerPresent ();
void DebugMsg (const char fmt[], ...);
void DebugMsgV (const char fmt[], va_list args);
#ifdef HS_DEBUGGING
void hsDebugMessage(const char message[], long refcon);
#define hsDebugCode(code) code
#define hsIfDebugMessage(expr, msg, ref) (void)( ((expr) != 0) || (hsDebugMessage(msg, ref), 0) )
#define hsAssert(expr, msg) (void)( ((expr) != 0) || (ErrorAssert(__LINE__, __FILE__, msg), 0) )
#define ASSERT(expr) (void)( ((expr) != 0) || (ErrorAssert(__LINE__, __FILE__, #expr), 0) )
#define ASSERTMSG(expr, msg) (void)( ((expr) != 0) || (ErrorAssert(__LINE__, __FILE__, msg), 0) )
#define FATAL(msg) ErrorAssert(__LINE__, __FILE__, msg)
#define DEBUG_MSG DebugMsg
#define DEBUG_MSGV DebugMsgV
#define DEBUG_BREAK_IF_DEBUGGER_PRESENT DebugBreakIfDebuggerPresent
#else /* Not debugging */
#define hsDebugMessage(message, refcon) NULL_STMT
#define hsDebugCode(code) /* empty */
#define hsIfDebugMessage(expr, msg, ref) NULL_STMT
#define hsAssert(expr, msg) NULL_STMT
#define ASSERT(expr) NULL_STMT
#define ASSERTMSG(expr, msg) NULL_STMT
#define FATAL(msg) NULL_STMT
#define DEBUG_MSG NULL_STMT
#define DEBUG_MSGV NULL_STMT
#define DEBUG_BREAK_IF_DEBUGGER_PRESENT NULL_STMT
#endif // HS_DEBUGGING
#ifdef _MSC_VER
#define DEFAULT_FATAL(var) default: FATAL("No valid case for switch variable '" #var "'"); __assume(0); break;
#else
#define DEFAULT_FATAL(var) default: FATAL("No valid case for switch variable '" #var "'"); break;
#endif
#ifdef PLASMA_EXTERNAL_RELEASE
#define hsStatusMessage(x) NULL_STMT
#define hsStatusMessageF(x,y) NULL_STMT
#else /* Not external release */
void hsStatusMessage(const char message[]);
void hsStatusMessageF(const char * fmt, ...);
#endif // PLASMA_EXTERNAL_RELEASE
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,796 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsUtils.h"
#if HS_BUILD_FOR_MAC
#include <Gestalt.h>
#endif
#if HS_BUILD_FOR_WIN32
extern "C" {
#endif
#include <stdio.h>
#include <stdarg.h>
#if HS_BUILD_FOR_WIN32
};
#endif
#if __MWERKS__
#include <ctype.h>
#endif
#if HS_BUILD_FOR_PS2
#include <ctype.h>
#include "eekernel.h"
#include "sifdev.h"
#endif
#if HS_BUILD_FOR_WIN32
#include <winsock2.h>
#include <windows.h>
#endif
#include "hsStlUtils.h"
#include "hsTemplates.h"
char * hsFormatStr(const char * fmt, ...)
{
va_list args;
va_start(args,fmt);
char * result = hsFormatStrV(fmt,args);
va_end(args);
return result;
}
char * hsFormatStrV(const char * fmt, va_list args)
{
std::string buf;
xtl::formatv(buf,fmt,args);
return hsStrcpy(buf.c_str());
}
static char hsStrBuf[100];
char *hsScalarToStr(hsScalar s)
{
#if !(HS_BUILD_FOR_REFERENCE)
if (s == hsIntToScalar(hsScalarToInt(s)))
sprintf(hsStrBuf, "%d", hsScalarToInt(s));
else
#if HS_CAN_USE_FLOAT
sprintf(hsStrBuf, "%f", hsScalarToFloat(s));
#else
sprintf(hsStrBuf, "%d:%lu", hsFixedToInt(s), (UInt16)s);
#endif
#endif
return hsStrBuf;
}
bool hsMessageBox_SuppressPrompts = false;
int hsMessageBoxWithOwner(void * owner, const char message[], const char caption[], int kind, int icon)
{
if (hsMessageBox_SuppressPrompts)
return hsMBoxOk;
#if HS_BUILD_FOR_WIN32
UInt32 flags = 0;
if (kind == hsMessageBoxNormal)
flags |= MB_OK;
else if (kind == hsMessageBoxAbortRetyIgnore)
flags |= MB_ABORTRETRYIGNORE;
else if (kind == hsMessageBoxOkCancel)
flags |= MB_OKCANCEL;
else if (kind == hsMessageBoxRetryCancel)
flags |= MB_RETRYCANCEL;
else if (kind == hsMessageBoxYesNo)
flags |= MB_YESNO;
else if (kind == hsMessageBoxYesNoCancel)
flags |= MB_YESNOCANCEL;
else
flags |= MB_OK;
if (icon == hsMessageBoxIconError)
flags |= MB_ICONERROR;
else if (icon == hsMessageBoxIconQuestion)
flags |= MB_ICONQUESTION;
else if (icon == hsMessageBoxIconExclamation)
flags |= MB_ICONEXCLAMATION;
else if (icon == hsMessageBoxIconAsterisk)
flags |= MB_ICONASTERISK;
else
flags |= MB_ICONERROR;
#ifdef CLIENT
ErrorMinimizeAppWindow();
#endif
int ans = MessageBox((HWND)owner, message, caption, flags);
switch (ans)
{
case IDOK: return hsMBoxOk;
case IDCANCEL: return hsMBoxCancel;
case IDABORT: return hsMBoxAbort;
case IDRETRY: return hsMBoxRetry;
case IDIGNORE: return hsMBoxIgnore;
case IDYES: return hsMBoxYes;
case IDNO: return hsMBoxNo;
default: return hsMBoxCancel;
}
#endif
#if HS_BUILD_FOR_MACPPC
DebugStr(message);
#endif
#if HS_BUILD_FOR_PS2
printf("Cap:%s Message:%s\n",caption, message);
#endif
}
int hsMessageBoxWithOwner(void * owner, const wchar_t message[], const wchar_t caption[], int kind, int icon)
{
if (hsMessageBox_SuppressPrompts)
return hsMBoxOk;
#if HS_BUILD_FOR_WIN32
UInt32 flags = 0;
if (kind == hsMessageBoxNormal)
flags |= MB_OK;
else if (kind == hsMessageBoxAbortRetyIgnore)
flags |= MB_ABORTRETRYIGNORE;
else if (kind == hsMessageBoxOkCancel)
flags |= MB_OKCANCEL;
else if (kind == hsMessageBoxRetryCancel)
flags |= MB_RETRYCANCEL;
else if (kind == hsMessageBoxYesNo)
flags |= MB_YESNO;
else if (kind == hsMessageBoxYesNoCancel)
flags |= MB_YESNOCANCEL;
else
flags |= MB_OK;
if (icon == hsMessageBoxIconError)
flags |= MB_ICONERROR;
else if (icon == hsMessageBoxIconQuestion)
flags |= MB_ICONQUESTION;
else if (icon == hsMessageBoxIconExclamation)
flags |= MB_ICONEXCLAMATION;
else if (icon == hsMessageBoxIconAsterisk)
flags |= MB_ICONASTERISK;
else
flags |= MB_ICONERROR;
#ifdef CLIENT
ErrorMinimizeAppWindow();
#endif
int ans = MessageBoxW((HWND)owner, message, caption, flags);
switch (ans)
{
case IDOK: return hsMBoxOk;
case IDCANCEL: return hsMBoxCancel;
case IDABORT: return hsMBoxAbort;
case IDRETRY: return hsMBoxRetry;
case IDIGNORE: return hsMBoxIgnore;
case IDYES: return hsMBoxYes;
case IDNO: return hsMBoxNo;
default: return hsMBoxCancel;
}
#endif
#if HS_BUILD_FOR_MACPPC
DebugStr(message);
#endif
#if HS_BUILD_FOR_PS2
printf("Cap:%s Message:%s\n",caption, message);
#endif
}
int hsMessageBox(const char message[], const char caption[], int kind, int icon)
{
#if HS_BUILD_FOR_WIN32
return hsMessageBoxWithOwner(nil/*GetActiveWindow()*/,message,caption,kind,icon);
#else
return hsMessageBoxWithOwner(nil,message,caption,kind,icon);
#endif
}
int hsMessageBox(const wchar_t message[], const wchar_t caption[], int kind, int icon)
{
#if HS_BUILD_FOR_WIN32
return hsMessageBoxWithOwner(nil/*GetActiveWindow()*/,message,caption,kind,icon);
#else
return hsMessageBoxWithOwner(nil,message,caption,kind,icon);
#endif
}
/* Generic psuedo RNG used in ANSI C. */
static unsigned long SEED = 1;
int hsRand()
{
register int temp;
SEED = SEED * 1103515245 + 12345;
temp = (int)((SEED/65536)&32767);
return (temp);
}
void hsRandSeed(int seed)
{
SEED = seed;
}
/**************************************/
int hsStrlen(const char src[])
{
if (src==nil)
return 0;
int i = 0;
while (src[i])
i++;
return i;
}
char* hsStrcpy(char dst[], const char src[])
{
if (src)
{
if (dst == nil)
{
int count = hsStrlen(src);
dst = (char *)ALLOC(count + 1);
memcpy(dst, src, count);
dst[count] = 0;
return dst;
}
Int32 i;
for (i = 0; src[i] != 0; i++)
dst[i] = src[i];
dst[i] = 0;
}
return dst;
}
hsBool hsStrEQ(const char s1[], const char s2[])
{
if (s1 && s2)
{
while (*s1)
if(*s1++ != *s2++)
return false;
return *s2 == 0;
}
return (!s1 && !s2);
}
hsBool hsStrCaseEQ(const char* s1, const char* s2)
{
if (s1 && s2)
{
while (*s1)
if(tolower(*s1++) != tolower(*s2++))
return false;
return *s2 == 0;
}
return (!s1 && !s2);
}
void hsStrcat(char dst[], const char src[])
{
if (src && dst)
{
dst += hsStrlen(dst);
while(*src)
*dst++ = *src++;
*dst = 0;
}
}
void hsStrLower(char *s)
{
if (s)
{
int i;
for (i = 0; i < hsStrlen(s); i++)
s[i] = tolower(s[i]);
}
}
char* hsP2CString(const UInt8 pstring[], char cstring[])
{
char* cstr = cstring;
const UInt8* stop = &pstring[1] + pstring[0];
pstring += 1; // skip length byte
while (pstring < stop)
*cstr++ = *pstring++;
*cstr = 0;
return cstring;
}
UInt8* hsC2PString(const char cstring[], UInt8 pstring[])
{
int i;
for (i = 1; *cstring; i++)
pstring[i] = *cstring++;
pstring[0] = i - 1;
return pstring;
}
//// IStringToWString /////////////////////////////////////////////////////////
// Converts a char * string to a wchar_t * string
wchar_t *hsStringToWString( const char *str )
{
// convert the char string to a wchar_t string
int len = strlen(str);
wchar_t *wideString = TRACKED_NEW wchar_t[len+1];
for (int i=0; i<len; i++)
wideString[i] = btowc(str[i]);
wideString[len] = L'\0';
return wideString;
}
void hsStringToWString( wchar_t *dst, const char *src )
{
if (dst)
delete [] dst;
dst = hsStringToWString(src);
}
//// IWStringToString /////////////////////////////////////////////////////////
// Converts a wchar_t * string to a char * string
char *hsWStringToString( const wchar_t *str )
{
// convert the wchar_t string to a char string
int len = wcslen(str);
char *sStr = TRACKED_NEW char[len+1];
int i;
for (i = 0; i < len; i++)
{
char temp = wctob(str[i]);
if (temp == WEOF)
{
sStr[i] = '\0';
i = len;
}
else
sStr[i] = temp;
}
sStr[len] = '\0';
return sStr;
}
void hsWStringToString( char *dst, const wchar_t *src )
{
if (dst)
delete [] dst;
dst = hsWStringToString(src);
}
void hsCPathToMacPath(char* dst, char* fname)
{
int i;
int offset = 0;
hsBool prefix = 1; // Assume its a relative path.
// KLUDGE: this determines whether a PC path is
// relative or absolute. True if relative, therefore
// we prefix the pathname with a colon.
hsStrcpy(dst, "");
if(strstr(fname, ":"))
{
prefix = 0;
}
else if(strstr(fname, "\\\\"))
{
prefix = 0;
offset = 2; // copy fname from 2-bytes in. This removes
// the first two chars...
}
if(prefix)
{
hsStrcpy(dst, ":");
}
hsStrcat(dst, &fname[offset]);
// No more slashes? We're done. (Optimization? Not really I guess.)
if(!strstr(dst, "\\") && !strstr(dst, "/")) return;
for(i =0; i < hsStrlen(dst); i++)
{
if(dst[i] == '\\' || dst[i] == '/')
{
dst[i] = ':';
}
}
}
int hsRemove(const char * fname)
{
#if HS_BUILD_FOR_MACPPC
char buf[500];
hsStrcpy(buf,":");
hsStrcat(buf,fname);
int i;
for(i =0; i < hsStrlen(buf); i++)
if(buf[i] == '\\')
buf[i] = ':';
return remove(buf);
#endif
return remove(fname);
}
UInt32 hsPhysicalMemory()
{
#define HS_ONE_MEGABYTE 1048576 // 1024 * 1024
#if HS_BUILD_FOR_WIN32
MEMORYSTATUS ms;
GlobalMemoryStatus(&ms);
return (ms.dwTotalPhys / HS_ONE_MEGABYTE);
#elif HS_BUILD_FOR_MAC
// Silver, figure out the physical memory here (in MB)
OSErr err;
SInt32 TotPhysicalRAM;
err = Gestalt(gestaltPhysicalRAMSize, &TotPhysicalRAM);
return (TotPhysicalRAM / HS_ONE_MEGABYTE);
#endif
}
MemSpec hsMemorySpec()
{
UInt32 mem = hsPhysicalMemory();
// Currently adding a little margin of error here
// due to the fact that Windows doesn't seem to
// be totally accurate in it's calculations.
if (mem < 127)
return kBlows;
else if (mem < 255)
return kAcceptable;
else
return kOptimal;
}
#if HS_BUILD_FOR_MAC
FILE *hsFopen(const char *fname, const char *mode)
{
char buf[500];
#if 0
FILE *f;
hsStrcpy(buf,":");
hsStrcat(buf,fname);
int i;
for(i =0; i < hsStrlen(buf); i++)
if(buf[i] == '\\')
buf[i] = ':';
#endif
hsCPathToMacPath(buf, (char*)fname);
return fopen(buf,mode);
}
#endif
#if HS_BUILD_FOR_PS2
int hsPS2Open(const char name[], const char mode[])
{
char buf[500];
int newMode;
int i;
hsStrcpy(buf,"sim:");
//hsStrcpy(buf,"");
hsStrcat(buf,name);
for(i =0; i < hsStrlen(buf); i++)
if(buf[i] == '\\')
buf[i] = '/';
printf("Opening File %s\n",buf);
if(mode[0] == 'r')
newMode = SCE_RDONLY;
else if(mode[0] == 'w')
newMode = SCE_WRONLY|SCE_CREAT;
else
hsAssert(0,"Bad mode in hsPS2Open\n");
printf("Opening File %s mode =%d\n",buf,newMode);
return sceOpen(buf,newMode);
}
void hsPS2Close( int file )
{
if( file != -1 )
sceClose( file );
}
//FILE *hsFopen(const char *fname, const char *mode)
//{
// FILE *f;
// char buf[500];
// char newMode[10];
// hsStrcpy(buf,"sim:");
// //hsStrcpy(buf,"");
// hsStrcat(buf,fname);
// int i;
// for(i =0; i < hsStrlen(buf); i++)
// if(buf[i] == '\\')
// buf[i] = '/';
// printf("Opening File %s\n",buf);
// if(!strcmp("rt",mode))
// {
// strcpy(newMode, "r");
// }
// else
// strcpy(newMode, mode);
//
// printf("Opening File %s mode =%s\n",buf,newMode);
// f= fopen(buf,newMode);
// if(f)
// return f;
// else
// return nil;
//}
#endif
// Compare lexigraphically two strings
#if !(HS_BUILD_FOR_WIN32 || HS_BUILD_FOR_UNIX)
int hsStrcasecmp(const char *s1, const char *s2)
{
if (s1 && s2)
{
char c1, c2;
while (1)
{
c1 = tolower(*s1++);
c2 = tolower(*s2++);
if (c1 < c2) return -1;
if (c1 > c2) return 1;
if (c1 == '\0') return 0;
}
}
return !s1 ? -1 : 1;
}
// Compare lexigraphically two strings up to a max length
int hsStrncasecmp(const char *s1, const char *s2, int n)
{
if (s1 && s2)
{
int i;
char c1, c2;
for (i=0; i<n; i++)
{
c1 = tolower(*s1++);
c2 = tolower(*s2++);
if (c1 < c2) return -1;
if (c1 > c2) return 1;
if (!c1) return 0;
}
return 0;
}
return !s1 ? -1 : 1;
}
#endif
//
// Microsoft SAMPLE CODE
// returns array of allocated version info strings or nil
//
char** DisplaySystemVersion()
{
#if HS_BUILD_FOR_WIN32
#ifndef VER_SUITE_PERSONAL
#define VER_SUITE_PERSONAL 0x200
#endif
hsTArray<char*> versionStrs;
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
//
// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
{
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return FALSE;
}
switch (osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
// Test for the product.
if ( osvi.dwMajorVersion <= 4 )
versionStrs.Append(hsStrcpy("Microsoft Windows NT "));
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
versionStrs.Append(hsStrcpy ("Microsoft Windows 2000 "));
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
versionStrs.Append(hsStrcpy ("Microsoft Windows XP "));
// Test for product type.
if( bOsVersionInfoEx )
{
if ( osvi.wProductType == VER_NT_WORKSTATION )
{
if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
versionStrs.Append(hsStrcpy ( "Personal " ));
else
versionStrs.Append(hsStrcpy ( "Professional " ));
}
else if ( osvi.wProductType == VER_NT_SERVER )
{
if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
versionStrs.Append(hsStrcpy ( "DataCenter Server " ));
else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
versionStrs.Append(hsStrcpy ( "Advanced Server " ));
else
versionStrs.Append(hsStrcpy ( "Server " ));
}
}
else
{
HKEY hKey;
char szProductType[80];
DWORD dwBufLen;
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
0, KEY_QUERY_VALUE, &hKey );
RegQueryValueEx( hKey, "ProductType", NULL, NULL,
(LPBYTE) szProductType, &dwBufLen);
RegCloseKey( hKey );
if ( lstrcmpi( "WINNT", szProductType) == 0 )
versionStrs.Append(hsStrcpy( "Professional " ));
if ( lstrcmpi( "LANMANNT", szProductType) == 0 )
versionStrs.Append(hsStrcpy( "Server " ));
if ( lstrcmpi( "SERVERNT", szProductType) == 0 )
versionStrs.Append(hsStrcpy( "Advanced Server " ));
}
// Display version, service pack (if any), and build number.
if ( osvi.dwMajorVersion <= 4 )
{
versionStrs.Append(hsStrcpy (xtl::format("version %d.%d %s (Build %d)\n",
osvi.dwMajorVersion,
osvi.dwMinorVersion,
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF).c_str()));
}
else
{
versionStrs.Append(hsStrcpy (xtl::format("%s (Build %d)\n",
osvi.szCSDVersion,
osvi.dwBuildNumber & 0xFFFF).c_str()));
}
break;
case VER_PLATFORM_WIN32_WINDOWS:
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{
versionStrs.Append(hsStrcpy ("Microsoft Windows 95 "));
if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
versionStrs.Append(hsStrcpy("OSR2 " ));
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
versionStrs.Append(hsStrcpy ("Microsoft Windows 98 "));
if ( osvi.szCSDVersion[1] == 'A' )
versionStrs.Append(hsStrcpy("SE " ));
}
if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
{
versionStrs.Append(hsStrcpy ("Microsoft Windows Me "));
}
break;
case VER_PLATFORM_WIN32s:
versionStrs.Append(hsStrcpy ("Microsoft Win32s "));
break;
}
versionStrs.Append(nil); // terminator
return versionStrs.DetachArray();
#else
return nil;
#endif
}
#ifdef HS_BUILD_FOR_WIN32
static RTL_OSVERSIONINFOW s_WinVer;
const RTL_OSVERSIONINFOW& hsGetWindowsVersion()
{
static bool done = false;
if (!done) {
memset(&s_WinVer, 0, sizeof(RTL_OSVERSIONINFOW));
HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
hsAssert(ntdll, "Failed to LoadLibrary on ntdll???");
if (ntdll) {
s_WinVer.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
typedef LONG(WINAPI* RtlGetVersionPtr)(RTL_OSVERSIONINFOW*);
RtlGetVersionPtr getVersion = (RtlGetVersionPtr)GetProcAddress(ntdll, "RtlGetVersion");
hsAssert(getVersion, "Could not find RtlGetVersion in ntdll");
if (getVersion) {
getVersion(&s_WinVer);
done = true;
}
}
FreeLibrary(ntdll);
}
return s_WinVer;
}
#endif

View File

@ -0,0 +1,204 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsUtils_Defined
#define hsUtils_Defined
#include "HeadSpin.h"
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
int hsStrlen(const char src[]);
char* hsStrcpy(char dstOrNil[], const char src[]);
void hsStrcat(char dst[], const char src[]);
hsBool hsStrEQ(const char s1[], const char s2[]);
hsBool hsStrCaseEQ(const char* s1, const char* s2);
char* hsScalarToStr(hsScalar);
int hsRemove(const char* filename);
void hsCPathToMacPath(char* dst, char* fname);
void hsStrLower(char *s);
char * hsFormatStr(const char * fmt, ...); // You are responsible for returned memory.
char * hsFormatStrV(const char * fmt, va_list args); // You are responsible for returned memory.
// A pstring has a length byte at the beginning, and no trailing 0
char* hsP2CString(const UInt8 pstring[], char cstring[]);
UInt8* hsC2PString(const char cstring[], UInt8 pstring[]);
inline char* hsStrcpy(const char src[])
{
return hsStrcpy(nil, src);
}
inline char *hsStrncpy(char *strDest, const char *strSource, size_t count)
{
char *temp = strncpy(strDest, strSource, count-1);
strDest[count-1] = 0;
return temp;
}
wchar_t *hsStringToWString( const char *str );
void hsStringToWString( wchar_t *dst, const char *src );
char *hsWStringToString( const wchar_t *str );
void hsWStringToString( char *dst, const wchar_t *src);
enum { // Kind of MessageBox...passed to hsMessageBox
hsMessageBoxAbortRetyIgnore,
hsMessageBoxNormal, // Just Ok
hsMessageBoxOkCancel,
hsMessageBoxRetryCancel,
hsMessageBoxYesNo,
hsMessageBoxYesNoCancel,
};
enum {
hsMessageBoxIconError,
hsMessageBoxIconQuestion,
hsMessageBoxIconExclamation,
hsMessageBoxIconAsterisk,
};
enum { // RETURN VALUES FROM hsMessageBox
hsMBoxOk = 1, // OK button was selected.
hsMBoxCancel, // Cancel button was selected.
hsMBoxAbort, // Abort button was selected.
hsMBoxRetry, // Retry button was selected.
hsMBoxIgnore, // Ignore button was selected.
hsMBoxYes, // Yes button was selected.
hsMBoxNo // No button was selected.
};
extern bool hsMessageBox_SuppressPrompts;
int hsMessageBox(const char message[], const char caption[], int kind, int icon=hsMessageBoxIconAsterisk);
int hsMessageBox(const wchar_t message[], const wchar_t caption[], int kind, int icon=hsMessageBoxIconAsterisk);
int hsMessageBoxWithOwner(void* owner, const char message[], const char caption[], int kind, int icon=hsMessageBoxIconAsterisk);
int hsMessageBoxWithOwner(void* owner, const wchar_t message[], const wchar_t caption[], int kind, int icon=hsMessageBoxIconAsterisk);
inline hsBool hsCompare(hsScalar a, hsScalar b, hsScalar delta=0.0001)
{
return (fabs(a - b) < delta);
}
// flag testing / clearing
#define hsCheckBits(f,c) ((f & c)==c)
#define hsTestBits(f,b) ( (f) & (b) )
#define hsSetBits(f,b) ( (f) |= (b) )
#define hsClearBits(f,b) ( (f) &= ~(b) )
#define hsToggleBits(f,b) ( (f) ^= (b) )
#define hsChangeBits(f,b,t) ( t ? hsSetBits(f,b) : hsClearBits(f,b) )
#if HS_BUILD_FOR_WIN32
#define hsVsnprintf _vsnprintf
#define hsVsnwprintf _vsnwprintf
#define snprintf _snprintf
#define snwprintf _snwprintf
#define hsSnprintf snprintf
#define hsSnwprintf snwprintf
#else
#define hsVsnprintf vsnprintf
#define hsWvnwprintf vsnwprintf
#define hsSnprintf snprintf
#define hsSnwprintf snwprintf
#define _snprintf snprintf
#define _snwprintf snwprintf
#endif
#if HS_BUILD_FOR_UNIX || HS_BUILD_FOR_PS2
#define _stricmp(s1, s2) strcasecmp(s1, s2)
#define _strnicmp(s1, s2, n) strncasecmp(s1, s2, n)
#define stricmp(s1, s2) strcasecmp(s1, s2)
#define strnicmp(s1, s2, n) strncasecmp(s1, s2, n)
#define _fileno(n) fileno(n)
#elif HS_BUILD_FOR_MAC // HS_BUILD_FOR_UNIX || HS_BUILD_FOR_PS2
int hsStrcasecmp(const char s1[], const char s2[]);
int hsStrncasecmp(const char s1[], const char s2[], int n);
#define _stricmp(s1, s2) hsStrcasecmp(s1, s2)
#define _strnicmp(s1, s2, n) hsStrncasecmp(s1, s2, n)
#endif // HS_BUILD_FOR_UNIX || HS_BUILD_FOR_PS2
/////////////////////////////
// Physical memory functions
/////////////////////////////
enum MemSpec
{
kBlows = 0, // Less than 128
kAcceptable, // Less than 256
kOptimal // 256 or greater
};
UInt32 hsPhysicalMemory();
MemSpec hsMemorySpec();
inline int hsRandMax() { return 32767; }
inline float hsRandNorm() { return 1.f / 32767.f; } // multiply by hsRand to get randoms ranged [0..1]
int hsRand(void);
void hsRandSeed(int seed);
#if HS_BUILD_FOR_MAC
FILE* hsFopen(const char name[], const char mode[]); // handles path names with /s
#elif HS_BUILD_FOR_PS2 // HS_BUILD_FOR_MAC
int hsPS2Open(const char name[], const char mode[]);
void hsPS2Close( int file );
#else // HS_BUILD_FOR_MAC
#define hsFopen(name, mode) fopen(name, mode)
#endif // HS_BUILD_FOR_MAC
char** DisplaySystemVersion();
#endif // hsUtils_Defined

View File

@ -0,0 +1,353 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsWide.h"
/////////////////////////////////////////////////////////////////////////
inline hsBool OverflowAdd(UInt32* sum, UInt32 a, UInt32 b)
{
*sum = a + b;
return (a | b) > *sum; // true if overflow
}
/*
Return the overflow from adding the three longs into a signed-wide
wide = (high << 32) + (middle << 16) + low
*/
inline hsBool SetWide3(hsWide* target, Int32 high, UInt32 middle, UInt32 low)
{
hsAssert(high >= 0, "high is neg");
target->fLo = low + (middle << 16);
target->fHi = high + (middle >> 16) + (((low >> 16) + (UInt16)middle) >> 16);
return target->fHi < 0; // true if overflow
}
/////////////////////////////////////////////////////////////////////////
hsWide* hsWide::Mul(Int32 src1, Int32 src2)
{
int neg = 0;
if (src1 < 0)
{ src1 = -src1;
neg = ~0;
}
if (src2 < 0)
{ src2 = -src2;
neg = ~neg;
}
UInt32 a = src1 >> 16;
UInt32 b = (UInt16)src1;
UInt32 c = src2 >> 16;
UInt32 d = (UInt16)src2;
(void)SetWide3(this, a * c, a * d + c * b, b * d);
if (neg)
this->Negate();
return this;
}
hsWide* hsWide::Mul(Int32 A)
{
int neg = 0;
UInt32 B = fLo;
Int32 C = fHi;
Int32 tmp;
UInt32 clo,blo,bhi,alo;
if (A < 0)
{ A = -A;
neg = ~0;
}
if (WIDE_ISNEG(C, B))
{ WIDE_NEGATE(C, B);
neg = ~neg;
}
UInt32 ahi = A >> 16;
UInt32 chi = C >> 16;
if (ahi != 0 && chi != 0)
goto OVER_FLOW;
alo = (UInt16)A;
bhi = B >> 16;
blo = (UInt16)B;
clo = (UInt16)C;
tmp = alo * clo;
if (tmp < 0 || SetWide3(this, tmp, alo * bhi, alo * blo))
goto OVER_FLOW;
if (chi != 0)
{ UInt32 Vh = alo * chi;
if (Vh >> 15)
goto OVER_FLOW;
if (((this->fHi >> 16) + (UInt16)Vh) >> 15)
goto OVER_FLOW;
this->fHi += Vh << 16;
}
else // ahi != 0 && chi == 0
{ hsWide w;
UInt32 Vh = ahi * clo;
if (Vh >> 16)
goto OVER_FLOW;
tmp = ahi * bhi;
if (tmp < 0 || SetWide3(&w, tmp, ahi * blo, 0))
goto OVER_FLOW;
if (((w.fHi >> 16) + (UInt16)Vh) >> 15)
goto OVER_FLOW;
w.fHi += Vh << 16;
this->Add(&w);
}
if (neg)
this->Negate();
return this;
OVER_FLOW:
*this = neg ? kNegInfinity64 : kPosInfinity64;
return this;
}
hsWide* hsWide::Div(Int32 denom)
{
if (denom == 0)
{ if (this->IsNeg())
{ hsSignalMathUnderflow();
*this = kNegInfinity64;
}
else
{ hsSignalMathOverflow();
*this = kPosInfinity64;
}
return this;
}
int neg = 0;
Int32 resultH = 0;
UInt32 resultL = 0;
Int32 numerH = this->fHi;
UInt32 numerL = this->fLo;
if (denom < 0)
{ denom = -denom;
neg = ~0;
}
if (WIDE_ISNEG(numerH, numerL))
{ WIDE_NEGATE(numerH, numerL);
neg = ~neg;
}
WIDE_ADDPOS(numerH, numerL, denom >> 1); // add denom/2 to get a round result
UInt32 curr = (UInt32)numerH >> 31;
for (int i = 0; i < 64; i++)
{
WIDE_SHIFTLEFT(resultH, resultL, resultH, resultL, 1);
if (UInt32(denom) <= curr)
{
resultL |= 1;
curr -= denom;
}
WIDE_SHIFTLEFT(numerH, numerL, numerH, numerL, 1);
curr = (curr << 1) | ((UInt32)numerH >> 31);
}
if (neg)
WIDE_NEGATE(resultH, resultL);
return this->Set(resultH, resultL);
}
hsWide* hsWide::Div(const hsWide* denom)
{
hsWide d = *denom;
int shift = 0;
while (d.IsWide())
{ (void)d.ShiftRight(1);
shift += 1;
}
if (shift)
{ d = *denom;
(void)this->RoundRight(shift);
(void)d.RoundRight(shift);
}
return this->Div(d.AsLong());
}
inline int MaxLeftShift(const hsWide* w)
{
Int32 hi = w->fHi;
if (hi == 0)
return 31;
else
{ int shift = -1;
if (hi < 0) hi = -hi;
do {
hi <<= 1;
shift += 1;
} while (hi > 0);
return shift;
}
}
hsFixed hsWide::FixDiv(const hsWide* denom) const
{
hsWide num = *this;
hsWide den = *denom;
int maxShift = MaxLeftShift(this);
if (maxShift >= 16) // easy case
(void)num.ShiftLeft(16);
else
{ (void)num.ShiftLeft(maxShift);
(void)den.RoundRight(16 - maxShift);
}
return num.Div(&den)->AsLong();
}
hsFract hsWide::FracDiv(const hsWide* denom) const
{
hsWide num = *this;
hsWide den = *denom;
int maxShift = MaxLeftShift(this);
if (maxShift >= 30) // easy case
(void)num.ShiftLeft(30);
else
{ (void)num.ShiftLeft(maxShift);
(void)den.RoundRight(30 - maxShift);
}
return num.Div(&den)->AsLong();
}
////////////////////////////////////////////////////////////////////////////////////
Int32 hsWide::Sqrt() const
{
int bits = 32;
UInt32 root = 0;
UInt32 valueH = (UInt32)fHi;
UInt32 valueL = fLo;
UInt32 currH = 0;
UInt32 currL = 0;
UInt32 guessH, guessL;
do {
WIDE_SHIFTLEFT(currH, currL, currH, currL, 2);
currL |= TOP2BITS(valueH);
WIDE_SHIFTLEFT(valueH, valueL, valueH, valueL, 2);
WIDE_SHIFTLEFT(guessH, guessL, 0, root, 2);
root <<= 1;
if (WIDE_LESSTHAN(guessH, guessL, currH, currL))
{ WIDE_ADDPOS(guessH, guessL, 1);
WIDE_SUBWIDE(currH, currL, guessH, guessL);
root |= 1;
}
} while (--bits);
#if HS_PIN_MATH_OVERFLOW
if ((Int32)root < 0)
return kPosInfinity32;
#endif
return (Int32)root;
}
Int32 hsWide::CubeRoot() const
{
int bits = 21;
UInt32 root = 0;
UInt32 valueH = (UInt32)fHi;
UInt32 valueL = fLo;
UInt32 currH, currL;
UInt32 guessH, guessL;
hsBool neg = false;
if (WIDE_ISNEG(valueH, valueL))
{ neg = true;
WIDE_NEGATE(valueH, valueL);
}
currH = currL = 0;
WIDE_SHIFTLEFT(valueH, valueL, valueH, valueL, 1);
do {
WIDE_SHIFTLEFT(currH, currL, currH, currL, 3);
currL |= TOP3BITS(valueH);
WIDE_SHIFTLEFT(valueH, valueL, valueH, valueL, 3);
root <<= 1;
hsWide w;
w.Mul(root, root)->Add(root);
#if 0
w.Mul(3);
#else
hsWide w2 = w;
w.ShiftLeft(1)->Add(&w2);
#endif
guessH = (UInt32)w.fHi;
guessL = w.fLo;
if (WIDE_LESSTHAN(guessH, guessL, currH, currL))
{ WIDE_ADDPOS(guessH, guessL, 1);
WIDE_SUBWIDE(currH, currL, guessH, guessL);
root |= 1;
}
} while (--bits);
if (neg)
root = -Int32(root);
return (Int32)root;
}

View File

@ -0,0 +1,221 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsWideDefined
#define hsWideDefined
#include "hsTypes.h"
struct hsWide {
Int32 fHi;
UInt32 fLo;
hsWide* Set(Int32 lo) { fLo = lo; if (lo < 0) fHi = -1L; else fHi = 0; return this; }
hsWide* Set(Int32 hi, UInt32 lo) { fHi = hi; fLo = lo; return this; }
inline hsBool IsNeg() const { return fHi < 0; }
inline hsBool IsPos() const { return fHi > 0 || (fHi == 0 && fLo != 0); }
inline hsBool IsZero() const { return fHi == 0 && fLo == 0; }
inline hsBool IsWide() const;
hsBool operator==(const hsWide& b) const { return fHi == b.fHi && fLo == b.fLo; }
hsBool operator<(const hsWide& b) const { return fHi < b.fHi || fHi == b.fHi && fLo < b.fLo; }
hsBool operator>( const hsWide& b) const { return fHi > b.fHi || fHi == b.fHi && fLo > b.fLo; }
hsBool operator!=( const hsWide& b) const { return !( *this == b); }
hsBool operator<=(const hsWide& b) const { return !(*this > b); }
hsBool operator>=(const hsWide& b) const { return !(*this < b); }
inline hsWide* Negate();
inline hsWide* Add(Int32 scaler);
inline hsWide* Add(const hsWide* a);
inline hsWide* Sub(const hsWide* a);
inline hsWide* ShiftLeft(unsigned shift);
inline hsWide* ShiftRight(unsigned shift);
inline hsWide* RoundRight(unsigned shift);
inline Int32 AsLong() const; // return bits 31-0, checking for over/under flow
inline hsFixed AsFixed() const; // return bits 47-16, checking for over/under flow
inline hsFract AsFract() const; // return bits 61-30, checking for over/under flow
hsWide* Mul(Int32 a); // this updates the wide
hsWide* Mul(Int32 a, Int32 b); // this sets the wide
hsWide* Div(Int32 denom); // this updates the wide
hsWide* Div(const hsWide* denom); // this updates the wide
hsFixed FixDiv(const hsWide* denom) const;
hsFract FracDiv(const hsWide* denom) const;
Int32 Sqrt() const;
Int32 CubeRoot() const;
#if HS_CAN_USE_FLOAT
double AsDouble() const { return fHi * double(65536) * double(65536) + fLo; }
hsWide* Set(double d)
{
Int32 hi = Int32(d / double(65536) / double(65536));
Int32 lo = Int32(d - double(hi));
return Set(hi, lo);
}
#endif
};
const hsWide kPosInfinity64 = { kPosInfinity32, 0xffffffff };
const hsWide kNegInfinity64 = { kNegInfinity32, 0 };
/////////////////////// Inline implementations ///////////////////////
#define TOP2BITS(n) (UInt32(n) >> 30)
#define TOP3BITS(n) (UInt32(n) >> 29)
#if HS_PIN_MATH_OVERFLOW && HS_DEBUG_MATH_OVERFLOW
#define hsSignalMathOverflow() hsDebugMessage("Math overflow", 0)
#define hsSignalMathUnderflow() hsDebugMessage("Math underflow", 0)
#else
#define hsSignalMathOverflow()
#define hsSignalMathUnderflow()
#endif
#define WIDE_ISNEG(hi, lo) (Int32(hi) < 0)
#define WIDE_LESSTHAN(hi, lo, hi2, lo2) ((hi) < (hi2) || (hi) == (hi2) && (lo) < (lo2))
#define WIDE_SHIFTLEFT(outH, outL, inH, inL, shift) do { (outH) = ((inH) << (shift)) | ((inL) >> (32 - (shift))); (outL) = (inL) << (shift); } while (0)
#define WIDE_NEGATE(hi, lo) do { (hi) = ~(hi); if (((lo) = -Int32(lo)) == 0) (hi) += 1; } while (0)
#define WIDE_ADDPOS(hi, lo, scaler) do { UInt32 tmp = (lo) + (scaler); if (tmp < (lo)) (hi) += 1; (lo) = tmp; } while (0)
#define WIDE_SUBWIDE(hi, lo, subhi, sublo) do { (hi) -= (subhi); if ((lo) < (sublo)) (hi) -= 1; (lo) -= (sublo); } while (0)
/////////////////////// Inline implementations ///////////////////////
inline hsWide* hsWide::Negate()
{
WIDE_NEGATE(fHi, fLo);
return this;
}
inline hsWide* hsWide::Add(Int32 scaler)
{
if (scaler >= 0)
WIDE_ADDPOS(fHi, fLo, scaler);
else
{ scaler = -scaler;
if (fLo < UInt32(scaler))
fHi--;
fLo -= scaler;
}
return this;
}
inline hsWide* hsWide::Add(const hsWide* a)
{
UInt32 newLo = fLo + a->fLo;
fHi += a->fHi;
if (newLo < (fLo | a->fLo))
fHi++;
fLo = newLo;
return this;
}
inline hsWide* hsWide::Sub(const hsWide* a)
{
WIDE_SUBWIDE(fHi, fLo, a->fHi, a->fLo);
return this;
}
inline hsWide* hsWide::ShiftLeft(unsigned shift)
{
WIDE_SHIFTLEFT(fHi, fLo, fHi, fLo, shift);
return this;
}
inline hsWide* hsWide::ShiftRight(unsigned shift)
{
fLo = (fLo >> shift) | (fHi << (32 - shift));
fHi = fHi >> shift; // fHi >>= shift; Treated as logical shift on CW9-WIN32, which breaks for fHi < 0
return this;
}
inline hsWide* hsWide::RoundRight(unsigned shift)
{
return this->Add(1L << (shift - 1))->ShiftRight(shift);
}
inline Int32 hsWide::AsLong() const
{
#if HS_PIN_MATH_OVERFLOW
if (fHi > 0 || fHi == 0 && (Int32)fLo < 0)
{ hsSignalMathOverflow();
return kPosInfinity32;
}
if (fHi < -1L || fHi == -1L && (Int32)fLo >= 0)
{ hsSignalMathOverflow();
return kNegInfinity32;
}
#endif
return (Int32)fLo;
}
inline hsBool hsWide::IsWide() const
{
return (fHi > 0 || fHi == 0 && (Int32)fLo < 0) || (fHi < -1L || fHi == -1L && (Int32)fLo >= 0);
}
inline hsFixed hsWide::AsFixed() const
{
hsWide tmp = *this;
return tmp.RoundRight(16)->AsLong();
}
inline hsFract hsWide::AsFract() const
{
hsWide tmp = *this;
return tmp.RoundRight(30)->AsLong();
}
#endif

View File

@ -0,0 +1,62 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef HSWINDOWHNDL_inc
#define HSWINDOWHNDL_inc
#include "HeadSpin.h"
// decide what hsWindowHndl is
#if HS_BUILD_FOR_MAC
#include <QuickDraw.h>
#ifdef HS_MAC_CARBON
typedef WindowPtr hsWindowHndl;
#else
typedef GrafPtr hsWindowHndl;
#endif
#endif
#if HS_BUILD_FOR_WIN32
typedef struct HWND__ * hsWindowHndl;
#elif HS_BUILD_FOR_PS2 || HS_BUILD_FOR_UNIX
typedef int* hsWindowHndl;
#endif
#endif

View File

@ -0,0 +1,61 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsConfig.h"
#if HS_BUILD_FOR_WIN32
#ifndef __AFX_H__ // MFC apps won't let us include windows from here. =(
#if defined(_MSC_VER) && _MSC_VER >= 1600
#define _WIN32_WINNT 0x0501
#else
#define _WIN32_WINNT 0x0400
#endif
#include <WinSock2.h>
#include <Windows.h>
#endif // __AFX_H__
const RTL_OSVERSIONINFOW& hsGetWindowsVersion();
#endif // HS_BUILD_FOR_WIN32

View File

@ -0,0 +1,3 @@
-Removed code for matrices, planes, xformTriangles, and lights from hsGeometry3.
Would like something generic here for consistent error handling. m&p

View File

@ -0,0 +1,65 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
///////////////////////////////////////////////////////////////////////////////
// //
// pcSmallRect - A tiny Int16-based 2D rectangle class //
// //
///////////////////////////////////////////////////////////////////////////////
#include "pcSmallRect.h"
#include "hsStream.h"
void pcSmallRect::Read( hsStream *s )
{
s->ReadSwap( &fX );
s->ReadSwap( &fY );
s->ReadSwap( &fWidth );
s->ReadSwap( &fHeight );
}
void pcSmallRect::Write( hsStream *s )
{
s->WriteSwap( fX );
s->WriteSwap( fY );
s->WriteSwap( fWidth );
s->WriteSwap( fHeight );
}

View File

@ -0,0 +1,80 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
///////////////////////////////////////////////////////////////////////////////
// //
// pcSmallRect - A tiny Int16-based 2D rectangle class //
// //
///////////////////////////////////////////////////////////////////////////////
// Note: I'm introducing the concept here that new-style coreLib files/classes
// are named with the "pc" prefix, just as featureLib uses "pf" and nucleusLib
// uses "pn". I have no clue if this is kosher or good, but I'm doing it anyway.
// Feel free to change if desired
#ifndef _pcSmallRect_h
#define _pcSmallRect_h
#include "hsTypes.h"
class hsStream;
class pcSmallRect
{
public:
Int16 fX, fY, fWidth, fHeight;
pcSmallRect() { Empty(); }
pcSmallRect( Int16 x, Int16 y, Int16 w, Int16 h ) { Set( x, y, w, h ); }
void Set( Int16 x, Int16 y, Int16 w, Int16 h ) { fX = x; fY = y; fWidth = w; fHeight = h; }
void Empty( void ) { fX = fY = fWidth = fHeight = 0; }
Int16 GetRight( void ) const { return fX + fWidth; }
Int16 GetBottom( void ) const { return fY + fHeight; }
void Read( hsStream *s );
void Write( hsStream *s );
hsBool Contains( Int16 x, Int16 y ) { if( x >= fX && x <= fX + fWidth && y >= fY && y <= fY + fHeight ) return true; return false; }
};
#endif // _pcSmallRect_h

View File

@ -0,0 +1,203 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsUtils.h"
#include "plGeneric.h"
plGeneric::plGeneric(): fType(kNull), fBoolVal(false), fIntVal(0), fFloatVal(0.0) {}
plGeneric::plGeneric(const bool& val): fType(kBool), fBoolVal(val), fIntVal(0), fFloatVal(0.0) {}
plGeneric::plGeneric(const int& val): fType(kInt), fBoolVal(false), fIntVal(val), fFloatVal(0.0) {}
plGeneric::plGeneric(const double& val): fType(kFloat), fBoolVal(false), fIntVal(0), fFloatVal(val) {}
plGeneric::plGeneric(const char* val): fType(kString), fBoolVal(false), fIntVal(0), fFloatVal(0.0)
{
wchar_t* temp = hsStringToWString(val);
fStringVal = temp;
delete [] temp;
}
plGeneric::plGeneric(const std::string& val): fType(kString), fBoolVal(false), fIntVal(0), fFloatVal(0.0)
{
wchar_t* temp = hsStringToWString(val.c_str());
fStringVal = temp;
delete [] temp;
}
plGeneric::plGeneric(const wchar_t* val): fType(kString), fBoolVal(false), fIntVal(0), fFloatVal(0.0),
fStringVal(val) {}
plGeneric::plGeneric(const std::wstring& val): fType(kString), fBoolVal(false), fIntVal(0), fFloatVal(0.0),
fStringVal(val) {}
void plGeneric::IReset()
{
fType = kNull;
fBoolVal = false;
fIntVal = 0;
fFloatVal = 0.0;
fStringVal = L"";
}
plGeneric& plGeneric::operator=(const bool& val)
{
IReset();
fType = kBool;
fBoolVal = val;
return *this;
}
plGeneric& plGeneric::operator=(const int& val)
{
IReset();
fType = kInt;
fIntVal = val;
return *this;
}
plGeneric& plGeneric::operator=(const double& val)
{
IReset();
fType = kFloat;
fFloatVal = val;
return *this;
}
plGeneric& plGeneric::operator=(const char* val)
{
IReset();
fType = kString;
wchar_t* temp = hsStringToWString(val);
fStringVal = temp;
delete [] temp;
return *this;
}
plGeneric& plGeneric::operator=(const std::string& val)
{
IReset();
fType = kString;
wchar_t* temp = hsStringToWString(val.c_str());
fStringVal = temp;
delete [] temp;
return *this;
}
plGeneric& plGeneric::operator=(const wchar_t* val)
{
IReset();
fType = kString;
fStringVal = val;
return *this;
}
plGeneric& plGeneric::operator=(const std::wstring& val)
{
IReset();
fType = kString;
fStringVal = val;
return *this;
}
int plGeneric::Write(hsStream* stream)
{
stream->WriteByte((UInt8)fType);
switch (fType)
{
case kNull:
break; // nothing to write
case kBool:
stream->WriteBool(fBoolVal);
break;
case kInt:
stream->WriteSwap(fIntVal);
break;
case kFloat:
stream->WriteSwap(fFloatVal);
break;
case kString:
stream->WriteSafeWString(fStringVal.c_str());
break;
}
return stream->GetPosition();
}
int plGeneric::Read(hsStream* stream)
{
IReset();
fType = (GenericType)stream->ReadByte();
switch (fType)
{
case kNull:
break; // nothing to read
case kBool:
fBoolVal = (stream->ReadBool() != 0);
break;
case kInt:
stream->ReadSwap(&fIntVal);
break;
case kFloat:
stream->ReadSwap(&fFloatVal);
break;
case kString:
{
wchar_t* temp = stream->ReadSafeWString();
if (temp)
{
fStringVal = temp;
delete [] temp;
}
}
break;
}
return stream->GetPosition();
}

View File

@ -0,0 +1,101 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef __PLGENERIC_H__
#define __PLGENERIC_H__
#include "hsStream.h"
#include "hsStlUtils.h"
class plGeneric
{
public:
enum GenericType
{
kNull,
kBool,
kInt,
kFloat,
kString
};
private:
GenericType fType;
bool fBoolVal;
int fIntVal;
double fFloatVal;
std::wstring fStringVal;
void IReset();
public:
plGeneric();
plGeneric(const bool& val);
plGeneric(const int& val);
plGeneric(const double& val);
plGeneric(const char* val);
plGeneric(const std::string& val);
plGeneric(const wchar_t* val);
plGeneric(const std::wstring& val);
void SetToNull() {IReset();}
plGeneric& operator=(const bool& val);
plGeneric& operator=(const int& val);
plGeneric& operator=(const double& val);
plGeneric& operator=(const char* val);
plGeneric& operator=(const std::string& val);
plGeneric& operator=(const wchar_t* val);
plGeneric& operator=(const std::wstring& val);
// the cast functions will NOT cast from one type to another, use
// GetType() to determine the type of parameter, then cast it to that type
GenericType GetType() const {return fType;}
operator const bool() const {return fBoolVal;}
operator const int() const {return fIntVal;}
operator const double() const {return fFloatVal;}
operator const wchar_t*() const {return fStringVal.c_str();}
operator const std::wstring() const {return fStringVal;}
int Write(hsStream* stream);
int Read(hsStream* stream);
};
#endif // __PLGENERIC_H__

View File

@ -0,0 +1,186 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plLoadMask.h"
#include "hsStream.h"
#include "hsTemplates.h"
#include "plQuality.h"
///////////////////////////////////////////////////////////////////
// Global settings first. Implemented here for convenience (mine).
// They could go in pnSingletons, but they require LoadMask to link
// (and compile) anyway. Mostly, I just wanted the plQuality interface
// in its own header file so you would know to include plQuality.h
// to get plQuality::Func, rather than the less obvious plLoadMask.h.
///////////////////////////////////////////////////////////////////
int plQuality::fQuality = 0;
int plQuality::fCapability = 0;
void plQuality::SetQuality(int q)
{
fQuality = q;
plLoadMask::SetGlobalQuality(q);
}
// Set by the pipeline according to platform capabilities.
void plQuality::SetCapability(int c)
{
fCapability = c;
plLoadMask::SetGlobalCapability(c);
}
///////////////////////////////////////////////////////////////////
// Now the LoadMask implementation.
///////////////////////////////////////////////////////////////////
const plLoadMask plLoadMask::kAlways;
UInt8 plLoadMask::fGlobalQuality = UInt8(1);
UInt8 plLoadMask::fGlobalCapability = UInt8(0);
void plLoadMask::Read(hsStream* s)
{
// read as packed byte
UInt8 qc;
s->LogReadSwap(&qc,"Quality|Capabilty");
fQuality[0] = (qc & 0xf0) >> 4;
fQuality[1] = (qc & 0x0f);
// Or in the bits we stripped on write, or else IsUsed() won't work.
fQuality[0] |= 0xf0;
fQuality[1] |= 0xf0;
}
void plLoadMask::Write(hsStream* s) const
{
// write packed into 1 byte
UInt8 qc = (fQuality[0]<<4) | (fQuality[1] & 0xf);
s->WriteSwap(qc);
}
UInt32 plLoadMask::ValidateReps(int num, const int quals[], const int caps[])
{
UInt32 retVal = 0;
int i;
for( i = 1; i < num; i++ )
{
int j;
for( j = 0; j < i; j++ )
{
if( (quals[i] >= quals[j]) && (caps[i] >= caps[j]) )
{
// Bogus, this would double load.
retVal |= (1 << i);
}
}
}
return retVal;
}
UInt32 plLoadMask::ValidateMasks(int num, plLoadMask masks[])
{
UInt32 retVal = 0;
int i;
for( i = 0; i < num; i++ )
{
if( !masks[i].fQuality[0] && !masks[i].fQuality[1] )
retVal |= (1 << i);
int j;
for( j = 0; j < i; j++ )
{
int k;
for( k = 0; k <= kMaxCap; k++ )
{
if( masks[i].fQuality[k] & masks[j].fQuality[k] )
{
masks[i].fQuality[k] &= ~masks[j].fQuality[k];
retVal |= (1 << i);
}
}
}
}
return retVal;
}
hsBool plLoadMask::ComputeRepMasks(
int num,
const int quals[],
const int caps[],
plLoadMask masks[])
{
hsBool retVal = false; // Okay till proven otherwise.
int i;
for( i = 0; i < num; i++ )
{
int k;
for( k = 0; k <= kMaxCap; k++ )
{
// Q starts off the bits higher than or equal to 1 << qual.
// I.e. we just turned off all lower quality bits.
UInt8 q = ~( (1 << quals[i]) - 1 );
// For this cap level, if we require higher caps,
// turn off our quality (i.e. we won't load at this
// cap for any quality setting.
UInt8 c = caps[i] > kMaxCap ? kMaxCap : caps[i];
if( c > k )
q = 0;
// Turn off all bits already covered for this cap level
// so we never double load.
int j;
for( j = 0; j < i; j++ )
{
q &= ~masks[j].fQuality[k];
}
masks[i].fQuality[k] = q;
}
if( masks[i].NeverLoads() )
retVal = true;
}
return retVal;
}

View File

@ -0,0 +1,135 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plLoadMask_inc
#define plLoadMask_inc
#include "hsTypes.h"
template <class T> class hsTArray;
class hsStream;
class plLoadMask
{
public:
enum {
kMaxCap = 1
};
protected:
static UInt8 fGlobalQuality;
static UInt8 fGlobalCapability;
union {
UInt8 fQuality[kMaxCap+1];
UInt16 fMask;
};
static void SetGlobalQuality(int q) { fGlobalQuality = IBitToMask(q); }
static void SetGlobalCapability(int c) { if( c > kMaxCap ) c = kMaxCap; else if( c < 0 ) c = 0; fGlobalCapability = c; }
static UInt8 IBitToMask(int b) { hsAssert(b<8, "LoadMask: bit too large for byte"); return (1 << b); }
friend class plQuality;
public:
// Change this to a for loop on kMaxCap+1 if we ever get more caps.
plLoadMask() { fQuality[0] = fQuality[1] = 0xff; }
plLoadMask(UInt8 qLo, UInt8 qHi) { fQuality[0] = qLo; fQuality[1] = qHi; }
~plLoadMask() {}
hsBool DontLoad() const { return !(fQuality[fGlobalCapability] & fGlobalQuality); }
hsBool NeverLoads() const { return !(fQuality[0] && fQuality[1]); }
hsBool IsUsed() const { return (fQuality[0] != UInt8(-1)) || (fQuality[1] != UInt8(-1)); }
hsBool MatchesQuality(int q) const { return (IBitToMask(q) & (fQuality[0] | fQuality[1])) != 0; }
hsBool MatchesCapability(int c) const { return fQuality[c] != 0; }
hsBool MatchesQualityAndCapability(int q, int c) const { return IBitToMask(q) & fQuality[c]; }
hsBool MatchesCurrentQuality() const { return MatchesQuality(fGlobalQuality); }
hsBool MatchesCurrentCapability() const { return MatchesCapability(fGlobalCapability); }
hsBool MatchesCurrent() const { return !DontLoad(); }
UInt8 GetQualityMask(int cap) const { return fQuality[cap]; }
plLoadMask& SetMask(UInt8 lo, UInt8 hi) { fQuality[0] = lo; fQuality[1] = hi; return *this; }
plLoadMask& SetNever() { return SetMask(0,0); }
plLoadMask& SetAlways() { return SetMask(UInt8(-1), UInt8(-1)); }
plLoadMask& operator|=(const plLoadMask& m) { fMask |= m.fMask; return *this; }
plLoadMask& operator&=(const plLoadMask& m) { fMask &= m.fMask; return *this; }
int operator==(const plLoadMask& m) const { return fMask == m.fMask; }
int operator!=(const plLoadMask& m) const { return !(*this == m); }
// Only useful for sorting.
int operator<(const plLoadMask& m) const { return fMask < m.fMask; }
friend plLoadMask operator|(const plLoadMask& lhs, const plLoadMask& rhs) { plLoadMask r(lhs); r |= rhs; return r; }
friend plLoadMask operator&(const plLoadMask& lhs, const plLoadMask& rhs) { plLoadMask r(lhs); r &= rhs; return r; }
void Read(hsStream* s);
void Write(hsStream* s) const;
static const plLoadMask kAlways;
// Input lists are in order of preference, i.e. if rep[0] and rep[1] are both loadable based
// on the current settings, only rep[0] will be loaded. This implies some rules
// to avoid wasted reps (reps that would never get loaded). Basically:
// if( i < j ) then
// (quals[i] > quals[j]) || (caps[i] > caps[j])
//
// It doesn't break anything if that condition isn't met, it just means
// the latter one will never get loaded (have a load mask of zero).
// So, just to be a pal, we'll detect that condition and return based on it.
// i.e. Return true on invalid input (something will never get loaded).
//
// You can also pre-validate your input with ValidateReps, and/or validate
// the output with ValidateMasks. The return value is a bitmask of which
// items in the list had problems, so return of zero means A-OK.
//
static hsBool ComputeRepMasks(int num, const int quals[], const int caps[], plLoadMask masks[]);
static UInt32 ValidateReps(int num, const int quals[], const int caps[]);
static UInt32 ValidateMasks(int num, plLoadMask masks[]);
};
#endif // plLoadMask_inc

View File

@ -0,0 +1,83 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plQuality_inc
#define plQuality_inc
class plQuality
{
public:
enum
{
kMinimum = 0,
kPS_1_1 = 2,
kPS_1_4 = 3,
kPS_2_Plus = 4
};
protected:
// These two are instanciated in plLoadMask.cpp, as well as
// function implementations.
static int fQuality;
static int fCapability;
friend class plClient;
friend class plQualitySlider;
friend class plDXPipeline;
// Set by the app according to user preference.
static void SetQuality(int q);
// Set by the pipeline according to platform capabilities.
static void SetCapability(int c);
public:
// Set by the app according to user preference.
static int GetQuality() { return fQuality; }
// Set by the pipeline according to platform capabilities.
static int GetCapability() { return fCapability; }
};
#endif // plQuality_inc

View File

@ -0,0 +1,89 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plRefCnt_Defined
#define plRefCnt_Defined
#include "hsTypes.h"
// plRef count addes refcount abilities to any plCreatable
class plRefCnt
{ UInt32 fRefCnt;
public:
plRefCnt() : fRefCnt(1){}
~plRefCnt(){}
hsBool TimeToDelete() { return (fRefCnt == 1); }
void Incr() { fRefCnt++; }
void Decr() { fRefCnt--; }
};
#define DEFINE_REF_COUNT plRefCnt fMyRef;\
virtual void UnRef() { /*hsDebugCode(hsThrowIfFalse(fRefCnt >= 1);)*/if (fMyRef.TimeToDelete()) delete this; else fMyRef.Decr(); }\
virtual void Ref() { fMyRef.Incr(); }
/*
class hsRefCnt {
private:
Int32 fRefCnt;
public:
hsRefCnt() : fRefCnt(1) {}
virtual ~hsRefCnt();
Int32 RefCnt() const { return fRefCnt; }
virtual void UnRef();
virtual void Ref();
};
#define hsRefCnt_SafeRef(obj) do { if (obj) (obj)->Ref(); } while (0)
#define hsRefCnt_SafeUnRef(obj) do { if (obj) (obj)->UnRef(); } while (0)
#define hsRefCnt_SafeAssign(dst, src) \
do { \
hsRefCnt_SafeRef(src); \
hsRefCnt_SafeUnRef(dst); \
dst = src; \
} while (0)
*/
#endif

View File

@ -0,0 +1,105 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plRenderLevel_inc
#define plRenderLevel_inc
class plRenderLevel
{
public:
// A renderlevel is [Major bits 32..8]|[Minor bits 7..0]
// The major render level is further broken into 3 ranges.
// Range [0x00..0xff] - Blend onto the frame buffer (before even opaque objects)
// Range [0x0100..0xffff] - Opaque and nearly opaque objects
// Range [0x010000..0xffffff] - For blending objects (typically sorted amongst each other)
// The minor bits denote a slight difference in draw order. For example, a decal wants
// to be drawn after the opaque object it is applied to, but hopefully not very long after.
// The avatar gets a render priority of kDefRendMajorLevel,kAvatarRendMinorLevel. This puts
// it in the group of normal opaque objects with no render dependencies, but with the maximum
// permitted minor level. So it will be drawn after the opaque background, and the opaque background's
// decals, but before the first thing with a render dependency on the background (e.g. plants).
// Removed kAvatarBlendRendMinorLevel, not being used anywhere. mf
enum {
kOpaqueMajorLevel = 0x0,
kFBMajorLevel = 0x1,
kDefRendMajorLevel = 0x2,
kBlendRendMajorLevel = 0x4,
kLateRendMajorLevel = 0x8
};
enum {
kMajorShift = 28
};
enum {
kDefRendMinorLevel = 0x00,
kOpaqueMinorLevel = 0x0,
kMinorLevelMask = ((1 << kMajorShift) - 1),
kAvatarRendMinorLevel = kMinorLevelMask-1
};
public:
plRenderLevel() { Set(kDefRendMajorLevel, kDefRendMinorLevel); }
plRenderLevel(UInt32 l) : fLevel(l) {}
plRenderLevel(UInt32 major, UInt32 minor) { Set(major, minor); }
int operator==(const plRenderLevel& l) const { return fLevel == l.fLevel; }
int operator!=(const plRenderLevel& l) const { return fLevel != l.fLevel; }
int operator>(const plRenderLevel& l) const { return fLevel > l.fLevel; }
int operator<(const plRenderLevel& l) const { return fLevel < l.fLevel; }
int operator>=(const plRenderLevel& l) const { return fLevel >= l.fLevel; }
int operator<=(const plRenderLevel& l) const { return fLevel <= l.fLevel; }
UInt32 Level() const { return fLevel; }
UInt32 Minor() const { return UInt32(fLevel & kMinorLevelMask); }
UInt32 Major() const { return UInt32(fLevel >> kMajorShift); }
plRenderLevel& Set(UInt32 l) { fLevel = l; return *this; }
plRenderLevel& Set(UInt32 major, UInt32 minor) { fLevel = (UInt32(major) << kMajorShift) | UInt32(minor); return *this; }
UInt32 fLevel;
static plRenderLevel OpaqueRenderLevel() { return plRenderLevel(kOpaqueMajorLevel, kOpaqueMinorLevel); }
};
#endif // plRenderLevel_inc

View File

@ -0,0 +1,76 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plTweak_inc
#define plTweak_inc
template <typename T> class plTweak
{
public:
plTweak() {}
plTweak(const T& init) : fVal(init) {};
T fVal;
plTweak& operator=(const T& v) { fVal = v; return *this; }
operator T () const
{
return fVal;
}
};
#ifndef HS_DEBUGGING
#define plCONST(T) const T
#else // HS_DEBUGGING
#define plCONST(T) static plTweak<T>
#endif // HS_DEBUGGING
#define plConst(T) plCONST(T)
#endif // plTweak_inc

View File

@ -0,0 +1,389 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "hsBounds.h"
#include "hsStream.h"
#include "plViewTransform.h"
const hsScalar plViewTransform::kMinHither = 0.25f;
plViewTransform::plViewTransform()
: fFlags(kViewPortRelative),
fWidth(0),
fHeight(0)
{
fCameraToWorld.Reset();
fWorldToCamera.Reset();
fViewPortX.Set(0,1.f,1.f);
fViewPortY.Set(0,1.f,1.f);
fMapMin.Set(0.f, 0.f, 0.f);
fMapMax.Set(1.f, 1.f, 1.f);
}
void plViewTransform::Reset()
{
fFlags = kViewPortRelative;
fCameraToWorld.Reset();
fWorldToCamera.Reset();
fViewPortX.Set(0,1.f,1.f);
fViewPortY.Set(0,1.f,1.f);
}
void plViewTransform::ISetCameraToNDC() const
{
fCameraToNDC.Reset();
fCameraToNDC.NotIdentity();
if( GetOrthogonal() )
{
hsPoint3 worldSizeInv;
worldSizeInv.fX = hsScalarInvert( fMax.fX - fMin.fX ) * 2.f;
worldSizeInv.fY = hsScalarInvert( fMax.fY - fMin.fY ) * 2.f;
worldSizeInv.fZ = hsScalarInvert( fMax.fZ - fMin.fZ );
fCameraToNDC.fMap[0][0] = worldSizeInv.fX;
fCameraToNDC.fMap[0][3] = -fMin.fX * worldSizeInv.fX - hsScalar1;
fCameraToNDC.fMap[1][1] = worldSizeInv.fY;
fCameraToNDC.fMap[1][3] = -fMin.fY * worldSizeInv.fY - hsScalar1;
// Map Screen Z to range 0 (at hither) to 1 (at yon)
fCameraToNDC.fMap[2][2] = worldSizeInv.fZ;
fCameraToNDC.fMap[2][3] = -fMin.fZ * worldSizeInv.fZ;
}
else
{
fCameraToNDC.fMap[0][0] = 2.f / (fMax.fX - fMin.fX);
fCameraToNDC.fMap[0][2] = (fMax.fX + fMin.fX) / (fMax.fX - fMin.fX);
fCameraToNDC.fMap[1][1] = 2.f / (fMax.fY - fMin.fY);
fCameraToNDC.fMap[1][2] = (fMax.fY + fMin.fY) / (fMax.fY - fMin.fY);
fCameraToNDC.fMap[2][2] = fMax.fZ / (fMax.fZ - fMin.fZ);
fCameraToNDC.fMap[2][3] = -fMax.fZ * fMin.fZ / (fMax.fZ - fMin.fZ);
fCameraToNDC.fMap[3][2] = 1.f;
fCameraToNDC.fMap[3][3] = 0.f;
}
ISetFlag(kCameraToNDCSet);
}
void plViewTransform::SetViewPort(const hsPoint2& mins, const hsPoint2& maxs, hsBool relative)
{
fViewPortX.Set(mins.fX, maxs.fX, 1.f / (maxs.fX - mins.fX));
fViewPortY.Set(mins.fY, maxs.fY, 1.f / (maxs.fY - mins.fY));
ISetFlag(kViewPortRelative, relative);
}
hsScalarTriple plViewTransform::ScreenToNDC(const hsScalarTriple& scrP) const
{
hsPoint2 vpMin, vpMax;
GetViewPort(vpMin, vpMax);
hsPoint3 ndc;
ndc.fX = (scrP.fX - vpMin.fX) / (vpMax.fX - vpMin.fX) * 2.f - 1.f;
ndc.fY = (vpMax.fY - scrP.fY) / (vpMax.fY - vpMin.fY) * 2.f - 1.f;
ndc.fZ = scrP.fZ;
return ndc;
}
hsScalarTriple plViewTransform::NDCToScreen(const hsScalarTriple& ndc) const
{
hsPoint2 vpMin, vpMax;
GetViewPort(vpMin, vpMax);
hsPoint3 scrP;
scrP.fX = (ndc.fX + 1.f) * 0.5f * (vpMax.fX - vpMin.fX) + vpMin.fX;
scrP.fY = (-ndc.fY + 1.f) * 0.5f * (vpMax.fY - vpMin.fY) + vpMin.fY;
scrP.fZ = ndc.fZ;
return scrP;
}
hsScalarTriple plViewTransform::NDCToCamera(const hsScalarTriple& ndc) const
{
hsPoint3 camP;
hsScalar w = ndc.fZ;
const hsMatrix44& c2NDC = GetCameraToNDC();
camP.fX = (ndc.fX - c2NDC.fMap[0][2]) * w / c2NDC.fMap[0][0];
camP.fY = (ndc.fY - c2NDC.fMap[1][2]) * w / c2NDC.fMap[1][1];
camP.fZ = ndc.fZ;
return camP;
}
hsScalarTriple plViewTransform::CameraToNDC(const hsScalarTriple& camP) const
{
const hsMatrix44& c2NDC = GetCameraToNDC();
#ifdef MF_FLIP_SPARSE
// We count on the fact that we set up CameratToNDC, so we know where the
// zeros are. Also, note that the proper "* camP.fZ"'s are missing off the
// c2NDC.fMap[i][2] terms, because they just get cancelled out by the invW.
hsPoint3 ndc;
if( GetOrthogonal() )
{
ndc.fX = c2NDC.fMap[0][0] * camP.fX
+ c2NDC.fMap[0][2];
ndc.fY = c2NDC.fMap[1][1] * camP.fY
+ c2NDC.fMap[1][2];
ndc.fZ = c2NDC.fMap[2][2] * camP.fZ
+ c2NDC.fMap[2][3];
}
else
{
hsScalar invW = 1.f / camP.fZ;
ndc.fX = c2NDC.fMap[0][0] * camP.fX * invW
+ c2NDC.fMap[0][2];
ndc.fY = c2NDC.fMap[1][1] * camP.fY * invW
+ c2NDC.fMap[1][2];
ndc.fZ = c2NDC.fMap[2][2] * camP.fZ
+ c2NDC.fMap[2][3];
ndc.fZ *= invW;
}
#else // MF_FLIP_SPARSE
hsPoint3 ndc = c2NDC * hsPoint3(camP);
if( !GetOrthogonal() )
{
hsScalar invW = 1.f / camP.fZ;
ndc *= invW;
}
#endif // MF_FLIP_SPARSE
return ndc;
}
hsScalarTriple plViewTransform::NDCToMap(const hsScalarTriple& ndcP) const
{
hsPoint3 map;
map.fX = fMapMin.fX + (ndcP.fX + 1.f) * 0.5f * (fMapMax.fX - fMapMin.fX);
map.fY = fMapMin.fY + (ndcP.fY + 1.f) * 0.5f * (fMapMax.fY - fMapMin.fY);
map.fZ = fMapMin.fZ + (ndcP.fZ + 1.f) * 0.5f * (fMapMax.fZ - fMapMin.fZ);
return map;
}
hsBool plViewTransform::SetProjection(const hsBounds3& bnd)
{
hsPoint3 maxs;
hsPoint3 mins;
if( IGetMaxMinsFromBnd(bnd, mins, maxs) )
{
SetView(mins, maxs);
return true;
}
return false;
}
hsBool plViewTransform::SetProjectionWorld(const hsBounds3& wBnd)
{
hsBounds3Ext cBnd = wBnd;
cBnd.Transform(&GetWorldToCamera());
return SetProjection(cBnd);
}
hsBool plViewTransform::IGetMaxMinsFromBnd(const hsBounds3& bnd, hsPoint3& mins, hsPoint3& maxs) const
{
if( bnd.GetMaxs().fZ <= kMinHither )
return false;
hsPoint3 minBnd = bnd.GetMins();
hsPoint3 maxBnd = bnd.GetMaxs();
// If the box intersects the hither plane, we'll need to chop it
// off.
if( minBnd.fZ < kMinHither )
{
minBnd.fZ = kMinHither;
}
mins.Set(minBnd.fX / minBnd.fZ, minBnd.fY / minBnd.fZ, minBnd.fZ);
maxs.Set(maxBnd.fX / minBnd.fZ, maxBnd.fY / minBnd.fZ, maxBnd.fZ);
return true;
}
hsBool plViewTransform::Intersect(const plViewTransform& view)
{
hsPoint3 mins;
hsPoint3 maxs;
hsBool retVal = true;
int i;
for( i = 0; i < 3; i++ )
{
mins[i] = hsMaximum(fMin[i], view.fMin[i]);
maxs[i] = hsMinimum(fMax[i], view.fMax[i]);
if( mins[i] >= maxs[i] )
{
mins[i] = maxs[i] = (mins[i] + maxs[i]) * 0.5f;
retVal = false;
}
}
SetView(mins, maxs);
return retVal;
}
hsBool plViewTransform::Union(const plViewTransform& view)
{
hsPoint3 mins;
hsPoint3 maxs;
int i;
for( i = 0; i < 3; i++ )
{
mins[i] = hsMinimum(fMin[i], view.fMin[i]);
maxs[i] = hsMaximum(fMax[i], view.fMax[i]);
}
SetView(mins, maxs);
return true;
}
hsScalar plViewTransform::GetFovX() const
{
hsScalar minAng = hsATan2(fMin.fX, 1.f);
hsScalar maxAng = hsATan2(fMax.fX, 1.f);
return maxAng - minAng;
}
hsScalar plViewTransform::GetFovY() const
{
hsScalar minAng = hsATan2(fMin.fY, 1.f);
hsScalar maxAng = hsATan2(fMax.fY, 1.f);
return maxAng - minAng;
}
void plViewTransform::GetViewPort(hsPoint2& mins, hsPoint2& maxs) const
{
if( GetViewPortRelative() )
{
mins.Set(fViewPortX.fX * fWidth, fViewPortY.fX * fHeight);
maxs.Set(fViewPortX.fY * fWidth, fViewPortY.fY * fHeight);
}
else
{
mins.Set(fViewPortX.fX, fViewPortY.fX);
maxs.Set(fViewPortX.fY, fViewPortY.fY);
}
}
void plViewTransform::GetViewPort(int& loX, int& loY, int& hiX, int& hiY) const
{
if( GetViewPortRelative() )
{
loX = int(fViewPortX.fX * fWidth);
loY = int(fViewPortY.fX * fHeight);
hiX = int(fViewPortX.fY * fHeight);
hiY = int(fViewPortY.fY * fWidth);
}
else
{
loX = int(fViewPortX.fX);
loY = int(fViewPortY.fX);
hiX = int(fViewPortX.fY);
hiY = int(fViewPortY.fY);
}
}
void plViewTransform::Read(hsStream* s)
{
fFlags = s->ReadSwap32();
fFlags &= ~kSetMask;
fCameraToWorld.Read(s);
fWorldToCamera.Read(s);
fMin.Read(s);
fMax.Read(s);
fWidth = s->ReadSwap16();
fHeight = s->ReadSwap16();
fViewPortX.Read(s);
fViewPortY.Read(s);
fMapMin.Read(s);
fMapMin.Read(s);
}
void plViewTransform::Write(hsStream* s)
{
s->WriteSwap32(fFlags & ~kSetMask);
fCameraToWorld.Write(s);
fWorldToCamera.Write(s);
fMin.Write(s);
fMax.Write(s);
s->WriteSwap16(fWidth);
s->WriteSwap16(fHeight);
fViewPortX.Write(s);
fViewPortY.Write(s);
fMapMin.Write(s);
fMapMin.Write(s);
}

View File

@ -0,0 +1,342 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef plViewTransform_inc
#define plViewTransform_inc
#include "hsMatrix44.h"
#include "hsGeometry3.h"
#include "hsPoint2.h"
class hsBounds3;
class hsStream;
// There's a lot here, but there's a lot one might want to do with view transforms.
// It's easiest to grab the structure thinking of it in terms of the different
// spaces you might want a point in. The ones supported here are:
// Screen - this is actual pixel values
// NDC - Normalized Device Coordinates, these are post W divide, so the
// valid range is x = [-1..1], y = [-1..1], z = [0..1]
// Camera - relative to the camera, with (0,0,-1) directly in front of the camera,
// and (0, 1, 0) directly above the camera.
// World - Universal world space.
// Map - arbitrary mapping of NDC. Like from [(-1,-1,0)..(1,1,1)] => [(0,0,0)..(1,1,1)] (default).
// Note that there is no object space here. There could be, but I wanted something more constant, more
// world independent, so the ViewTransform remains constant unless the view changes. Whatever.
//
// So we're broken into functional sections:
// 1) Queries on the state of this view transform, properties, matrix values, whatever. Note that you
// generally shouldn't be reading a value (e.g. matrix) out of the ViewTransform, but let the
// ViewTransform perform the operation you would with the matrix.
// 2) Setting state, properties, matrix values, whatever. There's a couple of really bizarre variants
// (like the union and intersection of view frustums). Full support is available for perspective
// or orthogonal views. An additional capability (not necessary) is offset transforms, useful
// for rendering textures. If you don't what good they are, they probably aren't any good to you.
// 3) Conversions of points from one space to another. You may notice that there are a whole lot of them.
// There is a conversion from each of the spaces above to each of the other spaces. That's 12
// transformations right there. But Points and Vectors actually transform differently, so there
// are different versions for those. Where they could be treated the same, there is an hsScalarTriple
// version that does the actual work, and then casting versions to come and go from the right type.
// 4) Read and write (note these are NOT virtual).
//
// More Notes:
// This class has no virtual functions.
// You must set the width and height for Screen queries to work (duh!).
// ViewPort defaults to cover the entire width and height. Viewport only affects mapping, not clipping
// (i.e. reducing the viewport width will still render the same stuff, just skinnier).
// The actual data here is very small, this is mostly a collection of functions, so where possible,
// just keep one of these to pass around, (e.g. rather than keeping track of FOV etc and passing
// those around).
//
class plViewTransform
{
public:
plViewTransform();
~plViewTransform() {}
void Reset(); // resets to default state
// Queries
hsBool GetOrthogonal() const { return IHasFlag(kOrthogonal); }
hsBool GetPerspective() const { return !GetOrthogonal(); }
hsBool GetViewPortRelative() const { return IHasFlag(kViewPortRelative); }
// Next, all our matrices.
const hsMatrix44& GetCameraToWorld() const { return fCameraToWorld; }
const hsMatrix44& GetWorldToCamera() const { return fWorldToCamera; }
const hsMatrix44& GetCameraToNDC() const { return ICheckCameraToNDC(); }
const hsMatrix44& GetWorldToNDC() const { return ICheckWorldToNDC(); }
hsPoint3 GetPosition() const { return GetCameraToWorld().GetTranslate(); }
hsVector3 GetDirection() const { return *((hsVector3 *)&GetWorldToCamera().fMap[2]); }
hsVector3 GetUp() const { return *((hsVector3*)&GetWorldToCamera().fMap[1]); }
hsVector3 GetAcross() const { return *((hsVector3*)&GetWorldToCamera().fMap[0]); }
UInt16 GetScreenWidth() const { return fWidth; }
UInt16 GetScreenHeight() const { return fHeight; }
void GetViewPort(hsPoint2& mins, hsPoint2& maxs) const;
void GetViewPort(int& loX, int& loY, int& hiX, int& hiY) const;
int GetViewPortWidth() const { return GetViewPortRight() - GetViewPortLeft(); }
int GetViewPortHeight() const { return GetViewPortBottom() - GetViewPortTop(); }
int GetViewPortLeft() const { return int(GetViewPortLoX()); }
int GetViewPortTop() const { return int(GetViewPortLoY()); }
int GetViewPortRight() const { return int(GetViewPortHiX()); }
int GetViewPortBottom() const { return int(GetViewPortHiY()); }
float GetViewPortLoX() const { return GetViewPortRelative() ? fViewPortX.fX * fWidth : fViewPortX.fX; }
float GetViewPortLoY() const { return GetViewPortRelative() ? fViewPortY.fX * fHeight : fViewPortY.fX; }
float GetViewPortHiX() const { return GetViewPortRelative() ? fViewPortX.fY * fWidth : fViewPortX.fY; }
float GetViewPortHiY() const { return GetViewPortRelative() ? fViewPortY.fY * fHeight : fViewPortY.fY; }
hsPoint3 GetMapMin() const { return fMapMin; }
hsPoint3 GetMapMax() const { return fMapMax; }
void GetMapping(hsPoint3& mapMin, hsPoint3& mapMax) const { mapMin = fMapMin; mapMax = fMapMax; }
hsScalar GetFovX() const;
hsScalar GetFovY() const;
hsScalar GetFovXDeg() const { return hsScalarRadToDeg(GetFovX()); }
hsScalar GetFovYDeg() const { return hsScalarRadToDeg(GetFovY()); }
hsScalar GetOrthoWidth() const { return fMax.fX - fMin.fX; }
hsScalar GetOrthoHeight() const { return fMax.fY - fMin.fY; }
hsScalar GetHither() const { return fMin.fZ; }
hsScalar GetYon() const { return fMax.fZ; }
void GetDepth(hsScalar& hither, hsScalar& yon) const { hither = GetHither(); yon = GetYon(); }
// Setup.
// First, our world to camera and back again.
void SetCameraTransform(const hsMatrix44& w2c, const hsMatrix44& c2w) { fWorldToCamera = w2c; fCameraToWorld = c2w; ISetFlag(kWorldToNDCSet, false); }
// Next, what kind of projection.
void SetOrthogonal(hsBool on) { ISetFlag(kOrthogonal, on); InvalidateTransforms(); }
void SetPerspective(hsBool on) { SetOrthogonal(!on); }
// Next, setting the scree/window/rendertarget size
void SetWidth(UInt16 w) { fWidth = w; }
void SetHeight(UInt16 h) { fHeight = h; }
void SetScreenSize(UInt16 w, UInt16 h) { SetWidth(w); SetHeight(h); }
// Next, setting the viewport. You only need to do this if you want to use the screen functions above.
// If you're passing in and getting out normalized device coordinates, skip this. If you don't set viewport,
// Defaults to 0,0,width,height (i.e. the whole screen).
void SetViewPort(const hsPoint2& mins, const hsPoint2& maxs, hsBool relative=true);
void SetViewPort(float loX, float loY, float hiX, float hiY, hsBool relative=true) { SetViewPort(hsPoint2().Set(loX, loY), hsPoint2().Set(hiX, hiY), relative); }
void SetViewPort(UInt16 left, UInt16 top, UInt16 right, UInt16 bottom) { SetViewPort(hsScalar(left), hsScalar(top), hsScalar(right), hsScalar(bottom), false); }
void SetMapping(const hsPoint3& mins, const hsPoint3& maxs) { SetMapMin(mins); SetMapMax(maxs); }
void SetMapMin(const hsPoint3& mins) { fMapMin = mins; }
void SetMapMax(const hsPoint3& maxs) { fMapMax = maxs; }
// Next, variants on setting up our projection matrix.
// Depth is pretty uniform.
void SetDepth(hsScalar hither, hsScalar yon) { fMin.fZ = hither; fMax.fZ = yon; InvalidateTransforms(); }
void SetDepth(const hsPoint2& d) { SetDepth(d.fX, d.fY); }
void SetHither(hsScalar hither) { fMin.fZ = hither; InvalidateTransforms(); }
void SetYon(hsScalar yon) { fMax.fZ = yon; InvalidateTransforms(); }
// Garden variety symmetric fov uses either of this first batch. Unless you're doing some funky projection, you don't even
// need to look through the rest.
// Degrees - all are full angles, < 180 degrees
void SetFovDeg(const hsPoint2& deg) { SetFovDeg(deg.fX, deg.fY); }
void SetFovDeg(hsScalar degX, hsScalar degY) { SetFovXDeg(degX); SetFovYDeg(degY); }
void SetFovXDeg(hsScalar deg) { SetFovX(hsScalarDegToRad(deg)); }
void SetFovYDeg(hsScalar deg) { SetFovY(hsScalarDegToRad(deg)); }
// Radians - all are full angles, < PI
void SetFov(const hsPoint2& rad) { SetFov(rad.fX, rad.fY); }
void SetFov(hsScalar radX, hsScalar radY) { SetFovX(radX); SetFovY(radY); }
void SetFovX(hsScalar rad) { SetHalfWidth(hsTan(rad * 0.5f)); }
void SetFovY(hsScalar rad) { SetHalfHeight(hsTan(rad * 0.5f)); }
// For orthogonal projection, don't call SetWidth(hsTan(fovRads)), because hsTan(f)/2 != hsTan(f/2)
// For non-centered, call SetWidths/Heights() directly.
void SetWidth(hsScalar w) { SetHalfWidth(w * 0.5f); }
void SetHeight(hsScalar h) { SetHalfHeight(h * 0.5f); }
// The rest do no interpretation, just stuff the values passed in.
void SetHalfWidth(hsScalar hw) { SetWidths(-hw, hw); }
void SetHalfHeight(hsScalar hh) { SetHeights(-hh, hh); }
void SetWidths(hsScalar minW, hsScalar maxW) { fMin.fX = minW; fMax.fX = maxW; InvalidateTransforms(); }
void SetHeights(hsScalar minH, hsScalar maxH) { fMin.fY = minH; fMax.fY = maxH; InvalidateTransforms(); }
void SetWidths(const hsPoint2& w) { SetWidths(w.fX, w.fY); }
void SetHeights(const hsPoint2& h) { SetHeights(h.fX, h.fY); }
void SetView(const hsPoint3& mins, const hsPoint3& maxs) { fMax = maxs; fMin = mins; InvalidateTransforms(); }
// Take a CAMERA SPACE bounding box and sets up the projection to just surround it.
// Note this doesn't swivel the camera around to see the box, it offsets the projection.
// Return false if there isn't a projection that will capture any of the bnd. This
// can be from the bnd being behind the camera.
hsBool SetProjection(const hsBounds3& cBnd);
hsBool SetProjectionWorld(const hsBounds3& wBnd);
// This lets you create insane projection matrices. Note that it won't change the answer on anything like
// GetFov().
void PreMultCameraToNDC(const hsMatrix44& m) { fCameraToNDC = m * GetCameraToNDC(); }
void PostMultCameraToNDC(const hsMatrix44& m) { fCameraToNDC = GetCameraToNDC() * m; }
void Recalc() { InvalidateTransforms(); }
// These do the obvious, constructing a single view that encompasses either the intersection or union
// of what the two views will see. The boolean is performed in axis aligned camera space, which lines
// up nicely with screen space. Note that this only makes sense for two ViewTransforms with identical
// CameraToWorld's (which isn't checked).
hsBool Intersect(const plViewTransform& view);
hsBool Union(const plViewTransform& view);
// Convenience to move from one space to another.
// Screen means pixels - Default is mapping NDC -> [0..1]. Z value of pixel is NDC Z.
// NDC is the ([-1..1],[-1..1],[0..1]) Normalized device coordinates.
// Camera is camera space.
// World is world space.
// Past that, you're on your own.
hsScalarTriple ScreenToNDC(const hsScalarTriple& scrP) const;
hsScalarTriple ScreenToCamera(const hsScalarTriple& scrP) const { return NDCToCamera(ScreenToNDC(scrP)); }
hsPoint3 ScreenToNDC(const hsPoint3& scrP) const { return hsPoint3(ScreenToNDC(hsScalarTriple(scrP))); }
hsPoint3 ScreenToCamera(const hsPoint3& scrP) const { return hsPoint3(ScreenToCamera(hsScalarTriple(scrP))); }
hsPoint3 ScreenToWorld(const hsPoint3& scrP) const { return CameraToWorld(ScreenToCamera(scrP)); }
hsVector3 ScreenToNDC(const hsVector3& scrV) const { return hsVector3(ScreenToNDC(hsScalarTriple(scrV))); }
hsVector3 ScreenToCamera(const hsVector3& scrV) const { return hsVector3(ScreenToCamera(hsScalarTriple(scrV))); }
hsVector3 ScreenToWorld(const hsVector3& scrV) const { return CameraToWorld(ScreenToCamera(scrV)); }
hsScalarTriple NDCToScreen(const hsScalarTriple& ndc) const;
hsScalarTriple NDCToCamera(const hsScalarTriple& ndc) const;
hsPoint3 NDCToScreen(const hsPoint3& ndc) const { return hsPoint3(NDCToScreen(hsScalarTriple(ndc))); }
hsPoint3 NDCToCamera(const hsPoint3& ndc) const { return hsPoint3(NDCToCamera(hsScalarTriple(ndc))); }
hsPoint3 NDCToWorld(const hsPoint3& ndc) const { return CameraToWorld(NDCToCamera(ndc)); }
hsVector3 NDCToScreen(const hsVector3& ndc) const { return hsVector3(NDCToScreen(hsScalarTriple(ndc))); }
hsVector3 NDCToCamera(const hsVector3& ndc) const { return hsVector3(NDCToCamera(hsScalarTriple(ndc))); }
hsVector3 NDCToWorld(const hsVector3& ndc) const { return CameraToWorld(NDCToCamera(ndc)); }
hsScalarTriple CameraToScreen(const hsScalarTriple& camP) const { return NDCToScreen(CameraToNDC(camP)); }
hsScalarTriple CameraToNDC(const hsScalarTriple& camP) const;
hsPoint3 CameraToScreen(const hsPoint3& camP) const { return hsPoint3(CameraToScreen(hsScalarTriple(camP))); }
hsPoint3 CameraToNDC(const hsPoint3& camP) const { return hsPoint3(CameraToNDC(hsScalarTriple(camP))); }
hsPoint3 CameraToWorld(const hsPoint3& camP) const { return GetCameraToWorld() * camP; }
hsVector3 CameraToScreen(const hsVector3& camP) const { return hsVector3(CameraToScreen(hsScalarTriple(camP))); }
hsVector3 CameraToNDC(const hsVector3& camP) const { return hsVector3(CameraToNDC(hsScalarTriple(camP))); }
hsVector3 CameraToWorld(const hsVector3& camV) const { return GetCameraToWorld() * camV; }
hsPoint3 WorldToScreen(const hsPoint3& worldP) const { return (hsPoint3)CameraToScreen(WorldToCamera(worldP)); }
hsPoint3 WorldToNDC(const hsPoint3& worldP) const { return CameraToNDC(WorldToCamera(worldP)); }
hsPoint3 WorldToCamera(const hsPoint3& worldP) const { return GetWorldToCamera() * worldP; }
hsVector3 WorldToScreen(const hsVector3& worldV) const { return (hsVector3)CameraToScreen(WorldToCamera(worldV)); }
hsVector3 WorldToNDC(const hsVector3& worldP) const { return CameraToNDC(WorldToCamera(worldP)); }
hsVector3 WorldToCamera(const hsVector3& worldV) const { return GetWorldToCamera() * worldV; }
hsScalarTriple NDCToMap(const hsScalarTriple& ndcP) const;
hsScalarTriple CameraToMap(const hsScalarTriple& camP) const { return NDCToMap(CameraToNDC(camP)); }
hsPoint3 NDCToMap(const hsPoint3& ndcP) const { return hsPoint3(NDCToMap(hsScalarTriple(ndcP))); }
hsPoint3 CameraToMap(const hsPoint3& camP) const { return hsPoint3(CameraToMap(hsScalarTriple(camP))); }
hsPoint3 WorldToMap(const hsPoint3& worldP) const { return CameraToMap(WorldToCamera(worldP)); }
hsVector3 NDCToMap(const hsVector3& ndcP) const { return hsVector3(NDCToMap(hsScalarTriple(ndcP))); }
hsVector3 CameraToMap(const hsVector3& camP) const { return hsVector3(CameraToMap(hsScalarTriple(camP))); }
hsVector3 WorldToMap(const hsVector3& worldP) const { return CameraToMap(WorldToCamera(worldP)); }
void Read(hsStream* s);
void Write(hsStream* s);
protected:
enum
{
kNone = 0x0,
kOrthogonal = 0x1,
kSymmetric = 0x2,
kCameraToNDCSet = 0x4,
kWorldToNDCSet = 0x8,
kSetMask = kCameraToNDCSet | kWorldToNDCSet,
kViewPortRelative = 0x10
};
mutable UInt32 fFlags;
hsMatrix44 fCameraToWorld;
hsMatrix44 fWorldToCamera;
hsPoint3 fMin; // minTanX/X, minTanY/Y, hither
hsPoint3 fMax; // maxTanX/X, maxTanY/Y, yon
// Screen (or rendertarget) dimensions in pixels.
UInt16 fWidth;
UInt16 fHeight;
// Viewport can be stored as fraction of screen size, so the view transform's viewport
// can be set up independent of the size of the window it's applied to.
hsPoint3 fViewPortX; // min, max, 1 / (max-min)
hsPoint3 fViewPortY; // min, max, 1 / (max-min)
// For arbitrary mapping (unconfined to pixel coords or NDC), just set what you want
// to map to.
hsPoint3 fMapMin;
hsPoint3 fMapMax;
// Some mutables. These are just the calculated from the above (e.g. fov, depth, perspective, etc).
mutable hsMatrix44 fCameraToNDC;
mutable hsMatrix44 fWorldToNDC;
// Have to set a limit here on the smallest the hither plane can be.
static const hsScalar kMinHither;
void ISetCameraToNDC() const;
hsBool ICameraToNDCSet() const { return IHasFlag(kCameraToNDCSet); }
const hsMatrix44& ICheckCameraToNDC() const { if( !ICameraToNDCSet() ) ISetCameraToNDC(); return fCameraToNDC; }
void ISetWorldToNDC() const { fWorldToNDC = GetCameraToNDC() * fWorldToCamera; ISetFlag(kWorldToNDCSet); }
hsBool IWorldToNDCSet() const { return IHasFlag(kWorldToNDCSet); }
const hsMatrix44& ICheckWorldToNDC() const { if( !IWorldToNDCSet() ) ISetWorldToNDC(); return fWorldToNDC; }
hsBool IGetMaxMinsFromBnd(const hsBounds3& bnd, hsPoint3& mins, hsPoint3& maxs) const;
void InvalidateTransforms() { ISetFlag(kCameraToNDCSet|kWorldToNDCSet, false); }
// Flags - generic
hsBool IHasFlag(UInt32 f) const { return 0 != (fFlags & f); }
void ISetFlag(UInt32 f, hsBool on=true) const { if(on) fFlags |= f; else fFlags &= ~f; }
};
#endif // plViewTransform_inc