mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-13 18:17:49 -04:00
Fix line endings and tabs
This commit is contained in:
@ -1,24 +1,24 @@
|
||||
include_directories("../../CoreLib")
|
||||
include_directories("../../NucleusLib")
|
||||
include_directories("../../PubUtilLib")
|
||||
|
||||
set(plMath_SOURCES
|
||||
hsNoiseFunc.cpp
|
||||
hsRadixSort.cpp
|
||||
plAvg.cpp
|
||||
plTriUtils.cpp
|
||||
)
|
||||
|
||||
set(plMath_HEADERS
|
||||
hsNoiseFunc.h
|
||||
hsRadixSort.h
|
||||
hsSearchVersion.h
|
||||
plAvg.h
|
||||
plRandom.h
|
||||
plTriUtils.h
|
||||
)
|
||||
|
||||
add_library(plMath STATIC ${plMath_SOURCES} ${plMath_HEADERS})
|
||||
|
||||
source_group("Source Files" FILES ${plMath_SOURCES})
|
||||
source_group("Header Files" FILES ${plMath_HEADERS})
|
||||
include_directories("../../CoreLib")
|
||||
include_directories("../../NucleusLib")
|
||||
include_directories("../../PubUtilLib")
|
||||
|
||||
set(plMath_SOURCES
|
||||
hsNoiseFunc.cpp
|
||||
hsRadixSort.cpp
|
||||
plAvg.cpp
|
||||
plTriUtils.cpp
|
||||
)
|
||||
|
||||
set(plMath_HEADERS
|
||||
hsNoiseFunc.h
|
||||
hsRadixSort.h
|
||||
hsSearchVersion.h
|
||||
plAvg.h
|
||||
plRandom.h
|
||||
plTriUtils.h
|
||||
)
|
||||
|
||||
add_library(plMath STATIC ${plMath_SOURCES} ${plMath_HEADERS})
|
||||
|
||||
source_group("Source Files" FILES ${plMath_SOURCES})
|
||||
source_group("Header Files" FILES ${plMath_HEADERS})
|
||||
|
@ -1,140 +1,140 @@
|
||||
/*==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/>.
|
||||
|
||||
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 "hsNoiseFunc.h"
|
||||
#include "hsTypes.h"
|
||||
#include "hsScalar.h"
|
||||
#include "hsGeometry3.h"
|
||||
|
||||
hsNoiseFunc::hsNoiseFunc()
|
||||
{
|
||||
}
|
||||
|
||||
hsNoiseFunc::~hsNoiseFunc()
|
||||
{
|
||||
}
|
||||
|
||||
void hsNoiseFunc::Seed(UInt32 s)
|
||||
{
|
||||
srand(s);
|
||||
}
|
||||
|
||||
hsTableNoise::hsTableNoise()
|
||||
: fTable(nil), fTableLen(0)
|
||||
{
|
||||
}
|
||||
|
||||
hsTableNoise::~hsTableNoise()
|
||||
{
|
||||
delete [] fTable;
|
||||
}
|
||||
|
||||
void hsTableNoise::SetTable(int len, hsScalar* arr)
|
||||
{
|
||||
fTableLen = len;
|
||||
|
||||
delete [] fTable;
|
||||
if( !len )
|
||||
{
|
||||
fTable = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
fTable = TRACKED_NEW hsScalar[len+2];
|
||||
|
||||
int i;
|
||||
for( i = 0; i < len; i++ )
|
||||
fTable[i] = arr[i];
|
||||
fTable[i++] = fTable[i-1];
|
||||
fTable[i++] = fTable[i-1];
|
||||
|
||||
}
|
||||
|
||||
hsScalar hsTableNoise::Noise(hsScalar lo, hsScalar hi, hsScalar t)
|
||||
{
|
||||
hsAssert(fTableLen, "Badly initialized table noise function");
|
||||
|
||||
hsScalar r = hsScalar(rand()) / hsScalar(RAND_MAX);
|
||||
r = lo + (hi - lo) * r;
|
||||
|
||||
if( t < 0 )
|
||||
t = 0;
|
||||
else if( t > hsScalar1 )
|
||||
t = hsScalar1;
|
||||
|
||||
hsScalar tIdx = t * fTableLen;
|
||||
UInt32 idx = UInt32(tIdx);
|
||||
hsScalar frac = tIdx - hsScalar(idx);
|
||||
hsAssert((idx >= 0)&&(idx <= fTableLen), "Noise parm t out of range [0..1]");
|
||||
|
||||
hsScalar scale = fTable[idx] + (fTable[idx+1] - fTable[idx]) * frac;
|
||||
|
||||
r *= scale;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
hsScalar hsTableNoise::NoisePoint(const hsPoint3& p, hsScalar lo, hsScalar hi, hsScalar t)
|
||||
{
|
||||
hsAssert(fTableLen, "Badly initialized table noise function");
|
||||
|
||||
UInt32 sX = *((UInt32*)&p.fX);
|
||||
UInt32 sY = *((UInt32*)&p.fY);
|
||||
UInt32 sZ = *((UInt32*)&p.fZ);
|
||||
|
||||
UInt32 sAll = ((((sX & 0x07800000) >> 16) | ((sX & 0x007fffff) >> 17)) << 20)
|
||||
| ((((sY & 0x07800000) >> 16) | ((sY & 0x007fffff) >> 17)) << 10)
|
||||
| ((((sZ & 0x07800000) >> 16) | ((sZ & 0x007fffff) >> 17)) );
|
||||
|
||||
const UInt32 kExp = 0x3f800000;
|
||||
const UInt32 kMsk = 0x007fffff;
|
||||
|
||||
const UInt32 kA = 1665636L;
|
||||
const UInt32 kC = 1013904223L;
|
||||
|
||||
UInt32 iR = kA * sAll + kC;
|
||||
iR &= kMsk;
|
||||
iR |= kExp;
|
||||
|
||||
hsScalar r = (*(float*)&iR) - 1.f;
|
||||
|
||||
r = lo + (hi - lo) * r;
|
||||
|
||||
if( t < 0 )
|
||||
t = 0;
|
||||
else if( t > hsScalar1 )
|
||||
t = hsScalar1;
|
||||
|
||||
hsScalar tIdx = t * fTableLen;
|
||||
UInt32 idx = UInt32(tIdx);
|
||||
hsScalar frac = tIdx - hsScalar(idx);
|
||||
hsAssert((idx >= 0)&&(idx <= fTableLen), "Noise parm t out of range [0..1]");
|
||||
|
||||
hsScalar scale = fTable[idx] + (fTable[idx+1] - fTable[idx]) * frac;
|
||||
|
||||
r *= scale;
|
||||
|
||||
return r;
|
||||
}
|
||||
/*==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/>.
|
||||
|
||||
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 "hsNoiseFunc.h"
|
||||
#include "hsTypes.h"
|
||||
#include "hsScalar.h"
|
||||
#include "hsGeometry3.h"
|
||||
|
||||
hsNoiseFunc::hsNoiseFunc()
|
||||
{
|
||||
}
|
||||
|
||||
hsNoiseFunc::~hsNoiseFunc()
|
||||
{
|
||||
}
|
||||
|
||||
void hsNoiseFunc::Seed(UInt32 s)
|
||||
{
|
||||
srand(s);
|
||||
}
|
||||
|
||||
hsTableNoise::hsTableNoise()
|
||||
: fTable(nil), fTableLen(0)
|
||||
{
|
||||
}
|
||||
|
||||
hsTableNoise::~hsTableNoise()
|
||||
{
|
||||
delete [] fTable;
|
||||
}
|
||||
|
||||
void hsTableNoise::SetTable(int len, hsScalar* arr)
|
||||
{
|
||||
fTableLen = len;
|
||||
|
||||
delete [] fTable;
|
||||
if( !len )
|
||||
{
|
||||
fTable = nil;
|
||||
return;
|
||||
}
|
||||
|
||||
fTable = TRACKED_NEW hsScalar[len+2];
|
||||
|
||||
int i;
|
||||
for( i = 0; i < len; i++ )
|
||||
fTable[i] = arr[i];
|
||||
fTable[i++] = fTable[i-1];
|
||||
fTable[i++] = fTable[i-1];
|
||||
|
||||
}
|
||||
|
||||
hsScalar hsTableNoise::Noise(hsScalar lo, hsScalar hi, hsScalar t)
|
||||
{
|
||||
hsAssert(fTableLen, "Badly initialized table noise function");
|
||||
|
||||
hsScalar r = hsScalar(rand()) / hsScalar(RAND_MAX);
|
||||
r = lo + (hi - lo) * r;
|
||||
|
||||
if( t < 0 )
|
||||
t = 0;
|
||||
else if( t > hsScalar1 )
|
||||
t = hsScalar1;
|
||||
|
||||
hsScalar tIdx = t * fTableLen;
|
||||
UInt32 idx = UInt32(tIdx);
|
||||
hsScalar frac = tIdx - hsScalar(idx);
|
||||
hsAssert((idx >= 0)&&(idx <= fTableLen), "Noise parm t out of range [0..1]");
|
||||
|
||||
hsScalar scale = fTable[idx] + (fTable[idx+1] - fTable[idx]) * frac;
|
||||
|
||||
r *= scale;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
hsScalar hsTableNoise::NoisePoint(const hsPoint3& p, hsScalar lo, hsScalar hi, hsScalar t)
|
||||
{
|
||||
hsAssert(fTableLen, "Badly initialized table noise function");
|
||||
|
||||
UInt32 sX = *((UInt32*)&p.fX);
|
||||
UInt32 sY = *((UInt32*)&p.fY);
|
||||
UInt32 sZ = *((UInt32*)&p.fZ);
|
||||
|
||||
UInt32 sAll = ((((sX & 0x07800000) >> 16) | ((sX & 0x007fffff) >> 17)) << 20)
|
||||
| ((((sY & 0x07800000) >> 16) | ((sY & 0x007fffff) >> 17)) << 10)
|
||||
| ((((sZ & 0x07800000) >> 16) | ((sZ & 0x007fffff) >> 17)) );
|
||||
|
||||
const UInt32 kExp = 0x3f800000;
|
||||
const UInt32 kMsk = 0x007fffff;
|
||||
|
||||
const UInt32 kA = 1665636L;
|
||||
const UInt32 kC = 1013904223L;
|
||||
|
||||
UInt32 iR = kA * sAll + kC;
|
||||
iR &= kMsk;
|
||||
iR |= kExp;
|
||||
|
||||
hsScalar r = (*(float*)&iR) - 1.f;
|
||||
|
||||
r = lo + (hi - lo) * r;
|
||||
|
||||
if( t < 0 )
|
||||
t = 0;
|
||||
else if( t > hsScalar1 )
|
||||
t = hsScalar1;
|
||||
|
||||
hsScalar tIdx = t * fTableLen;
|
||||
UInt32 idx = UInt32(tIdx);
|
||||
hsScalar frac = tIdx - hsScalar(idx);
|
||||
hsAssert((idx >= 0)&&(idx <= fTableLen), "Noise parm t out of range [0..1]");
|
||||
|
||||
hsScalar scale = fTable[idx] + (fTable[idx+1] - fTable[idx]) * frac;
|
||||
|
||||
r *= scale;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -1,66 +1,66 @@
|
||||
/*==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/>.
|
||||
|
||||
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 hsNoiseFunc_inc
|
||||
#define hsNoiseFunc_inc
|
||||
|
||||
#include "hsRefCnt.h"
|
||||
#include "hsScalar.h"
|
||||
|
||||
struct hsPoint3;
|
||||
|
||||
class hsNoiseFunc : public hsRefCnt // should inherit from keyed object
|
||||
{
|
||||
public:
|
||||
hsNoiseFunc();
|
||||
virtual ~hsNoiseFunc();
|
||||
|
||||
virtual void Seed(UInt32 s);
|
||||
virtual hsScalar Noise(hsScalar lo=0, hsScalar hi=hsScalar1, hsScalar t=0) = 0; // t = [0..1] - returns random num [lo..hi] scaled by fTable[t]
|
||||
|
||||
virtual hsScalar NoisePoint(const hsPoint3& p, hsScalar lo=0, hsScalar hi=hsScalar1, hsScalar t=0) = 0; // t = [0..1] - returns random num [lo..hi] scaled by fTable[t]
|
||||
};
|
||||
|
||||
class hsTableNoise : public hsNoiseFunc // should inherit from keyed object
|
||||
{
|
||||
protected:
|
||||
hsScalar* fTable;
|
||||
UInt32 fTableLen;
|
||||
|
||||
|
||||
public:
|
||||
hsTableNoise();
|
||||
virtual ~hsTableNoise();
|
||||
|
||||
void SetTable(int len, hsScalar* arr); // copies. arr should be hsScalars in range [0..1]
|
||||
hsScalar* GetTable(int& len) { len = fTableLen; return fTable; } // should be debug only, access through noise func
|
||||
|
||||
virtual hsScalar Noise(hsScalar lo=0, hsScalar hi=hsScalar1, hsScalar t=0); // t = [0..1] - returns random num [lo..hi] scaled by fTable[t]
|
||||
|
||||
virtual hsScalar NoisePoint(const hsPoint3& p, hsScalar lo=0, hsScalar hi=hsScalar1, hsScalar t=0); // t = [0..1] - returns random num [lo..hi] scaled by fTable[t]
|
||||
};
|
||||
|
||||
#endif // hsNoiseFunc_inc
|
||||
/*==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/>.
|
||||
|
||||
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 hsNoiseFunc_inc
|
||||
#define hsNoiseFunc_inc
|
||||
|
||||
#include "hsRefCnt.h"
|
||||
#include "hsScalar.h"
|
||||
|
||||
struct hsPoint3;
|
||||
|
||||
class hsNoiseFunc : public hsRefCnt // should inherit from keyed object
|
||||
{
|
||||
public:
|
||||
hsNoiseFunc();
|
||||
virtual ~hsNoiseFunc();
|
||||
|
||||
virtual void Seed(UInt32 s);
|
||||
virtual hsScalar Noise(hsScalar lo=0, hsScalar hi=hsScalar1, hsScalar t=0) = 0; // t = [0..1] - returns random num [lo..hi] scaled by fTable[t]
|
||||
|
||||
virtual hsScalar NoisePoint(const hsPoint3& p, hsScalar lo=0, hsScalar hi=hsScalar1, hsScalar t=0) = 0; // t = [0..1] - returns random num [lo..hi] scaled by fTable[t]
|
||||
};
|
||||
|
||||
class hsTableNoise : public hsNoiseFunc // should inherit from keyed object
|
||||
{
|
||||
protected:
|
||||
hsScalar* fTable;
|
||||
UInt32 fTableLen;
|
||||
|
||||
|
||||
public:
|
||||
hsTableNoise();
|
||||
virtual ~hsTableNoise();
|
||||
|
||||
void SetTable(int len, hsScalar* arr); // copies. arr should be hsScalars in range [0..1]
|
||||
hsScalar* GetTable(int& len) { len = fTableLen; return fTable; } // should be debug only, access through noise func
|
||||
|
||||
virtual hsScalar Noise(hsScalar lo=0, hsScalar hi=hsScalar1, hsScalar t=0); // t = [0..1] - returns random num [lo..hi] scaled by fTable[t]
|
||||
|
||||
virtual hsScalar NoisePoint(const hsPoint3& p, hsScalar lo=0, hsScalar hi=hsScalar1, hsScalar t=0); // t = [0..1] - returns random num [lo..hi] scaled by fTable[t]
|
||||
};
|
||||
|
||||
#endif // hsNoiseFunc_inc
|
||||
|
@ -1,165 +1,165 @@
|
||||
/*==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/>.
|
||||
|
||||
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 "hsMemory.h"
|
||||
#include "hsRadixSort.h"
|
||||
|
||||
hsRadixSort::hsRadixSort()
|
||||
{
|
||||
HSMemory::Clear(fHeads, 256*sizeof(Elem*));
|
||||
HSMemory::Clear(fTails, 256*sizeof(Elem*));
|
||||
}
|
||||
|
||||
void hsRadixSort::ILink(Elem*& head, Elem*& tail, int i)
|
||||
{
|
||||
if( fHeads[i] )
|
||||
{
|
||||
if( !head )
|
||||
head = fHeads[i];
|
||||
else
|
||||
tail->fNext = fHeads[i];
|
||||
tail = fTails[i];
|
||||
}
|
||||
fHeads[i] = fTails[i] = nil;
|
||||
}
|
||||
|
||||
void hsRadixSort::ISlot(Elem* in, int i)
|
||||
{
|
||||
if( !fTails[i] )
|
||||
fHeads[i] = in;
|
||||
else
|
||||
fTails[i]->fNext = in;
|
||||
in->fNext = nil;
|
||||
fTails[i] = in;
|
||||
}
|
||||
|
||||
void hsRadixSort::ICollapse()
|
||||
{
|
||||
Elem* head = nil;
|
||||
Elem* tail = nil;
|
||||
|
||||
int i;
|
||||
for( i = 0; i < 256; i++ )
|
||||
ILink(head, tail, i);
|
||||
|
||||
fList = head;
|
||||
}
|
||||
|
||||
void hsRadixSort::IUnPackSignedInt()
|
||||
{
|
||||
Elem* head = nil;
|
||||
Elem* tail = nil;
|
||||
|
||||
int i;
|
||||
for( i = 128; i < 256; i++ )
|
||||
ILink(head, tail, i);
|
||||
|
||||
for( i = 0; i < 128; i++ )
|
||||
ILink(head, tail, i);
|
||||
|
||||
fList = head;
|
||||
}
|
||||
|
||||
void hsRadixSort::IUnPackFloat()
|
||||
{
|
||||
Elem* head = nil;
|
||||
Elem* tail = nil;
|
||||
|
||||
int i;
|
||||
for( i = 128; i < 256; i++ )
|
||||
ILink(head, tail, i);
|
||||
fList = head;
|
||||
head = tail;
|
||||
tail = fList;
|
||||
IReverse();
|
||||
|
||||
for( i = 0; i < 128; i++ )
|
||||
ILink(head, tail, i);
|
||||
|
||||
fList = head;
|
||||
}
|
||||
|
||||
void hsRadixSort::IReverse()
|
||||
{
|
||||
if( !(fList && fList->fNext) )
|
||||
return;
|
||||
|
||||
Elem* p = fList->fNext;
|
||||
fList->fNext = nil;
|
||||
while( p )
|
||||
{
|
||||
Elem* n = p->fNext;
|
||||
p->fNext = fList;
|
||||
fList = p;
|
||||
p = n;
|
||||
}
|
||||
}
|
||||
|
||||
hsRadixSort::Elem* hsRadixSort::Sort(Elem* inList, UInt32 flags)
|
||||
{
|
||||
if( !(inList && inList->fNext) )
|
||||
return inList;
|
||||
|
||||
fList = inList;
|
||||
|
||||
Elem* p;
|
||||
Elem* n;
|
||||
|
||||
for( p = fList, n = p->fNext; n; p = n, n = p->fNext )
|
||||
ISlot(p, p->fKey.fLong & 0xff);
|
||||
ISlot(p, p->fKey.fLong & 0xff);
|
||||
|
||||
ICollapse();
|
||||
|
||||
for( p = fList, n = p->fNext; n; p = n, n = p->fNext )
|
||||
ISlot(p, (p->fKey.fLong >> 8) & 0xff);
|
||||
ISlot(p, (p->fKey.fLong >> 8) & 0xff);
|
||||
|
||||
ICollapse();
|
||||
|
||||
for( p = fList, n = p->fNext; n; p = n, n = p->fNext )
|
||||
ISlot(p, (p->fKey.fLong >> 16) & 0xff);
|
||||
ISlot(p, (p->fKey.fLong >> 16) & 0xff);
|
||||
|
||||
ICollapse();
|
||||
|
||||
for( p = fList, n = p->fNext; n; p = n, n = p->fNext )
|
||||
ISlot(p, (p->fKey.fLong >> 24) & 0xff);
|
||||
ISlot(p, (p->fKey.fLong >> 24) & 0xff);
|
||||
|
||||
if( flags & kSignedInt )
|
||||
IUnPackSignedInt();
|
||||
else if( flags & kUnsigned )
|
||||
ICollapse();
|
||||
else
|
||||
IUnPackFloat();
|
||||
|
||||
if( flags & kReverse )
|
||||
IReverse();
|
||||
|
||||
return fList;
|
||||
}
|
||||
/*==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/>.
|
||||
|
||||
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 "hsMemory.h"
|
||||
#include "hsRadixSort.h"
|
||||
|
||||
hsRadixSort::hsRadixSort()
|
||||
{
|
||||
HSMemory::Clear(fHeads, 256*sizeof(Elem*));
|
||||
HSMemory::Clear(fTails, 256*sizeof(Elem*));
|
||||
}
|
||||
|
||||
void hsRadixSort::ILink(Elem*& head, Elem*& tail, int i)
|
||||
{
|
||||
if( fHeads[i] )
|
||||
{
|
||||
if( !head )
|
||||
head = fHeads[i];
|
||||
else
|
||||
tail->fNext = fHeads[i];
|
||||
tail = fTails[i];
|
||||
}
|
||||
fHeads[i] = fTails[i] = nil;
|
||||
}
|
||||
|
||||
void hsRadixSort::ISlot(Elem* in, int i)
|
||||
{
|
||||
if( !fTails[i] )
|
||||
fHeads[i] = in;
|
||||
else
|
||||
fTails[i]->fNext = in;
|
||||
in->fNext = nil;
|
||||
fTails[i] = in;
|
||||
}
|
||||
|
||||
void hsRadixSort::ICollapse()
|
||||
{
|
||||
Elem* head = nil;
|
||||
Elem* tail = nil;
|
||||
|
||||
int i;
|
||||
for( i = 0; i < 256; i++ )
|
||||
ILink(head, tail, i);
|
||||
|
||||
fList = head;
|
||||
}
|
||||
|
||||
void hsRadixSort::IUnPackSignedInt()
|
||||
{
|
||||
Elem* head = nil;
|
||||
Elem* tail = nil;
|
||||
|
||||
int i;
|
||||
for( i = 128; i < 256; i++ )
|
||||
ILink(head, tail, i);
|
||||
|
||||
for( i = 0; i < 128; i++ )
|
||||
ILink(head, tail, i);
|
||||
|
||||
fList = head;
|
||||
}
|
||||
|
||||
void hsRadixSort::IUnPackFloat()
|
||||
{
|
||||
Elem* head = nil;
|
||||
Elem* tail = nil;
|
||||
|
||||
int i;
|
||||
for( i = 128; i < 256; i++ )
|
||||
ILink(head, tail, i);
|
||||
fList = head;
|
||||
head = tail;
|
||||
tail = fList;
|
||||
IReverse();
|
||||
|
||||
for( i = 0; i < 128; i++ )
|
||||
ILink(head, tail, i);
|
||||
|
||||
fList = head;
|
||||
}
|
||||
|
||||
void hsRadixSort::IReverse()
|
||||
{
|
||||
if( !(fList && fList->fNext) )
|
||||
return;
|
||||
|
||||
Elem* p = fList->fNext;
|
||||
fList->fNext = nil;
|
||||
while( p )
|
||||
{
|
||||
Elem* n = p->fNext;
|
||||
p->fNext = fList;
|
||||
fList = p;
|
||||
p = n;
|
||||
}
|
||||
}
|
||||
|
||||
hsRadixSort::Elem* hsRadixSort::Sort(Elem* inList, UInt32 flags)
|
||||
{
|
||||
if( !(inList && inList->fNext) )
|
||||
return inList;
|
||||
|
||||
fList = inList;
|
||||
|
||||
Elem* p;
|
||||
Elem* n;
|
||||
|
||||
for( p = fList, n = p->fNext; n; p = n, n = p->fNext )
|
||||
ISlot(p, p->fKey.fLong & 0xff);
|
||||
ISlot(p, p->fKey.fLong & 0xff);
|
||||
|
||||
ICollapse();
|
||||
|
||||
for( p = fList, n = p->fNext; n; p = n, n = p->fNext )
|
||||
ISlot(p, (p->fKey.fLong >> 8) & 0xff);
|
||||
ISlot(p, (p->fKey.fLong >> 8) & 0xff);
|
||||
|
||||
ICollapse();
|
||||
|
||||
for( p = fList, n = p->fNext; n; p = n, n = p->fNext )
|
||||
ISlot(p, (p->fKey.fLong >> 16) & 0xff);
|
||||
ISlot(p, (p->fKey.fLong >> 16) & 0xff);
|
||||
|
||||
ICollapse();
|
||||
|
||||
for( p = fList, n = p->fNext; n; p = n, n = p->fNext )
|
||||
ISlot(p, (p->fKey.fLong >> 24) & 0xff);
|
||||
ISlot(p, (p->fKey.fLong >> 24) & 0xff);
|
||||
|
||||
if( flags & kSignedInt )
|
||||
IUnPackSignedInt();
|
||||
else if( flags & kUnsigned )
|
||||
ICollapse();
|
||||
else
|
||||
IUnPackFloat();
|
||||
|
||||
if( flags & kReverse )
|
||||
IReverse();
|
||||
|
||||
return fList;
|
||||
}
|
||||
|
@ -1,75 +1,75 @@
|
||||
/*==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/>.
|
||||
|
||||
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 hsRadixSort_inc
|
||||
#define hsRadixSort_inc
|
||||
|
||||
class hsRadixSortElem
|
||||
{
|
||||
public:
|
||||
union {
|
||||
float fFloat;
|
||||
long fLong;
|
||||
unsigned long fULong;
|
||||
} fKey;
|
||||
|
||||
void* fBody;
|
||||
|
||||
hsRadixSortElem* fNext;
|
||||
};
|
||||
|
||||
class hsRadixSort {
|
||||
public:
|
||||
enum {
|
||||
kFloat = 0x0,
|
||||
kSignedInt = 0x1,
|
||||
kUnsigned = 0x2,
|
||||
kReverse = 0x4
|
||||
};
|
||||
typedef hsRadixSortElem Elem;
|
||||
|
||||
protected:
|
||||
Elem* fList;
|
||||
Elem* fHeads[256];
|
||||
Elem* fTails[256];
|
||||
|
||||
inline void ILink(Elem*& head, Elem*& tail, int i); // inline?
|
||||
inline void ISlot(Elem* in, int i); // inline?
|
||||
|
||||
void ICollapse();
|
||||
void IUnPackSignedInt();
|
||||
void IUnPackFloat();
|
||||
void IReverse();
|
||||
|
||||
public:
|
||||
|
||||
hsRadixSort();
|
||||
|
||||
Elem* Sort(Elem* inList, UInt32 flags = 0);
|
||||
|
||||
};
|
||||
|
||||
#endif // hsRadixSort_inc
|
||||
/*==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/>.
|
||||
|
||||
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 hsRadixSort_inc
|
||||
#define hsRadixSort_inc
|
||||
|
||||
class hsRadixSortElem
|
||||
{
|
||||
public:
|
||||
union {
|
||||
float fFloat;
|
||||
long fLong;
|
||||
unsigned long fULong;
|
||||
} fKey;
|
||||
|
||||
void* fBody;
|
||||
|
||||
hsRadixSortElem* fNext;
|
||||
};
|
||||
|
||||
class hsRadixSort {
|
||||
public:
|
||||
enum {
|
||||
kFloat = 0x0,
|
||||
kSignedInt = 0x1,
|
||||
kUnsigned = 0x2,
|
||||
kReverse = 0x4
|
||||
};
|
||||
typedef hsRadixSortElem Elem;
|
||||
|
||||
protected:
|
||||
Elem* fList;
|
||||
Elem* fHeads[256];
|
||||
Elem* fTails[256];
|
||||
|
||||
inline void ILink(Elem*& head, Elem*& tail, int i); // inline?
|
||||
inline void ISlot(Elem* in, int i); // inline?
|
||||
|
||||
void ICollapse();
|
||||
void IUnPackSignedInt();
|
||||
void IUnPackFloat();
|
||||
void IReverse();
|
||||
|
||||
public:
|
||||
|
||||
hsRadixSort();
|
||||
|
||||
Elem* Sort(Elem* inList, UInt32 flags = 0);
|
||||
|
||||
};
|
||||
|
||||
#endif // hsRadixSort_inc
|
||||
|
@ -1,165 +1,165 @@
|
||||
/*==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/>.
|
||||
|
||||
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 hsSearchVersion_inc
|
||||
#define hsSearchVersion_inc
|
||||
|
||||
#include "hsTypes.h"
|
||||
|
||||
/*
|
||||
do a template of lists to search for a matching entry. basic idea is that
|
||||
you start off with an array of buckets and you know that you will get at
|
||||
least one, possibly several, in each bucket. when you go to search, you already
|
||||
know which bucket it will be in if it's there. even as the array is being filled,
|
||||
each filled entry in each bucket has a valid forever index, as well as it's key
|
||||
value. so array is fixed length, index into array has no bearing on forever index,
|
||||
elements of array can grow, and at all times the used forever indices form a contiguous
|
||||
set from 0 to max forever index.
|
||||
*/
|
||||
|
||||
template <class T> class hsVersionNode {
|
||||
protected:
|
||||
T fData;
|
||||
Int32 fIndex;
|
||||
hsVersionNode<T>* fNext;
|
||||
public:
|
||||
hsVersionNode(const UInt32 idx, const T &data) : fIndex(idx), fNext(nil) { fData = data; }
|
||||
~hsVersionNode() { delete fNext; }
|
||||
|
||||
hsVersionNode<T>* Next() const { return fNext; }
|
||||
|
||||
Int32 Index() const { return fIndex; }
|
||||
|
||||
inline void Append(hsVersionNode<T>* next);
|
||||
inline int operator==(const T& o) const;
|
||||
|
||||
int operator!=(const T& o) const { return !(this->operator==(o)); }
|
||||
|
||||
T& GetData() { return fData; }
|
||||
};
|
||||
|
||||
template <class T> int hsVersionNode<T>::operator==(const T& data) const
|
||||
{
|
||||
return fData == data;
|
||||
}
|
||||
|
||||
template <class T> void hsVersionNode<T>::Append(hsVersionNode<T>* next)
|
||||
{
|
||||
if( fNext )
|
||||
fNext->Append(next);
|
||||
else
|
||||
fNext = next;
|
||||
}
|
||||
|
||||
template <class T> class hsSearchVersion {
|
||||
protected:
|
||||
UInt32 fLength;
|
||||
hsVersionNode<T>** fArray;
|
||||
UInt32 fNextIndex;
|
||||
UInt32 fNumIndex;
|
||||
UInt32 fIncIndex;
|
||||
T** fBackArray;
|
||||
|
||||
void ICheckBackArray();
|
||||
public:
|
||||
hsSearchVersion(UInt32 len, UInt32 inc = 0);
|
||||
~hsSearchVersion();
|
||||
|
||||
T& operator[]( Int32 index );
|
||||
|
||||
Int32 Find(int where, const T& what, hsBool forceUnique=false);
|
||||
|
||||
UInt32 GetCount() const { return fNextIndex; }
|
||||
};
|
||||
|
||||
template <class T> T& hsSearchVersion<T>::operator[]( Int32 index )
|
||||
{
|
||||
hsDebugCode(hsThrowIfBadParam((UInt32)index >= (UInt32)fNextIndex);)
|
||||
|
||||
return *fBackArray[index];
|
||||
}
|
||||
|
||||
template <class T> hsSearchVersion<T>::hsSearchVersion(UInt32 len, UInt32 inc)
|
||||
: fNextIndex(0)
|
||||
{
|
||||
fIncIndex = inc ? inc : len;
|
||||
fLength = len;
|
||||
fArray = TRACKED_NEW hsVersionNode<T>*[fLength];
|
||||
HSMemory::Clear(fArray, fLength*sizeof(*fArray));
|
||||
fBackArray = TRACKED_NEW T*[fNumIndex = fLength];
|
||||
}
|
||||
|
||||
template <class T> hsSearchVersion<T>::~hsSearchVersion()
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fLength; i++ )
|
||||
delete fArray[i];
|
||||
delete [] fArray;
|
||||
delete [] fBackArray;
|
||||
}
|
||||
|
||||
template <class T> void hsSearchVersion<T>::ICheckBackArray()
|
||||
{
|
||||
if( fNextIndex >= fNumIndex )
|
||||
{
|
||||
T** newBackArray = TRACKED_NEW T*[fNumIndex + fIncIndex];
|
||||
HSMemory::BlockMove(fBackArray, newBackArray, fNextIndex*sizeof(T*));
|
||||
delete [] fBackArray;
|
||||
fBackArray = newBackArray;
|
||||
fNumIndex += fIncIndex;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> Int32 hsSearchVersion<T>::Find(int where, const T&what, hsBool forceUnique)
|
||||
{
|
||||
hsVersionNode<T>* curr = fArray[where];
|
||||
|
||||
ICheckBackArray();
|
||||
|
||||
if( !curr )
|
||||
{
|
||||
hsVersionNode<T>* next = TRACKED_NEW hsVersionNode<T>(fNextIndex, what);
|
||||
fArray[where] = next;
|
||||
fBackArray[fNextIndex] = &next->GetData();
|
||||
return fNextIndex++;
|
||||
}
|
||||
if( *curr == what )
|
||||
return curr->Index();
|
||||
|
||||
while( curr->Next()
|
||||
&& (forceUnique || (*curr->Next() != what)) )
|
||||
curr = curr->Next();
|
||||
|
||||
if( curr->Next() )
|
||||
return curr->Next()->Index();
|
||||
|
||||
hsVersionNode<T>* next = TRACKED_NEW hsVersionNode<T>(fNextIndex, what);
|
||||
curr->Append(next);
|
||||
fBackArray[fNextIndex] = &next->GetData();
|
||||
return fNextIndex++;
|
||||
}
|
||||
|
||||
#endif // hsSearchVersion_inc
|
||||
/*==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/>.
|
||||
|
||||
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 hsSearchVersion_inc
|
||||
#define hsSearchVersion_inc
|
||||
|
||||
#include "hsTypes.h"
|
||||
|
||||
/*
|
||||
do a template of lists to search for a matching entry. basic idea is that
|
||||
you start off with an array of buckets and you know that you will get at
|
||||
least one, possibly several, in each bucket. when you go to search, you already
|
||||
know which bucket it will be in if it's there. even as the array is being filled,
|
||||
each filled entry in each bucket has a valid forever index, as well as it's key
|
||||
value. so array is fixed length, index into array has no bearing on forever index,
|
||||
elements of array can grow, and at all times the used forever indices form a contiguous
|
||||
set from 0 to max forever index.
|
||||
*/
|
||||
|
||||
template <class T> class hsVersionNode {
|
||||
protected:
|
||||
T fData;
|
||||
Int32 fIndex;
|
||||
hsVersionNode<T>* fNext;
|
||||
public:
|
||||
hsVersionNode(const UInt32 idx, const T &data) : fIndex(idx), fNext(nil) { fData = data; }
|
||||
~hsVersionNode() { delete fNext; }
|
||||
|
||||
hsVersionNode<T>* Next() const { return fNext; }
|
||||
|
||||
Int32 Index() const { return fIndex; }
|
||||
|
||||
inline void Append(hsVersionNode<T>* next);
|
||||
inline int operator==(const T& o) const;
|
||||
|
||||
int operator!=(const T& o) const { return !(this->operator==(o)); }
|
||||
|
||||
T& GetData() { return fData; }
|
||||
};
|
||||
|
||||
template <class T> int hsVersionNode<T>::operator==(const T& data) const
|
||||
{
|
||||
return fData == data;
|
||||
}
|
||||
|
||||
template <class T> void hsVersionNode<T>::Append(hsVersionNode<T>* next)
|
||||
{
|
||||
if( fNext )
|
||||
fNext->Append(next);
|
||||
else
|
||||
fNext = next;
|
||||
}
|
||||
|
||||
template <class T> class hsSearchVersion {
|
||||
protected:
|
||||
UInt32 fLength;
|
||||
hsVersionNode<T>** fArray;
|
||||
UInt32 fNextIndex;
|
||||
UInt32 fNumIndex;
|
||||
UInt32 fIncIndex;
|
||||
T** fBackArray;
|
||||
|
||||
void ICheckBackArray();
|
||||
public:
|
||||
hsSearchVersion(UInt32 len, UInt32 inc = 0);
|
||||
~hsSearchVersion();
|
||||
|
||||
T& operator[]( Int32 index );
|
||||
|
||||
Int32 Find(int where, const T& what, hsBool forceUnique=false);
|
||||
|
||||
UInt32 GetCount() const { return fNextIndex; }
|
||||
};
|
||||
|
||||
template <class T> T& hsSearchVersion<T>::operator[]( Int32 index )
|
||||
{
|
||||
hsDebugCode(hsThrowIfBadParam((UInt32)index >= (UInt32)fNextIndex);)
|
||||
|
||||
return *fBackArray[index];
|
||||
}
|
||||
|
||||
template <class T> hsSearchVersion<T>::hsSearchVersion(UInt32 len, UInt32 inc)
|
||||
: fNextIndex(0)
|
||||
{
|
||||
fIncIndex = inc ? inc : len;
|
||||
fLength = len;
|
||||
fArray = TRACKED_NEW hsVersionNode<T>*[fLength];
|
||||
HSMemory::Clear(fArray, fLength*sizeof(*fArray));
|
||||
fBackArray = TRACKED_NEW T*[fNumIndex = fLength];
|
||||
}
|
||||
|
||||
template <class T> hsSearchVersion<T>::~hsSearchVersion()
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fLength; i++ )
|
||||
delete fArray[i];
|
||||
delete [] fArray;
|
||||
delete [] fBackArray;
|
||||
}
|
||||
|
||||
template <class T> void hsSearchVersion<T>::ICheckBackArray()
|
||||
{
|
||||
if( fNextIndex >= fNumIndex )
|
||||
{
|
||||
T** newBackArray = TRACKED_NEW T*[fNumIndex + fIncIndex];
|
||||
HSMemory::BlockMove(fBackArray, newBackArray, fNextIndex*sizeof(T*));
|
||||
delete [] fBackArray;
|
||||
fBackArray = newBackArray;
|
||||
fNumIndex += fIncIndex;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> Int32 hsSearchVersion<T>::Find(int where, const T&what, hsBool forceUnique)
|
||||
{
|
||||
hsVersionNode<T>* curr = fArray[where];
|
||||
|
||||
ICheckBackArray();
|
||||
|
||||
if( !curr )
|
||||
{
|
||||
hsVersionNode<T>* next = TRACKED_NEW hsVersionNode<T>(fNextIndex, what);
|
||||
fArray[where] = next;
|
||||
fBackArray[fNextIndex] = &next->GetData();
|
||||
return fNextIndex++;
|
||||
}
|
||||
if( *curr == what )
|
||||
return curr->Index();
|
||||
|
||||
while( curr->Next()
|
||||
&& (forceUnique || (*curr->Next() != what)) )
|
||||
curr = curr->Next();
|
||||
|
||||
if( curr->Next() )
|
||||
return curr->Next()->Index();
|
||||
|
||||
hsVersionNode<T>* next = TRACKED_NEW hsVersionNode<T>(fNextIndex, what);
|
||||
curr->Append(next);
|
||||
fBackArray[fNextIndex] = &next->GetData();
|
||||
return fNextIndex++;
|
||||
}
|
||||
|
||||
#endif // hsSearchVersion_inc
|
||||
|
@ -1,143 +1,143 @@
|
||||
/*==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/>.
|
||||
|
||||
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 "plAvg.h"
|
||||
#include <math.h>
|
||||
|
||||
template class TimeBasedAvgRing<float>;
|
||||
template class TimeBasedAvgRing<double>;
|
||||
|
||||
#define PercisionRoundUp(x) (ceil(x / kPercision) * kPercision)
|
||||
|
||||
template <class T>
|
||||
const float TimeBasedAvgRing<T>::kPercision = 0.001;
|
||||
|
||||
template <class T>
|
||||
void TimeBasedAvgRing<T>::AddItem(T value, double time)
|
||||
{
|
||||
hsTempMutexLock lock( fLock );
|
||||
|
||||
if ( fList.empty() )
|
||||
{
|
||||
// initialize with the first time and zero the first value
|
||||
fList.insert(fList.end(),Item<T>(0.0,time));
|
||||
fRingStart = fRingEnd = fList.begin();
|
||||
fAvg = (float)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we're within the percision amount subtract the RingEnd value from total
|
||||
// and update the RingEnd value by adding the current value to it
|
||||
if (time - (*fRingEnd).GetTime() <= kPercision)
|
||||
{
|
||||
fTotal -= PercisionRoundUp((*fRingEnd).GetValue());
|
||||
(*fRingEnd).SetValue((*fRingEnd).GetValue() + value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// clean up the begining of the ring
|
||||
//// there can be some precision loss in the loop time calc
|
||||
//// check to see if the difference is within 1 milli
|
||||
while (time - (*fRingStart).GetTime() > fLen + kPercision
|
||||
&& fRingStart != fRingEnd)
|
||||
{
|
||||
// remove RingStart from the avg part of the average calc
|
||||
fTotal -= (*fRingStart).GetValue();
|
||||
|
||||
TimeList::iterator prev = fRingStart++;
|
||||
|
||||
// loop the ring if needed
|
||||
if (fRingStart == fList.end())
|
||||
fRingStart = fList.begin();
|
||||
|
||||
|
||||
// if the new ring start is in the range, interpolate
|
||||
// and reuse prev
|
||||
if (time - (*fRingStart).GetTime() < fLen)
|
||||
{
|
||||
// remove RingStart from the avg part of the average calc
|
||||
fTotal -= PercisionRoundUp((*fRingStart).GetValue());
|
||||
|
||||
// Set up the interp
|
||||
double remainder = fLen - (time - (*fRingStart).GetTime());
|
||||
double timedelta = (*fRingStart).GetTime() - (*prev).GetTime();
|
||||
(*prev).SetTime((*fRingStart).GetTime() - remainder);
|
||||
(*prev).SetValue(0);
|
||||
// rounding loss occurs here if T is not floting point
|
||||
double scale = remainder/timedelta;
|
||||
hsAssert(scale < 1.0 && scale > 0.0,"Interp Scale Out of Bounds");
|
||||
(*fRingStart).SetValue((float)((*fRingStart).GetValue() * scale));
|
||||
|
||||
// add the new value in
|
||||
fTotal += (*fRingStart).GetValue();
|
||||
|
||||
// put prev back as ring start
|
||||
fRingStart = prev;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// zero total & fAvg if we looped or neg
|
||||
if (fRingStart == fRingEnd || fTotal < 0.0)
|
||||
{
|
||||
fTotal = 0.0;
|
||||
fAvg = 0.0;
|
||||
}
|
||||
|
||||
// put the new value in the ring by expanding the ring if needed
|
||||
// or replacing an empty value
|
||||
fRingEnd++;
|
||||
if (fRingEnd == fList.end())
|
||||
fRingEnd = fList.begin();
|
||||
// Do we have free space?
|
||||
if (fRingEnd == fRingStart)
|
||||
{
|
||||
// no free space
|
||||
fList.insert(fRingEnd,Item<T>(value,time));
|
||||
fRingEnd--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// yes free space @ fRingEnd
|
||||
(*fRingEnd) = Item<T>(value,time);
|
||||
}
|
||||
}
|
||||
|
||||
//update the avg
|
||||
fTotal += (*fRingEnd).GetValue();
|
||||
double currentLen = (*fRingEnd).GetTime() - (*fRingStart).GetTime();
|
||||
if (currentLen < 1.0)
|
||||
fAvg = (float)fTotal;
|
||||
else
|
||||
fAvg = (float)(fTotal / currentLen);
|
||||
}
|
||||
|
||||
// update the max avg
|
||||
fMaxAvg = hsMaximum( fMaxAvg, fAvg );
|
||||
|
||||
}
|
||||
|
||||
/*==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/>.
|
||||
|
||||
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 "plAvg.h"
|
||||
#include <math.h>
|
||||
|
||||
template class TimeBasedAvgRing<float>;
|
||||
template class TimeBasedAvgRing<double>;
|
||||
|
||||
#define PercisionRoundUp(x) (ceil(x / kPercision) * kPercision)
|
||||
|
||||
template <class T>
|
||||
const float TimeBasedAvgRing<T>::kPercision = 0.001;
|
||||
|
||||
template <class T>
|
||||
void TimeBasedAvgRing<T>::AddItem(T value, double time)
|
||||
{
|
||||
hsTempMutexLock lock( fLock );
|
||||
|
||||
if ( fList.empty() )
|
||||
{
|
||||
// initialize with the first time and zero the first value
|
||||
fList.insert(fList.end(),Item<T>(0.0,time));
|
||||
fRingStart = fRingEnd = fList.begin();
|
||||
fAvg = (float)value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we're within the percision amount subtract the RingEnd value from total
|
||||
// and update the RingEnd value by adding the current value to it
|
||||
if (time - (*fRingEnd).GetTime() <= kPercision)
|
||||
{
|
||||
fTotal -= PercisionRoundUp((*fRingEnd).GetValue());
|
||||
(*fRingEnd).SetValue((*fRingEnd).GetValue() + value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// clean up the begining of the ring
|
||||
//// there can be some precision loss in the loop time calc
|
||||
//// check to see if the difference is within 1 milli
|
||||
while (time - (*fRingStart).GetTime() > fLen + kPercision
|
||||
&& fRingStart != fRingEnd)
|
||||
{
|
||||
// remove RingStart from the avg part of the average calc
|
||||
fTotal -= (*fRingStart).GetValue();
|
||||
|
||||
TimeList::iterator prev = fRingStart++;
|
||||
|
||||
// loop the ring if needed
|
||||
if (fRingStart == fList.end())
|
||||
fRingStart = fList.begin();
|
||||
|
||||
|
||||
// if the new ring start is in the range, interpolate
|
||||
// and reuse prev
|
||||
if (time - (*fRingStart).GetTime() < fLen)
|
||||
{
|
||||
// remove RingStart from the avg part of the average calc
|
||||
fTotal -= PercisionRoundUp((*fRingStart).GetValue());
|
||||
|
||||
// Set up the interp
|
||||
double remainder = fLen - (time - (*fRingStart).GetTime());
|
||||
double timedelta = (*fRingStart).GetTime() - (*prev).GetTime();
|
||||
(*prev).SetTime((*fRingStart).GetTime() - remainder);
|
||||
(*prev).SetValue(0);
|
||||
// rounding loss occurs here if T is not floting point
|
||||
double scale = remainder/timedelta;
|
||||
hsAssert(scale < 1.0 && scale > 0.0,"Interp Scale Out of Bounds");
|
||||
(*fRingStart).SetValue((float)((*fRingStart).GetValue() * scale));
|
||||
|
||||
// add the new value in
|
||||
fTotal += (*fRingStart).GetValue();
|
||||
|
||||
// put prev back as ring start
|
||||
fRingStart = prev;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// zero total & fAvg if we looped or neg
|
||||
if (fRingStart == fRingEnd || fTotal < 0.0)
|
||||
{
|
||||
fTotal = 0.0;
|
||||
fAvg = 0.0;
|
||||
}
|
||||
|
||||
// put the new value in the ring by expanding the ring if needed
|
||||
// or replacing an empty value
|
||||
fRingEnd++;
|
||||
if (fRingEnd == fList.end())
|
||||
fRingEnd = fList.begin();
|
||||
// Do we have free space?
|
||||
if (fRingEnd == fRingStart)
|
||||
{
|
||||
// no free space
|
||||
fList.insert(fRingEnd,Item<T>(value,time));
|
||||
fRingEnd--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// yes free space @ fRingEnd
|
||||
(*fRingEnd) = Item<T>(value,time);
|
||||
}
|
||||
}
|
||||
|
||||
//update the avg
|
||||
fTotal += (*fRingEnd).GetValue();
|
||||
double currentLen = (*fRingEnd).GetTime() - (*fRingStart).GetTime();
|
||||
if (currentLen < 1.0)
|
||||
fAvg = (float)fTotal;
|
||||
else
|
||||
fAvg = (float)(fTotal / currentLen);
|
||||
}
|
||||
|
||||
// update the max avg
|
||||
fMaxAvg = hsMaximum( fMaxAvg, fAvg );
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,93 +1,93 @@
|
||||
/*==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/>.
|
||||
|
||||
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 PL_AVG_H
|
||||
#define PL_AVG_H
|
||||
|
||||
#include "hsConfig.h"
|
||||
#include "hsThread.h"
|
||||
#include "hsStlUtils.h"
|
||||
|
||||
|
||||
// A Time based Value Averaging class
|
||||
// implemented in a ring buffer
|
||||
// Values are averaged over the RingLen
|
||||
// independant of frame time
|
||||
// The ring buffer will grow to accomadate
|
||||
// as many samples as added during the Len
|
||||
// Only Accurate to kPercision (0.001) of whatever units
|
||||
// of time are used
|
||||
|
||||
template <class T> class TimeBasedAvgRing
|
||||
{
|
||||
/* T must be a simple type
|
||||
|
||||
If T is not a floating point type then rounding
|
||||
loss may occur when samples are interpolated
|
||||
at window boundries
|
||||
*/
|
||||
private:
|
||||
static const float kPercision;
|
||||
|
||||
template <class S> class Item
|
||||
{
|
||||
private:
|
||||
T fValue;
|
||||
double fTime;
|
||||
public:
|
||||
Item() { Reset(); }
|
||||
Item(const T val, const double time) : fValue(val), fTime(time) { }
|
||||
void Reset() { fValue = 0; fTime = 0; }
|
||||
void SetValue(const T val) { fValue = val; }
|
||||
void SetTime(const double time) { fTime = time; }
|
||||
T GetValue() const { return fValue; }
|
||||
double GetTime() const { return fTime; }
|
||||
};
|
||||
typedef std::list< Item<T> > TimeList;
|
||||
typedef typename TimeList::iterator TimeListIterator; // .NET added typename to be C++ ISO compliant - JL
|
||||
|
||||
TimeList fList;
|
||||
float fLen; // in time
|
||||
float fAvg;
|
||||
float fMaxAvg;
|
||||
double fTotal;
|
||||
TimeListIterator fRingStart, fRingEnd;
|
||||
hsMutex fLock;
|
||||
public:
|
||||
TimeBasedAvgRing():fLen(0.f),fAvg(0.f),fMaxAvg(0.f),fTotal(0.0) {}
|
||||
|
||||
void SetRingLen(const float len) { fLen = len; }
|
||||
float GetRingLen() const { return fLen; }
|
||||
void AddItem(T value, double time);
|
||||
float GetAvg() const { return fAvg; }
|
||||
double GetTotal() const { return fTotal; }
|
||||
float GetMaxAvg() const { return fMaxAvg; }
|
||||
void ResetMaxAvg() { fMaxAvg=fAvg; }
|
||||
void Reset() { fRingStart=fRingEnd; ResetMaxAvg(); }
|
||||
};
|
||||
|
||||
|
||||
#endif // PL_AVG_H
|
||||
|
||||
/*==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/>.
|
||||
|
||||
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 PL_AVG_H
|
||||
#define PL_AVG_H
|
||||
|
||||
#include "hsConfig.h"
|
||||
#include "hsThread.h"
|
||||
#include "hsStlUtils.h"
|
||||
|
||||
|
||||
// A Time based Value Averaging class
|
||||
// implemented in a ring buffer
|
||||
// Values are averaged over the RingLen
|
||||
// independant of frame time
|
||||
// The ring buffer will grow to accomadate
|
||||
// as many samples as added during the Len
|
||||
// Only Accurate to kPercision (0.001) of whatever units
|
||||
// of time are used
|
||||
|
||||
template <class T> class TimeBasedAvgRing
|
||||
{
|
||||
/* T must be a simple type
|
||||
|
||||
If T is not a floating point type then rounding
|
||||
loss may occur when samples are interpolated
|
||||
at window boundries
|
||||
*/
|
||||
private:
|
||||
static const float kPercision;
|
||||
|
||||
template <class S> class Item
|
||||
{
|
||||
private:
|
||||
T fValue;
|
||||
double fTime;
|
||||
public:
|
||||
Item() { Reset(); }
|
||||
Item(const T val, const double time) : fValue(val), fTime(time) { }
|
||||
void Reset() { fValue = 0; fTime = 0; }
|
||||
void SetValue(const T val) { fValue = val; }
|
||||
void SetTime(const double time) { fTime = time; }
|
||||
T GetValue() const { return fValue; }
|
||||
double GetTime() const { return fTime; }
|
||||
};
|
||||
typedef std::list< Item<T> > TimeList;
|
||||
typedef typename TimeList::iterator TimeListIterator; // .NET added typename to be C++ ISO compliant - JL
|
||||
|
||||
TimeList fList;
|
||||
float fLen; // in time
|
||||
float fAvg;
|
||||
float fMaxAvg;
|
||||
double fTotal;
|
||||
TimeListIterator fRingStart, fRingEnd;
|
||||
hsMutex fLock;
|
||||
public:
|
||||
TimeBasedAvgRing():fLen(0.f),fAvg(0.f),fMaxAvg(0.f),fTotal(0.0) {}
|
||||
|
||||
void SetRingLen(const float len) { fLen = len; }
|
||||
float GetRingLen() const { return fLen; }
|
||||
void AddItem(T value, double time);
|
||||
float GetAvg() const { return fAvg; }
|
||||
double GetTotal() const { return fTotal; }
|
||||
float GetMaxAvg() const { return fMaxAvg; }
|
||||
void ResetMaxAvg() { fMaxAvg=fAvg; }
|
||||
void Reset() { fRingStart=fRingEnd; ResetMaxAvg(); }
|
||||
};
|
||||
|
||||
|
||||
#endif // PL_AVG_H
|
||||
|
||||
|
@ -1,121 +1,121 @@
|
||||
/*==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/>.
|
||||
|
||||
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 plRandom_inc
|
||||
#define plRandom_inc
|
||||
|
||||
// FAST_Q is basically lifted from Numerical Recipes.
|
||||
// The RandZeroToOne and RandMinusOneToOne were "enhanced"
|
||||
// a bit, but tested out nicely to generate sequences with
|
||||
// appropriate maxs, mins, and means.
|
||||
// FAST_Q depends on IEEE floating point format. Undefine
|
||||
// it for any platform which doesn't satisfy this, or
|
||||
// come up with the appropriate constants for that platform.
|
||||
#define FAST_Q
|
||||
|
||||
|
||||
class plRandom
|
||||
{
|
||||
protected:
|
||||
mutable UInt32 fSeed;
|
||||
public:
|
||||
inline float RandNorm() const;
|
||||
inline int Rand() const;
|
||||
inline int RandRangeI(int lo, int hi) const;
|
||||
inline float RandRangeF(float lo, float hi) const;
|
||||
inline float RandMinusOneToOne() const;
|
||||
inline float RandZeroToOne() const;
|
||||
|
||||
UInt32 GetSeed() const { return fSeed; }
|
||||
void SetSeed(int seed) { fSeed = seed; }
|
||||
|
||||
plRandom(int seed = 1) : fSeed(seed) {}
|
||||
};
|
||||
|
||||
inline float plRandom::RandNorm() const
|
||||
{
|
||||
#ifndef FAST_Q
|
||||
return 1.f / 32767.f;
|
||||
#else // FAST_Q
|
||||
return (1.f / float(~0UL));
|
||||
#endif // FAST_Q
|
||||
}
|
||||
|
||||
inline int plRandom::Rand() const
|
||||
{
|
||||
#ifndef FAST_Q
|
||||
register int temp;
|
||||
fSeed = fSeed * 1103515245 + 12345;
|
||||
temp = (int)((fSeed/65536)&32767);
|
||||
return (temp);
|
||||
#else // FAST_Q
|
||||
return fSeed = 1664525L * fSeed + 1013904223L;
|
||||
#endif // FAST_Q
|
||||
}
|
||||
|
||||
// RandZeroToOne - take our usual random UInt32.
|
||||
// We're going to mask in an exponent to make it
|
||||
// a float in range [1..2). Then subtract 1.f to
|
||||
// make it [0..1). We shift our random UInt32 down
|
||||
// by 9 because the upper bits are the most random.
|
||||
inline float plRandom::RandZeroToOne() const
|
||||
{
|
||||
#ifndef FAST_Q
|
||||
return Rand() * RandNorm();
|
||||
#else // FAST_Q
|
||||
const UInt32 kOneExp = 0x3f800000;
|
||||
register UInt32 temp = kOneExp | (UInt32(Rand()) >> 9);
|
||||
return (*(float*)&temp) - 1.f;
|
||||
#endif // FAST_Q
|
||||
}
|
||||
|
||||
// RandMinusOneToOne - same as RandZeroToOne, but we
|
||||
// mask in an exponent putting it in range [2..4),
|
||||
// then subtract 3 to give [-1..1).
|
||||
inline float plRandom::RandMinusOneToOne() const
|
||||
{
|
||||
#ifndef FAST_Q
|
||||
return RandZeroToOne() * 2.f - 1.f;
|
||||
#else // FAST_Q
|
||||
const UInt32 kTwoExp = 0x40000000;
|
||||
register UInt32 temp = kTwoExp | (UInt32(Rand()) >> 9);
|
||||
return (*(float*)&temp) - 3.f;
|
||||
#endif // FAST_Q
|
||||
}
|
||||
|
||||
inline float plRandom::RandRangeF(float lo, float hi) const
|
||||
{
|
||||
return lo + RandZeroToOne() * (hi - lo);
|
||||
}
|
||||
|
||||
inline int plRandom::RandRangeI(int lo, int hi) const
|
||||
{
|
||||
return lo + int(RandZeroToOne() * float(hi + 1 - lo));
|
||||
}
|
||||
|
||||
|
||||
#endif // plRandom_inc
|
||||
|
||||
/*==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/>.
|
||||
|
||||
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 plRandom_inc
|
||||
#define plRandom_inc
|
||||
|
||||
// FAST_Q is basically lifted from Numerical Recipes.
|
||||
// The RandZeroToOne and RandMinusOneToOne were "enhanced"
|
||||
// a bit, but tested out nicely to generate sequences with
|
||||
// appropriate maxs, mins, and means.
|
||||
// FAST_Q depends on IEEE floating point format. Undefine
|
||||
// it for any platform which doesn't satisfy this, or
|
||||
// come up with the appropriate constants for that platform.
|
||||
#define FAST_Q
|
||||
|
||||
|
||||
class plRandom
|
||||
{
|
||||
protected:
|
||||
mutable UInt32 fSeed;
|
||||
public:
|
||||
inline float RandNorm() const;
|
||||
inline int Rand() const;
|
||||
inline int RandRangeI(int lo, int hi) const;
|
||||
inline float RandRangeF(float lo, float hi) const;
|
||||
inline float RandMinusOneToOne() const;
|
||||
inline float RandZeroToOne() const;
|
||||
|
||||
UInt32 GetSeed() const { return fSeed; }
|
||||
void SetSeed(int seed) { fSeed = seed; }
|
||||
|
||||
plRandom(int seed = 1) : fSeed(seed) {}
|
||||
};
|
||||
|
||||
inline float plRandom::RandNorm() const
|
||||
{
|
||||
#ifndef FAST_Q
|
||||
return 1.f / 32767.f;
|
||||
#else // FAST_Q
|
||||
return (1.f / float(~0UL));
|
||||
#endif // FAST_Q
|
||||
}
|
||||
|
||||
inline int plRandom::Rand() const
|
||||
{
|
||||
#ifndef FAST_Q
|
||||
register int temp;
|
||||
fSeed = fSeed * 1103515245 + 12345;
|
||||
temp = (int)((fSeed/65536)&32767);
|
||||
return (temp);
|
||||
#else // FAST_Q
|
||||
return fSeed = 1664525L * fSeed + 1013904223L;
|
||||
#endif // FAST_Q
|
||||
}
|
||||
|
||||
// RandZeroToOne - take our usual random UInt32.
|
||||
// We're going to mask in an exponent to make it
|
||||
// a float in range [1..2). Then subtract 1.f to
|
||||
// make it [0..1). We shift our random UInt32 down
|
||||
// by 9 because the upper bits are the most random.
|
||||
inline float plRandom::RandZeroToOne() const
|
||||
{
|
||||
#ifndef FAST_Q
|
||||
return Rand() * RandNorm();
|
||||
#else // FAST_Q
|
||||
const UInt32 kOneExp = 0x3f800000;
|
||||
register UInt32 temp = kOneExp | (UInt32(Rand()) >> 9);
|
||||
return (*(float*)&temp) - 1.f;
|
||||
#endif // FAST_Q
|
||||
}
|
||||
|
||||
// RandMinusOneToOne - same as RandZeroToOne, but we
|
||||
// mask in an exponent putting it in range [2..4),
|
||||
// then subtract 3 to give [-1..1).
|
||||
inline float plRandom::RandMinusOneToOne() const
|
||||
{
|
||||
#ifndef FAST_Q
|
||||
return RandZeroToOne() * 2.f - 1.f;
|
||||
#else // FAST_Q
|
||||
const UInt32 kTwoExp = 0x40000000;
|
||||
register UInt32 temp = kTwoExp | (UInt32(Rand()) >> 9);
|
||||
return (*(float*)&temp) - 3.f;
|
||||
#endif // FAST_Q
|
||||
}
|
||||
|
||||
inline float plRandom::RandRangeF(float lo, float hi) const
|
||||
{
|
||||
return lo + RandZeroToOne() * (hi - lo);
|
||||
}
|
||||
|
||||
inline int plRandom::RandRangeI(int lo, int hi) const
|
||||
{
|
||||
return lo + int(RandZeroToOne() * float(hi + 1 - lo));
|
||||
}
|
||||
|
||||
|
||||
#endif // plRandom_inc
|
||||
|
||||
|
@ -1,314 +1,314 @@
|
||||
/*==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/>.
|
||||
|
||||
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 "hsGeometry3.h"
|
||||
#include "plTriUtils.h"
|
||||
|
||||
static const hsScalar kAlmostZero = 1.e-5f;
|
||||
static const hsScalar kPastZero = -kAlmostZero;
|
||||
static const hsScalar kPastOne = 1.f + kAlmostZero;
|
||||
static const hsScalar kAlmostOne = 1.f - kAlmostZero;
|
||||
static const hsScalar kAlmostZeroSquared = kAlmostZero*kAlmostZero;
|
||||
|
||||
static inline hsVector3 Cross(const hsScalarTriple& p0, const hsScalarTriple& p1)
|
||||
{
|
||||
return hsVector3(p0.fY * p1.fZ - p0.fZ * p1.fY,
|
||||
p0.fZ * p1.fX - p0.fX * p1.fZ,
|
||||
p0.fX * p1.fY - p0.fY * p1.fX);
|
||||
}
|
||||
|
||||
|
||||
// There's actually a possibly faster way to do all this.
|
||||
// The barycentric coordinate in 3-space is the same as the barycentric coordinate of the projection
|
||||
// in 2-space, as long as the projection doesn't degenerate the triangle (i.e. project the tri onto
|
||||
// a plane perpindicular to the tri). The tri can't be perpindicular to all three major axes, so by
|
||||
// picking the right one (or just not picking the wrong one), the lengths of the cross products becomes
|
||||
// just the z component (e.g. v0.x*v1.y - v0.y*v1.x), so all the square roots go away (not to mention all
|
||||
// the vector math going from 3 component to 2).
|
||||
plTriUtils::Bary plTriUtils::ComputeBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
hsVector3 v12(&p1, &p2);
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 norm = Cross(v12, v02);
|
||||
|
||||
hsScalar invLenSq12 = norm.MagnitudeSquared();
|
||||
if( invLenSq12 < kAlmostZero )
|
||||
return kDegenerateTri; // degenerate triangle
|
||||
|
||||
invLenSq12 = 1.f / invLenSq12;
|
||||
|
||||
p += norm * (hsVector3(&p2, &p).InnerProduct(norm) * invLenSq12);
|
||||
|
||||
hsVector3 vp2(&p, &p2);
|
||||
hsVector3 v0 = Cross(v12, vp2);
|
||||
hsVector3 v1 = Cross(vp2, v02);
|
||||
|
||||
return IComputeBarycentric(norm, invLenSq12, v0, v1, out);
|
||||
}
|
||||
|
||||
plTriUtils::Bary plTriUtils::ComputeBarycentric(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
hsVector3 v12(&p1, &p2);
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 norm = Cross(v12, v02);
|
||||
hsScalar invLenSq12 = norm.MagnitudeSquared();
|
||||
if( invLenSq12 < kAlmostZero )
|
||||
return kDegenerateTri; // degenerate triangle
|
||||
|
||||
invLenSq12 = 1.f / invLenSq12;
|
||||
|
||||
hsVector3 vp2(&p, &p2);
|
||||
hsVector3 v0 = Cross(v12, vp2);
|
||||
hsVector3 v1 = Cross(vp2, v02);
|
||||
|
||||
return IComputeBarycentric(norm, invLenSq12, v0, v1, out);
|
||||
}
|
||||
|
||||
|
||||
plTriUtils::Bary plTriUtils::IComputeBarycentric(const hsVector3& v12, hsScalar invLenSq12, const hsVector3& v0, const hsVector3& v1, hsPoint3& out)
|
||||
{
|
||||
UInt32 state = 0;
|
||||
|
||||
hsScalar lenSq0 = v0.MagnitudeSquared();
|
||||
if( lenSq0 < kAlmostZeroSquared )
|
||||
{
|
||||
// On edge p1-p2;
|
||||
out[0] = 0;
|
||||
state |= kOnEdge12;
|
||||
}
|
||||
else
|
||||
{
|
||||
out[0] = lenSq0 * invLenSq12;
|
||||
out[0] = hsSquareRoot(out[0]);
|
||||
//
|
||||
if( v0.InnerProduct(v12) < 0 )
|
||||
{
|
||||
out[0] = -out[0];
|
||||
state |= kOutsideTri;
|
||||
}
|
||||
else if( out[0] > kPastOne )
|
||||
state |= kOutsideTri;
|
||||
else if( out[0] > kAlmostOne )
|
||||
state |= kOnVertex0;
|
||||
}
|
||||
|
||||
hsScalar lenSq1 = v1.MagnitudeSquared();
|
||||
if( lenSq1 < kAlmostZeroSquared )
|
||||
{
|
||||
// On edge p0-p2
|
||||
out[1] = 0;
|
||||
state |= kOnEdge02;
|
||||
}
|
||||
else
|
||||
{
|
||||
out[1] = lenSq1 * invLenSq12;
|
||||
out[1] = hsSquareRoot(out[1]);
|
||||
|
||||
if( v1.InnerProduct(v12) < 0 )
|
||||
{
|
||||
out[1] = -out[1];
|
||||
state |= kOutsideTri;
|
||||
}
|
||||
else if( out[1] > kPastOne )
|
||||
state |= kOutsideTri;
|
||||
else if( out[1] > kAlmostOne )
|
||||
state |= kOnVertex1;
|
||||
}
|
||||
|
||||
// Could make more robust against precision problems
|
||||
// by repeating above for out[2], then normalizing
|
||||
// so sum(out[i]) = 1.f
|
||||
out[2] = 1.f - out[0] - out[1];
|
||||
|
||||
if( out[2] < kPastZero )
|
||||
state |= kOutsideTri;
|
||||
else if( out[2] < kAlmostZero )
|
||||
state |= kOnEdge01;
|
||||
else if( out[2] > kAlmostOne )
|
||||
state |= kOnVertex2;
|
||||
|
||||
/*
|
||||
if( a,b,c outside range [0..1] )
|
||||
p is outside tri;
|
||||
else if( a,b,c == 1 )
|
||||
p is on vert;
|
||||
else if( a,b,c == 0 )
|
||||
p is on edge;
|
||||
*/
|
||||
|
||||
if( state & kOutsideTri )
|
||||
return kOutsideTri;
|
||||
|
||||
if( state & kOnVertex )
|
||||
return Bary(state & kOnVertex);
|
||||
|
||||
if( state & kOnEdge )
|
||||
return Bary(state & kOnEdge);
|
||||
|
||||
return kInsideTri;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int plTriUtils::ISelectAxis(const hsVector3& norm)
|
||||
{
|
||||
int retVal = -2;
|
||||
hsScalar maxDim = 0;
|
||||
int i;
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
if( norm[i] > maxDim )
|
||||
{
|
||||
maxDim = norm[i];
|
||||
retVal = i;
|
||||
}
|
||||
else if( -norm[i] > maxDim )
|
||||
{
|
||||
maxDim = -norm[i];
|
||||
retVal = i;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
hsBool plTriUtils::IFastBarycentric(int iAx, const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
if( --iAx < 0 )
|
||||
iAx = 2;
|
||||
int jAx = iAx - 1;
|
||||
if( jAx < 0 )
|
||||
jAx = 2;
|
||||
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
|
||||
hsScalar totArea = v02[iAx] * v12[jAx] - v02[jAx] * v12[iAx];
|
||||
hsAssert(totArea != 0, "Should have already filtered degerate tris and degenerate projection");
|
||||
|
||||
hsScalar invTotArea = 1.f / totArea;
|
||||
|
||||
hsVector3 vp2(&p, &p2);
|
||||
|
||||
hsScalar aArea = vp2[iAx] * v12[jAx] - vp2[jAx] * v12[iAx];
|
||||
|
||||
hsScalar bArea = v02[iAx] * vp2[jAx] - v02[jAx] * vp2[iAx];
|
||||
|
||||
out[0] = aArea * invTotArea;
|
||||
out[1] = bArea * invTotArea;
|
||||
out[2] = 1.f - out[0] - out[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool plTriUtils::FastBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
|
||||
hsVector3 norm = Cross(v12, v02);
|
||||
hsScalar invLenSq12 = norm.MagnitudeSquared();
|
||||
if( invLenSq12 < kAlmostZero )
|
||||
return false; // degenerate triangle
|
||||
|
||||
invLenSq12 = 1.f / invLenSq12;
|
||||
|
||||
hsVector3 del(&p0, &p);
|
||||
hsScalar delDotNormOverLenSq = del.InnerProduct(norm) * invLenSq12;
|
||||
|
||||
p += norm * delDotNormOverLenSq;
|
||||
|
||||
int iAx = ISelectAxis(norm);
|
||||
hsAssert(iAx >= 0, "Should have already picked out degenerate tris");
|
||||
|
||||
return IFastBarycentric(iAx, p0, p1, p2, p, out);
|
||||
}
|
||||
|
||||
hsBool plTriUtils::FastBarycentric(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
int iAx = ISelectAxis(Cross(v12, v02));
|
||||
if( iAx < 0 )
|
||||
return false;
|
||||
return IFastBarycentric(iAx, p0, p1, p2, p, out);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
hsBool plTriUtils::ProjectOntoPlane(const hsVector3& norm, hsScalar dist, hsPoint3& p)
|
||||
{
|
||||
hsScalar normMagSq = norm.MagnitudeSquared();
|
||||
if( normMagSq > kAlmostZero )
|
||||
{
|
||||
dist /= normMagSq;
|
||||
|
||||
p += norm * dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
hsBool plTriUtils::ProjectOntoPlane(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3& p)
|
||||
{
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
|
||||
hsVector3 norm = v12 % v02;
|
||||
|
||||
hsScalar dist = norm.InnerProduct(p0 - p);
|
||||
|
||||
return ProjectOntoPlane(norm, dist, p);
|
||||
}
|
||||
|
||||
hsBool plTriUtils::ProjectOntoPlaneAlongVector(const hsVector3& norm, hsScalar dist, const hsVector3& vec, hsPoint3& p)
|
||||
{
|
||||
hsScalar s = norm.InnerProduct(vec);
|
||||
const hsScalar kAlmostZero = 1.e-5f;
|
||||
if( (s > kAlmostZero)||(s < kPastZero) )
|
||||
{
|
||||
dist /= s;
|
||||
|
||||
p += vec * dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
hsBool plTriUtils::ProjectOntoPlaneAlongVector(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsVector3& vec, hsPoint3& p)
|
||||
{
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
|
||||
hsVector3 norm = v12 % v02;
|
||||
hsScalar dist = norm.InnerProduct(p0 - p);
|
||||
|
||||
return ProjectOntoPlaneAlongVector(norm, dist, vec, p);
|
||||
/*==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/>.
|
||||
|
||||
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 "hsGeometry3.h"
|
||||
#include "plTriUtils.h"
|
||||
|
||||
static const hsScalar kAlmostZero = 1.e-5f;
|
||||
static const hsScalar kPastZero = -kAlmostZero;
|
||||
static const hsScalar kPastOne = 1.f + kAlmostZero;
|
||||
static const hsScalar kAlmostOne = 1.f - kAlmostZero;
|
||||
static const hsScalar kAlmostZeroSquared = kAlmostZero*kAlmostZero;
|
||||
|
||||
static inline hsVector3 Cross(const hsScalarTriple& p0, const hsScalarTriple& p1)
|
||||
{
|
||||
return hsVector3(p0.fY * p1.fZ - p0.fZ * p1.fY,
|
||||
p0.fZ * p1.fX - p0.fX * p1.fZ,
|
||||
p0.fX * p1.fY - p0.fY * p1.fX);
|
||||
}
|
||||
|
||||
|
||||
// There's actually a possibly faster way to do all this.
|
||||
// The barycentric coordinate in 3-space is the same as the barycentric coordinate of the projection
|
||||
// in 2-space, as long as the projection doesn't degenerate the triangle (i.e. project the tri onto
|
||||
// a plane perpindicular to the tri). The tri can't be perpindicular to all three major axes, so by
|
||||
// picking the right one (or just not picking the wrong one), the lengths of the cross products becomes
|
||||
// just the z component (e.g. v0.x*v1.y - v0.y*v1.x), so all the square roots go away (not to mention all
|
||||
// the vector math going from 3 component to 2).
|
||||
plTriUtils::Bary plTriUtils::ComputeBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
hsVector3 v12(&p1, &p2);
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 norm = Cross(v12, v02);
|
||||
|
||||
hsScalar invLenSq12 = norm.MagnitudeSquared();
|
||||
if( invLenSq12 < kAlmostZero )
|
||||
return kDegenerateTri; // degenerate triangle
|
||||
|
||||
invLenSq12 = 1.f / invLenSq12;
|
||||
|
||||
p += norm * (hsVector3(&p2, &p).InnerProduct(norm) * invLenSq12);
|
||||
|
||||
hsVector3 vp2(&p, &p2);
|
||||
hsVector3 v0 = Cross(v12, vp2);
|
||||
hsVector3 v1 = Cross(vp2, v02);
|
||||
|
||||
return IComputeBarycentric(norm, invLenSq12, v0, v1, out);
|
||||
}
|
||||
|
||||
plTriUtils::Bary plTriUtils::ComputeBarycentric(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
hsVector3 v12(&p1, &p2);
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 norm = Cross(v12, v02);
|
||||
hsScalar invLenSq12 = norm.MagnitudeSquared();
|
||||
if( invLenSq12 < kAlmostZero )
|
||||
return kDegenerateTri; // degenerate triangle
|
||||
|
||||
invLenSq12 = 1.f / invLenSq12;
|
||||
|
||||
hsVector3 vp2(&p, &p2);
|
||||
hsVector3 v0 = Cross(v12, vp2);
|
||||
hsVector3 v1 = Cross(vp2, v02);
|
||||
|
||||
return IComputeBarycentric(norm, invLenSq12, v0, v1, out);
|
||||
}
|
||||
|
||||
|
||||
plTriUtils::Bary plTriUtils::IComputeBarycentric(const hsVector3& v12, hsScalar invLenSq12, const hsVector3& v0, const hsVector3& v1, hsPoint3& out)
|
||||
{
|
||||
UInt32 state = 0;
|
||||
|
||||
hsScalar lenSq0 = v0.MagnitudeSquared();
|
||||
if( lenSq0 < kAlmostZeroSquared )
|
||||
{
|
||||
// On edge p1-p2;
|
||||
out[0] = 0;
|
||||
state |= kOnEdge12;
|
||||
}
|
||||
else
|
||||
{
|
||||
out[0] = lenSq0 * invLenSq12;
|
||||
out[0] = hsSquareRoot(out[0]);
|
||||
//
|
||||
if( v0.InnerProduct(v12) < 0 )
|
||||
{
|
||||
out[0] = -out[0];
|
||||
state |= kOutsideTri;
|
||||
}
|
||||
else if( out[0] > kPastOne )
|
||||
state |= kOutsideTri;
|
||||
else if( out[0] > kAlmostOne )
|
||||
state |= kOnVertex0;
|
||||
}
|
||||
|
||||
hsScalar lenSq1 = v1.MagnitudeSquared();
|
||||
if( lenSq1 < kAlmostZeroSquared )
|
||||
{
|
||||
// On edge p0-p2
|
||||
out[1] = 0;
|
||||
state |= kOnEdge02;
|
||||
}
|
||||
else
|
||||
{
|
||||
out[1] = lenSq1 * invLenSq12;
|
||||
out[1] = hsSquareRoot(out[1]);
|
||||
|
||||
if( v1.InnerProduct(v12) < 0 )
|
||||
{
|
||||
out[1] = -out[1];
|
||||
state |= kOutsideTri;
|
||||
}
|
||||
else if( out[1] > kPastOne )
|
||||
state |= kOutsideTri;
|
||||
else if( out[1] > kAlmostOne )
|
||||
state |= kOnVertex1;
|
||||
}
|
||||
|
||||
// Could make more robust against precision problems
|
||||
// by repeating above for out[2], then normalizing
|
||||
// so sum(out[i]) = 1.f
|
||||
out[2] = 1.f - out[0] - out[1];
|
||||
|
||||
if( out[2] < kPastZero )
|
||||
state |= kOutsideTri;
|
||||
else if( out[2] < kAlmostZero )
|
||||
state |= kOnEdge01;
|
||||
else if( out[2] > kAlmostOne )
|
||||
state |= kOnVertex2;
|
||||
|
||||
/*
|
||||
if( a,b,c outside range [0..1] )
|
||||
p is outside tri;
|
||||
else if( a,b,c == 1 )
|
||||
p is on vert;
|
||||
else if( a,b,c == 0 )
|
||||
p is on edge;
|
||||
*/
|
||||
|
||||
if( state & kOutsideTri )
|
||||
return kOutsideTri;
|
||||
|
||||
if( state & kOnVertex )
|
||||
return Bary(state & kOnVertex);
|
||||
|
||||
if( state & kOnEdge )
|
||||
return Bary(state & kOnEdge);
|
||||
|
||||
return kInsideTri;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int plTriUtils::ISelectAxis(const hsVector3& norm)
|
||||
{
|
||||
int retVal = -2;
|
||||
hsScalar maxDim = 0;
|
||||
int i;
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
if( norm[i] > maxDim )
|
||||
{
|
||||
maxDim = norm[i];
|
||||
retVal = i;
|
||||
}
|
||||
else if( -norm[i] > maxDim )
|
||||
{
|
||||
maxDim = -norm[i];
|
||||
retVal = i;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
hsBool plTriUtils::IFastBarycentric(int iAx, const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
if( --iAx < 0 )
|
||||
iAx = 2;
|
||||
int jAx = iAx - 1;
|
||||
if( jAx < 0 )
|
||||
jAx = 2;
|
||||
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
|
||||
hsScalar totArea = v02[iAx] * v12[jAx] - v02[jAx] * v12[iAx];
|
||||
hsAssert(totArea != 0, "Should have already filtered degerate tris and degenerate projection");
|
||||
|
||||
hsScalar invTotArea = 1.f / totArea;
|
||||
|
||||
hsVector3 vp2(&p, &p2);
|
||||
|
||||
hsScalar aArea = vp2[iAx] * v12[jAx] - vp2[jAx] * v12[iAx];
|
||||
|
||||
hsScalar bArea = v02[iAx] * vp2[jAx] - v02[jAx] * vp2[iAx];
|
||||
|
||||
out[0] = aArea * invTotArea;
|
||||
out[1] = bArea * invTotArea;
|
||||
out[2] = 1.f - out[0] - out[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool plTriUtils::FastBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
|
||||
hsVector3 norm = Cross(v12, v02);
|
||||
hsScalar invLenSq12 = norm.MagnitudeSquared();
|
||||
if( invLenSq12 < kAlmostZero )
|
||||
return false; // degenerate triangle
|
||||
|
||||
invLenSq12 = 1.f / invLenSq12;
|
||||
|
||||
hsVector3 del(&p0, &p);
|
||||
hsScalar delDotNormOverLenSq = del.InnerProduct(norm) * invLenSq12;
|
||||
|
||||
p += norm * delDotNormOverLenSq;
|
||||
|
||||
int iAx = ISelectAxis(norm);
|
||||
hsAssert(iAx >= 0, "Should have already picked out degenerate tris");
|
||||
|
||||
return IFastBarycentric(iAx, p0, p1, p2, p, out);
|
||||
}
|
||||
|
||||
hsBool plTriUtils::FastBarycentric(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out)
|
||||
{
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
int iAx = ISelectAxis(Cross(v12, v02));
|
||||
if( iAx < 0 )
|
||||
return false;
|
||||
return IFastBarycentric(iAx, p0, p1, p2, p, out);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
hsBool plTriUtils::ProjectOntoPlane(const hsVector3& norm, hsScalar dist, hsPoint3& p)
|
||||
{
|
||||
hsScalar normMagSq = norm.MagnitudeSquared();
|
||||
if( normMagSq > kAlmostZero )
|
||||
{
|
||||
dist /= normMagSq;
|
||||
|
||||
p += norm * dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
hsBool plTriUtils::ProjectOntoPlane(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3& p)
|
||||
{
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
|
||||
hsVector3 norm = v12 % v02;
|
||||
|
||||
hsScalar dist = norm.InnerProduct(p0 - p);
|
||||
|
||||
return ProjectOntoPlane(norm, dist, p);
|
||||
}
|
||||
|
||||
hsBool plTriUtils::ProjectOntoPlaneAlongVector(const hsVector3& norm, hsScalar dist, const hsVector3& vec, hsPoint3& p)
|
||||
{
|
||||
hsScalar s = norm.InnerProduct(vec);
|
||||
const hsScalar kAlmostZero = 1.e-5f;
|
||||
if( (s > kAlmostZero)||(s < kPastZero) )
|
||||
{
|
||||
dist /= s;
|
||||
|
||||
p += vec * dist;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
hsBool plTriUtils::ProjectOntoPlaneAlongVector(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsVector3& vec, hsPoint3& p)
|
||||
{
|
||||
hsVector3 v02(&p0, &p2);
|
||||
hsVector3 v12(&p1, &p2);
|
||||
|
||||
hsVector3 norm = v12 % v02;
|
||||
hsScalar dist = norm.InnerProduct(p0 - p);
|
||||
|
||||
return ProjectOntoPlaneAlongVector(norm, dist, vec, p);
|
||||
}
|
@ -1,71 +1,71 @@
|
||||
/*==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/>.
|
||||
|
||||
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 plTriUtils_inc
|
||||
#define plTriUtils_inc
|
||||
|
||||
class plTriUtils
|
||||
{
|
||||
public:
|
||||
enum Bary {
|
||||
kInsideTri = 0x0,
|
||||
kOnVertex0 = 0x1,
|
||||
kOnVertex1 = 0x2,
|
||||
kOnVertex2 = 0x4,
|
||||
kOnVertex = kOnVertex0 | kOnVertex1 | kOnVertex2,
|
||||
kOnEdge01 = 0x8,
|
||||
kOnEdge12 = 0x10,
|
||||
kOnEdge02 = 0x20,
|
||||
kOnEdge = kOnEdge01 | kOnEdge12 | kOnEdge02,
|
||||
|
||||
kOutsideTri = 0x100,
|
||||
|
||||
kDegenerateTri = 0x200,
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
Bary IComputeBarycentric(const hsVector3& v12, hsScalar invLenSq12, const hsVector3& v0, const hsVector3& v1, hsPoint3& out);
|
||||
|
||||
int ISelectAxis(const hsVector3& norm);
|
||||
hsBool IFastBarycentric(int iAx, const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out);
|
||||
public:
|
||||
|
||||
Bary ComputeBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out);
|
||||
Bary ComputeBarycentric(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out);
|
||||
|
||||
|
||||
hsBool FastBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out);
|
||||
hsBool FastBarycentric(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out);
|
||||
|
||||
hsBool ProjectOntoPlane(const hsVector3& norm, hsScalar dist, hsPoint3& p);
|
||||
hsBool ProjectOntoPlane(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3& p);
|
||||
hsBool ProjectOntoPlaneAlongVector(const hsVector3& norm, hsScalar dist, const hsVector3& vec, hsPoint3& p);
|
||||
hsBool ProjectOntoPlaneAlongVector(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsVector3& vec, hsPoint3& p);
|
||||
|
||||
};
|
||||
|
||||
#endif // plTriUtils_inc
|
||||
/*==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/>.
|
||||
|
||||
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 plTriUtils_inc
|
||||
#define plTriUtils_inc
|
||||
|
||||
class plTriUtils
|
||||
{
|
||||
public:
|
||||
enum Bary {
|
||||
kInsideTri = 0x0,
|
||||
kOnVertex0 = 0x1,
|
||||
kOnVertex1 = 0x2,
|
||||
kOnVertex2 = 0x4,
|
||||
kOnVertex = kOnVertex0 | kOnVertex1 | kOnVertex2,
|
||||
kOnEdge01 = 0x8,
|
||||
kOnEdge12 = 0x10,
|
||||
kOnEdge02 = 0x20,
|
||||
kOnEdge = kOnEdge01 | kOnEdge12 | kOnEdge02,
|
||||
|
||||
kOutsideTri = 0x100,
|
||||
|
||||
kDegenerateTri = 0x200,
|
||||
};
|
||||
|
||||
|
||||
protected:
|
||||
Bary IComputeBarycentric(const hsVector3& v12, hsScalar invLenSq12, const hsVector3& v0, const hsVector3& v1, hsPoint3& out);
|
||||
|
||||
int ISelectAxis(const hsVector3& norm);
|
||||
hsBool IFastBarycentric(int iAx, const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out);
|
||||
public:
|
||||
|
||||
Bary ComputeBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out);
|
||||
Bary ComputeBarycentric(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out);
|
||||
|
||||
|
||||
hsBool FastBarycentricProjection(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3&p, hsPoint3& out);
|
||||
hsBool FastBarycentric(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsPoint3&p, hsPoint3& out);
|
||||
|
||||
hsBool ProjectOntoPlane(const hsVector3& norm, hsScalar dist, hsPoint3& p);
|
||||
hsBool ProjectOntoPlane(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, hsPoint3& p);
|
||||
hsBool ProjectOntoPlaneAlongVector(const hsVector3& norm, hsScalar dist, const hsVector3& vec, hsPoint3& p);
|
||||
hsBool ProjectOntoPlaneAlongVector(const hsPoint3& p0, const hsPoint3& p1, const hsPoint3& p2, const hsVector3& vec, hsPoint3& p);
|
||||
|
||||
};
|
||||
|
||||
#endif // plTriUtils_inc
|
||||
|
Reference in New Issue
Block a user