2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 14:37:41 +00:00

Initial Commit of CyanWorlds.com Engine Open Source Client/Plugin

This commit is contained in:
JWPlatt
2011-03-12 12:34:52 -05:00
commit a20a222fc2
3976 changed files with 1301355 additions and 0 deletions

View File

@ -0,0 +1,747 @@
/*==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 "hsStream.h"
#include "hsOscillator.h"
#include "../plMath/hsFastMath.h"
#include "hsGTriMesh.h"
#include "hsTriangle3.h"
#include "../plPipeline/plPipeline.h"
#if defined(__MWERKS__) && !defined(HS_DEBUGGING)
#pragma optimization_level 0
#endif
static hsScalar rnd0_1()
{
return hsScalar(rand()) / hsScalar(RAND_MAX);
}
void hsWave::Save(hsStream* s, hsScalar secs)
{
fWorldCenter.Write(s);
s->WriteSwapScalar(fWorldFrequency);
s->WriteSwapScalar(fWorldAmplitude);
s->WriteSwapScalar(fPhase);
s->WriteSwapScalar(fRate);
s->WriteSwapScalar(secs - fStartSecs);
s->WriteSwapScalar(fSecsToLive);
}
void hsWave::Load(hsStream* s, hsScalar secs)
{
fWorldCenter.Read(s);
fWorldFrequency = s->ReadSwapScalar();
fWorldAmplitude = s->ReadSwapScalar();
fPhase = s->ReadSwapScalar();
fRate = s->ReadSwapScalar();
fStartSecs = s->ReadSwapScalar();
fStartSecs = secs - fStartSecs;
fSecsToLive = s->ReadSwapScalar();
}
void hsWave::Init(hsScalar secs, hsPoint3& center, hsScalar per, hsScalar amp, hsScalar rate, hsScalar life, hsBool32 attenOut)
{
fStartSecs = secs;
fWorldCenter = center;
fWorldFrequency = hsScalarInvert(per);
fWorldAmplitude = amp;
fRate = rate;
fSecsToLive = life;
AttenuateOut(attenOut);
}
hsBool32 hsWave::IsSpent(hsScalar secs) const
{
return secs - fStartSecs > fSecsToLive;
}
void hsWave::Accumulate(const hsPoint3& pos, const hsVector3& localZ, hsVector3& accum, hsVector3& accumNorm) const
{
hsVector3 del(&pos, &fLocalCenter);
hsScalar dot = del.InnerProduct(localZ);
dot *= -2.f;
del += localZ * dot;
hsScalar dist = del.MagnitudeSquared();
dist = hsFastMath::InvSqrtAppr(dist);
del *= dist;
dist = hsScalarInvert(dist);
hsScalar ampl = fLocalAmplitude;
if( fAttenuateOutScale > 0 )
{
if( dist > fInnerRadius )
{
if( dist > fOuterRadius )
return;
ampl *= fOuterRadius - dist;
ampl *= fAttenuateOutScale;
}
}
dist *= fLocalFrequency;
dist += fPhase;
hsScalar s, c;
hsFastMath::SinCosAppr(dist, s, c);
s *= ampl;
s += ampl;
c *= ampl * fLocalFrequency;
// accum += s * localZ;
accum.fZ += s / localZ.fZ;
hsVector3 norm;
norm = localZ;
norm += del * -c;
accumNorm += norm;
return;
}
void hsWave::Update(hsScalar secs, const hsMatrix44& l2w, const hsMatrix44& w2l)
{
if( l2w.fFlags & hsMatrix44::kIsIdent )
{
fLocalCenter = fWorldCenter;
fLocalFrequency = fWorldFrequency;
fLocalAmplitude = fWorldAmplitude;
}
else
{
hsVector3 ax;
ax.Set(w2l.fMap[0][2], w2l.fMap[1][2], w2l.fMap[2][2]);
hsScalar ooScale = ax.MagnitudeSquared();
ooScale = hsFastMath::InvSqrtAppr(ooScale);
fLocalCenter = w2l * fWorldCenter;
fLocalFrequency = fWorldFrequency * ooScale;
hsScalar scale = 1.f / ooScale;
fLocalAmplitude = fWorldAmplitude * scale;
}
fLocalAmplitude *= AgeScale(secs);
if( fAttenuateOutScale > 0 )
{
fInnerRadius = fRate * (secs - fStartSecs) * hsScalarPI * 2.f;
fOuterRadius = fInnerRadius * (5.f/4.f);
fAttenuateOutScale = hsScalarInvert(fOuterRadius - fInnerRadius);
}
fPhase = -(secs - fStartSecs) * fRate * hsScalarPI * 2.f;
}
hsScalar hsWave::ScaledAmplitude(hsScalar secs) const
{
return fWorldAmplitude * AgeScale(secs);
}
hsScalar hsWave::AgeScale(hsScalar secs) const
{
hsScalar age = secs - fStartSecs;
extern int dbgCurrentTest;
if( dbgCurrentTest )
{
age *= 4.f;
age -= 2.f * fSecsToLive;
if( age < 0 )
age = -age;
age -= fSecsToLive;
}
else
{
age *= 2.f;
age -= fSecsToLive;
if( age < 0 )
age = -age;
}
hsScalar ageScale = 1.f - age / fSecsToLive;
if( ageScale < 0 )
ageScale = 0;
else if( ageScale > 1.f )
ageScale = 1.f;
return ageScale;
}
hsOscillator::hsOscillator()
{
}
hsOscillator::~hsOscillator()
{
}
hsWave& hsOscillator::GetWeakestWave(hsScalar secs)
{
hsAssert(!GetDisabled(), "Shouldn't be messing with disabled oscillator system");
int weakest = 0;
hsScalar amp = fWaves[0].ScaledAmplitude(secs);
int i;
for( i = 0; i < fWaves.GetCount(); i++ )
{
hsScalar tAmp = fWaves[i].ScaledAmplitude(secs);
if( tAmp < amp )
{
weakest = i;
amp = tAmp;
}
}
return fWaves[weakest];
}
hsWave& hsOscillator::GetTempWave(hsScalar secs)
{
int i;
for( i = 0; i < fTempWaves.GetCount(); i++ )
{
if( fTempWaves[i].IsSpent(secs) )
return fTempWaves[i];
}
fTempWaves.Push();
return fTempWaves[fTempWaves.GetCount()-1];
}
void hsOscillator::ISpawnWave(hsScalar secs, int i)
{
hsPoint3 corner;
fWorldCenterBounds.GetCorner(&corner);
hsVector3 ax[3];
fWorldCenterBounds.GetAxes(ax+0, ax+1, ax+2);
hsScalar r;
r = rnd0_1();
ax[0] *= r;
corner += ax[0];
r = rnd0_1();
ax[1] *= r;
corner += ax[1];
r = rnd0_1();
ax[2] *= r;
corner += ax[2];
hsScalar per = fMinPeriod;
r = rnd0_1();
hsScalar rr = r;
r *= fMaxPeriod - fMinPeriod;
per += r;
hsScalar amp = fMinAmplitude;
r = rr * rnd0_1();
r *= fMaxAmplitude - fMinAmplitude;
amp += r;
hsScalar life = fMinLife;
r = rnd0_1();
r *= fMaxLife - fMinLife;
life += r;
hsScalar rate = fMinRate;
r = rnd0_1();
r *= fMaxRate - fMinRate;
rate += r;
fWaves[i].Init(secs, corner, per, amp, rate, life);
}
void hsOscillator::IUpdate(hsScalar secs, plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l)
{
if( GetDisabled() )
return;
fWorldCenter = pipe->GetViewPositionWorld();
fWorldCenter.fZ = (fWorldCenterBounds.GetMins().fZ + fWorldCenterBounds.GetMaxs().fZ) * 0.5f;
fLocalCenter = w2l * fWorldCenter;
fLocalToWorld = l2w;
fWorldToLocal = w2l;
fLocalX.Set(w2l.fMap[0][0],w2l.fMap[1][0],w2l.fMap[2][0]);
fLocalX.Normalize();
fLocalY.Set(w2l.fMap[0][1],w2l.fMap[1][1],w2l.fMap[2][1]);
fLocalY.Normalize();
fLocalZ.Set(w2l.fMap[0][2],w2l.fMap[1][2],w2l.fMap[2][2]);
fLocalZ.Normalize();
hsVector3 ax;
hsScalar ooScale;
ax.Set(w2l.fMap[0][0], w2l.fMap[1][0], w2l.fMap[2][0]);
ooScale = ax.MagnitudeSquared();
ooScale = hsFastMath::InvSqrtAppr(ooScale);
fLocalAttenScale.fX = fWorldAttenScale.fX * ooScale;
ax.Set(w2l.fMap[0][1], w2l.fMap[1][1], w2l.fMap[2][1]);
ooScale = ax.MagnitudeSquared();
ooScale = hsFastMath::InvSqrtAppr(ooScale);
fLocalAttenScale.fY = fWorldAttenScale.fY * ooScale;
fLocalAttenScale.fZ = 0;
int i;
for( i = 0; i < fWaves.GetCount(); i++ )
{
if( fWaves[i].IsSpent(secs) )
ISpawnWave(secs, i);
fWaves[i].Update(secs, l2w, w2l);
}
for( i = 0; i < fTempWaves.GetCount(); i++ )
{
while( (i < fTempWaves.GetCount()) && fTempWaves[i].IsSpent(secs) )
fTempWaves.Remove(i, 1);
if( i < fTempWaves.GetCount() )
fTempWaves[i].Update(secs, l2w, w2l);
}
}
hsScalar hsOscillator::IAttenuate(const hsPoint3& in) const
{
const hsPoint3& cen = fLocalCenter;
hsVector3 del(&in, &cen);
hsScalar atX = del.InnerProduct(fLocalX);
atX *= fLocalAttenScale.fX;
if( atX > 0 )
atX = -atX;
atX += 1.f;
if( atX < 0 )
atX = 0;
hsScalar atY = del.InnerProduct(fLocalY);
atY *= fLocalAttenScale.fY;
if( atY > 0 )
atY = -atY;
atY += 1.f;
if( atY < 0 )
atY = 0;
hsScalar at = atX * atY;
return at;
}
void hsOscillator::AdjustWorldBounds(const hsMatrix44& l2w, const hsMatrix44& w2l, hsBounds3Ext& bnd) const
{
if( GetDisabled() )
return;
hsVector3 adj;
adj.Set(0,1.f/fLocalZ.fZ,0);
adj = l2w * adj;
adj *= fMaxAmplitude * fWaves.GetCount();
bnd.Union(&adj);
adj = -adj;
bnd.Union(&adj);
}
void hsOscillator::IPerterb(const hsPoint3& in, hsGVertex3& out) const
{
hsPoint3 pos = in;
hsVector3 del(&pos, &fLocalCenter);
hsScalar dot = del.InnerProduct(fLocalZ);
pos += fLocalZ * -dot;
hsVector3 accum;
hsVector3 accumNorm;
accum.Set(0,0,0);
accumNorm.Set(0,0,0);
int i;
for( i = 0; i < fWaves.GetCount(); i++ )
{
fWaves[i].Accumulate(pos, fLocalZ, accum, accumNorm);
}
for( i = 0; i < fTempWaves.GetCount(); i++ )
{
fTempWaves[i].Accumulate(pos, fLocalZ, accum, accumNorm);
}
hsScalar atten = IAttenuate(pos);
static int attenuating = 1;
if( attenuating ) // nuke me
accum *= atten;
out.fLocalPos = in + accum;
hsScalar invNorm = hsFastMath::InvSqrtAppr(accumNorm.MagnitudeSquared());
accumNorm *= invNorm;
out.fNormal = accumNorm;
}
void hsOscillator::Read(hsStream* s)
{
int n = s->ReadSwap32();
SetNumWaves(n);
fWorldAttenScale.Read(s);
fWorldCenterBounds.Read(s);
fMinPeriod = s->ReadSwapScalar();
fMaxPeriod = s->ReadSwapScalar();
fMinAmplitude = s->ReadSwapScalar();
fMaxAmplitude = s->ReadSwapScalar();
fMinRate = s->ReadSwapScalar();
fMaxRate = s->ReadSwapScalar();
fMinLife = s->ReadSwapScalar();
fMaxLife = s->ReadSwapScalar();
int i;
for( i = 0; i < fWaves.GetCount(); i++ )
fWaves[i].Kill();
fTempWaves.Reset();
}
void hsOscillator::Load(hsStream* s, hsScalar secs)
{
Read(s);
int i;
for( i = 0; i < fWaves.GetCount(); i++ )
fWaves[i].Load(s, secs);
fTempWaves.Reset();
}
void hsOscillator::Write(hsStream* s)
{
s->WriteSwap32(fWaves.GetCount());
fWorldAttenScale.Write(s);
fWorldCenterBounds.Write(s);
s->WriteSwapScalar(fMinPeriod);
s->WriteSwapScalar(fMaxPeriod);
s->WriteSwapScalar(fMinAmplitude);
s->WriteSwapScalar(fMaxAmplitude);
s->WriteSwapScalar(fMinRate);
s->WriteSwapScalar(fMaxRate);
s->WriteSwapScalar(fMinLife);
s->WriteSwapScalar(fMaxLife);
}
void hsOscillator::Save(hsStream* s, hsScalar secs)
{
Write(s);
int i;
for( i = 0; i < fWaves.GetCount(); i++ )
fWaves[i].Save(s, secs);
}
void hsOscillator::SetNumWaves(int n)
{
fWaves.SetCount(n);
int i;
for( i = 0; i < n; i++ )
fWaves[i].Kill();
}
void hsOscillator::Init(Int32 nParams, hsScalar* params)
{
// NumWaves = 1
// AttenScale = 2
// WorldCenterBounds = 6
// Period = 2
// Amp = 2
// Rate = 2
// Life = 2
hsAssert(17 == nParams, "Parameter input mismatch");
SetNumWaves(int(*params++));
fWorldAttenScale.fX = *params++;
fWorldAttenScale.fY = *params++;
fWorldAttenScale.fZ = 0;
hsPoint3 pt;
hsBounds3Ext bnd;
pt.fX = *params++;
pt.fY = *params++;
pt.fZ = *params++;
bnd.Reset(&pt);
pt.fX = *params++;
pt.fY = *params++;
pt.fZ = *params++;
bnd.Union(&pt);
SetWorldCenterBounds(bnd);
SetPeriodRange(params[0], params[1]);
params += 2;
SetAmplitudeRange(params[0], params[1]);
params += 2;
SetRateRange(params[0], params[1]);
params += 2;
SetLifeRange(params[0], params[1]);
fTempWaves.Reset();
}
#if 1
hsGTriMesh* hsOscillator::MakeWaveMesh(int nSpokes, const hsPoint3& center, hsScalar minRad, hsScalar maxRad, hsScalar uRange, hsScalar vRange, hsScalar attenStartFrac, hsBool32 stitch)
{
hsGTriMesh* triMesh = new hsGTriMesh;
hsTArray<hsScalar> radii;
hsScalar cRad = 0;
while( cRad < maxRad )
{
// OOPS - for the half circle, this should be PI*R/n, not 2PI. Don't fix until we've corrected the callers. Or we might want to leave it like
// this anyway, since we're looking obliquely at these faces anyway, and this error stretches the side that perspective compresses. May
// want to make the unstitched version wrong in the same way.
hsScalar tRad = 2.f * hsScalarPI * cRad / nSpokes;
if( tRad < minRad )
tRad = minRad;
cRad += tRad;
radii.Append(cRad);
}
int nShell = radii.GetCount();
int nTris = stitch
? 2 * nSpokes * (nShell-1) + nSpokes
: 2 * (nSpokes-1) * (nShell-1) + (nSpokes-1);
int nVerts = nSpokes * nShell + 1;
triMesh->AllocatePointers(nTris, nVerts, nVerts, nVerts);
triMesh->SetNumTriVertex(nVerts);
triMesh->SetNumPoints(nVerts);
triMesh->SetNumUvs(nVerts);
triMesh->SetHasColors(true);
*triMesh->GetPoint(0) = center;
triMesh->GetNormal(0)->Set(0,1.f,0);
triMesh->GetColor(0)->Set(0,0,0,1.f);
triMesh->GetUvs(0)->fX = triMesh->GetUvs(0)->fY = triMesh->GetUvs(0)->fZ = 0;
hsScalar iToRadians = stitch
? 2.f * hsScalarPI / nSpokes
: hsScalarPI / nSpokes;
hsScalar attenStart = maxRad * attenStartFrac;
hsScalar attenEnd = maxRad;
hsScalar attenScale = hsScalarInvert(attenEnd - attenStart);
int i, j;
for( i = 0; i < nSpokes; i++ )
{
hsScalar s = hsSine(i * iToRadians);
hsScalar c = hsCosine(i * iToRadians);
for( j = 0; j < nShell; j++ )
{
hsAssert(1 + i*nShell + j < nVerts, "Going out of range on verts");
hsGVertex3* vtx = triMesh->GetVertex(1 + i*nShell + j);
hsColorRGBA* col = triMesh->GetColor(1 + i*nShell + j);
hsGUv* uv = triMesh->GetUvs(1 + i*nShell + j);
hsScalar x = c * radii[j];
hsScalar y = s * radii[j];
hsScalar u = x / uRange;
hsScalar v = y / vRange;
vtx->fLocalPos.fX = center.fX + x;
vtx->fLocalPos.fY = center.fY + y;
vtx->fLocalPos.fZ = 0.f;
vtx->fNormal.Set(0,0,1.f);
uv->fX = u;
uv->fY = v;
uv->fZ = 0.f;
if( radii[j] > attenStart )
{
hsScalar a = (attenEnd - radii[j]) * attenScale;
if( a < 0 )
a = 0;
else if( a > 1.f )
a = 1.f;
col->Set(0,0,0,a);
}
else
col->Set(0,0,0,1.f);
}
}
int spokeEnd = stitch ? nSpokes : nSpokes-1;
int nextTri = 0;
for( i = 0; i < spokeEnd; i++ )
{
hsTriangle3* tri = triMesh->GetTriFromPool(nextTri);
tri->Zero();
tri->fOrigTri = tri;
triMesh->SetTriangle(nextTri++, tri);
tri->fVert[0] = triMesh->GetTriVertex(0);
tri->fVert[0]->fVtx = triMesh->GetVertex(0);
tri->fVert[0]->SetNumUvChannels(1);
tri->fVert[0]->fUvChan[0] = triMesh->GetUvs(0);
tri->fVert[0]->fVtxColor = triMesh->GetColor(0);
int iv0 = 1 + i * nShell;
int iv1 = i < nSpokes - 1 ? 1 + (i+1)*nShell : 1;
hsAssert((iv0 < nVerts)&&(iv1 < nVerts), "Out of range on triverts");
tri->fVert[1] = triMesh->GetTriVertex(iv0);
tri->fVert[1]->fVtx = triMesh->GetVertex(iv0);
tri->fVert[1]->SetNumUvChannels(1);
tri->fVert[1]->fUvChan[0] = triMesh->GetUvs(iv0);
tri->fVert[1]->fVtxColor = triMesh->GetColor(iv0);
tri->fVert[2] = triMesh->GetTriVertex(iv1);
tri->fVert[2]->fVtx = triMesh->GetVertex(iv1);
tri->fVert[2]->SetNumUvChannels(1);
tri->fVert[2]->fUvChan[0] = triMesh->GetUvs(iv1);
tri->fVert[2]->fVtxColor = triMesh->GetColor(iv1);
tri->fVert[0]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fVert[1]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fVert[2]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fFlags |= hsTriangle3::kHasVertexPosNorms
| hsTriangle3::kHasVertexUvs
| hsTriangle3::kHasVertexColors
| hsTriangle3::kHasPointers;
int iv2 = iv0 + 1;
int iv3 = iv1 + 1;
hsAssert((iv1 < nVerts)&&(iv2 < nVerts), "Out of range on triverts");
for( j = 0; j < nShell-1; j++ )
{
tri = triMesh->GetTriFromPool(nextTri);
tri->Zero();
tri->fOrigTri = tri;
triMesh->SetTriangle(nextTri++, tri);
tri->fVert[0] = triMesh->GetTriVertex(iv0);
tri->fVert[0]->fVtx = triMesh->GetVertex(iv0);
tri->fVert[0]->SetNumUvChannels(1);
tri->fVert[0]->fUvChan[0] = triMesh->GetUvs(iv0);
tri->fVert[0]->fVtxColor = triMesh->GetColor(iv0);
tri->fVert[1] = triMesh->GetTriVertex(iv2);
tri->fVert[1]->fVtx = triMesh->GetVertex(iv2);
tri->fVert[1]->SetNumUvChannels(1);
tri->fVert[1]->fUvChan[1] = triMesh->GetUvs(iv2);
tri->fVert[1]->fVtxColor = triMesh->GetColor(iv2);
tri->fVert[2] = triMesh->GetTriVertex(iv3);
tri->fVert[2]->fVtx = triMesh->GetVertex(iv3);
tri->fVert[2]->SetNumUvChannels(1);
tri->fVert[2]->fUvChan[0] = triMesh->GetUvs(iv3);
tri->fVert[2]->fVtxColor = triMesh->GetColor(iv3);
tri->fVert[0]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fVert[1]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fVert[2]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fFlags |= hsTriangle3::kHasVertexPosNorms
| hsTriangle3::kHasVertexUvs
| hsTriangle3::kHasVertexColors
| hsTriangle3::kHasPointers;
tri = triMesh->GetTriFromPool(nextTri);
tri->Zero();
tri->fOrigTri = tri;
triMesh->SetTriangle(nextTri++, tri);
tri->fVert[0] = triMesh->GetTriVertex(iv0);
tri->fVert[0]->fVtx = triMesh->GetVertex(iv0);
tri->fVert[0]->SetNumUvChannels(1);
tri->fVert[0]->fUvChan[0] = triMesh->GetUvs(iv0);
tri->fVert[0]->fVtxColor = triMesh->GetColor(iv0);
tri->fVert[1] = triMesh->GetTriVertex(iv3);
tri->fVert[1]->fVtx = triMesh->GetVertex(iv3);
tri->fVert[1]->SetNumUvChannels(1);
tri->fVert[1]->fUvChan[0] = triMesh->GetUvs(iv3);
tri->fVert[1]->fVtxColor = triMesh->GetColor(iv3);
tri->fVert[2] = triMesh->GetTriVertex(iv1);
tri->fVert[2]->fVtx = triMesh->GetVertex(iv1);
tri->fVert[2]->SetNumUvChannels(1);
tri->fVert[2]->fUvChan[0] = triMesh->GetUvs(iv1);
tri->fVert[2]->fVtxColor = triMesh->GetColor(iv1);
tri->fVert[0]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fVert[1]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fVert[2]->fFlags = hsGTriVertex::kHasPointers
| hsGTriVertex::kHasVertexUvs
| hsGTriVertex::kHasVertexColors;
tri->fFlags |= hsTriangle3::kHasVertexPosNorms
| hsTriangle3::kHasVertexUvs
| hsTriangle3::kHasVertexColors
| hsTriangle3::kHasPointers;
iv0++;
iv1++;
iv2++;
iv3++;
}
}
hsAssert(nextTri <= nTris, "Out of range on tris");
triMesh->StoreOrigPoints();
return triMesh;
}
#endif

View File

@ -0,0 +1,164 @@
/*==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 hsOscillator_inc
#define hsOscillator_inc
#include "hsPerterber.h"
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "../plIntersect/hsBounds.h"
class hsStream;
class plPipeline;
class hsWave
{
protected:
hsPoint3 fWorldCenter;
hsPoint3 fLocalCenter;
hsScalar fWorldFrequency; // 1.0 / Period
hsScalar fLocalFrequency;
hsScalar fWorldAmplitude;
hsScalar fLocalAmplitude;
hsScalar fPhase;
hsScalar fRate; // how long a crest takes to reach next crest
hsScalar fStartSecs;
hsScalar fSecsToLive;
hsScalar fInnerRadius;
hsScalar fOuterRadius;
hsScalar fAttenuateOutScale;
hsScalar AgeScale(hsScalar secs) const;
public:
void Accumulate(const hsPoint3& pos, const hsVector3& localZ, hsVector3& accum, hsVector3& accumNorm) const;
hsScalar ScaledAmplitude(hsScalar secs) const;
void Init(hsScalar secs, hsPoint3& center, hsScalar per, hsScalar amp, hsScalar rate, hsScalar life, hsBool32 attenOut=false);
void Update(hsScalar secs, const hsMatrix44& l2w, const hsMatrix44& w2l);
hsBool32 IsSpent(hsScalar secs) const;
void Kill() { fStartSecs = fSecsToLive = 0; }
void AttenuateOut(hsBool32 on) { fAttenuateOutScale = (on ? 1.f : 0); }
hsBool32 GetAttenuateOut() { return fAttenuateOutScale > 0; }
void Save(hsStream* s, hsScalar secs);
void Load(hsStream* s, hsScalar secs);
};
class hsOscillator : public hsPerterber
{
protected:
hsTArray<hsWave> fWaves;
hsTArray<hsWave> fTempWaves;
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
hsPoint3 fWorldCenter;
hsPoint3 fLocalCenter;
hsVector3 fWorldAttenScale;
hsVector3 fLocalAttenScale;
hsBounds3Ext fWorldCenterBounds;
hsScalar fMinPeriod;
hsScalar fMaxPeriod;
hsScalar fMinAmplitude;
hsScalar fMaxAmplitude;
hsScalar fMinRate;
hsScalar fMaxRate;
hsScalar fMinLife;
hsScalar fMaxLife;
hsVector3 fLocalX;
hsVector3 fLocalY;
hsVector3 fLocalZ;
hsScalar IAttenuate(const hsPoint3& in) const;
void ISpawnWave(hsScalar secs, int i);
virtual void IUpdate(hsScalar secs, plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual void IPerterb(const hsPoint3& in, hsGVertex3& out) const;
public:
hsOscillator();
virtual ~hsOscillator();
virtual void AdjustWorldBounds(const hsMatrix44& l2w, const hsMatrix44& w2l, hsBounds3Ext& bnd) const;
virtual UInt32 GetType() const { return kTypeOscillator; }
// Don't call these, use base class LabelAndWrite() and CreateAndRead()
virtual void Read(hsStream* s);
virtual void Write(hsStream* s);
virtual void Load(hsStream* s, hsScalar secs);
virtual void Save(hsStream* s, hsScalar secs);
void SetPeriodRange(hsScalar lo, hsScalar hi) { fMinPeriod = lo; fMaxPeriod = hi; }
void SetAmplitudeRange(hsScalar lo, hsScalar hi) { fMinAmplitude = lo; fMaxAmplitude = hi; }
void SetRateRange(hsScalar lo, hsScalar hi) { fMinRate = lo; fMaxRate = hi; }
void SetLifeRange(hsScalar lo, hsScalar hi) { fMinLife = lo; fMaxLife = hi; }
hsScalar GetMinPeriod() const { return fMinPeriod; }
hsScalar GetMaxPeriod() const { return fMaxPeriod; }
hsScalar GetMinAmplitude() const { return fMinAmplitude; }
hsScalar GetMaxAmplitude() const { return fMaxAmplitude; }
hsScalar GetMinRate() const { return fMinRate; }
hsScalar GetMaxRate() const { return fMaxRate; }
hsScalar GetMinLife() const { return fMinLife; }
hsScalar GetMaxLife() const { return fMaxLife; }
void SetWorldAttenScale(const hsVector3& s) { fWorldAttenScale = s; }
void SetWorldCenterBounds(const hsBounds3Ext& bnd) { fWorldCenterBounds = bnd; }
const hsVector3& GetWorldAttenScale() const { return fWorldAttenScale; }
const hsBounds3Ext& GetWorldCenterBounds() const { return fWorldCenterBounds; }
void SetNumWaves(int n);
UInt32 GetNumWaves() const { return fWaves.GetCount(); }
hsWave& GetWeakestWave(hsScalar secs);
hsWave& GetTempWave(hsScalar secs);
virtual void Init(Int32 nParams, hsScalar* params);
static hsGTriMesh* MakeWaveMesh(int nSpokes, const hsPoint3& center, hsScalar minRad, hsScalar maxRad, hsScalar uRange, hsScalar vRange, hsScalar attenStartFrac, hsBool32 stitch);
};
#endif // hsOscillator_inc

View File

@ -0,0 +1,334 @@
/*==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 "hsStream.h"
#include "hsPerterber.h"
#include "hsOscillator.h"
#include "hsGMesh.h"
#if 0 // GET_RID_OF_SHAPE_LAYER_DEFER
#include "hsGShape3.h"
#include "hsGShape3MegaMesh.h"
#endif// GET_RID_OF_SHAPE_LAYER_DEFER
#include "../plResMgr/plKey.h"
#include "../plSurface/hsGMaterial.h"
#include "hsTimer.h"
#include "../plPipeline/plPipeline.h"
hsBool32 hsPerterber::fDisabled = false;
hsPerterber::hsPerterber()
{
}
hsPerterber::~hsPerterber()
{
}
void hsPerterber::IUpdate(hsScalar secs, plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l)
{
}
void hsPerterber::TimeStampAndSave(hsStream* s)
{
hsScalar secs = hsTimer::GetSeconds();
hsKeyedObject::Save(s, nil);
Save(s, secs);
}
void hsPerterber::TimeStampAndLoad(hsStream* s)
{
hsScalar secs = hsTimer::GetSeconds();
hsKeyedObject::Load(s, nil);
Load(s, secs);
}
void hsPerterber::LabelAndWrite(hsStream* s)
{
s->WriteSwap32(GetType());
Write(s);
}
hsPerterber* hsPerterber::CreateAndRead(hsStream* s)
{
hsPerterber* retVal = nil;
UInt32 t = s->ReadSwap32();
switch( t )
{
case kTypeOscillator:
retVal = new hsOscillator;
break;
default:
hsAssert(false, "Unknown perterber type");
return nil;
}
retVal->Read(s);
return retVal;
}
hsGMesh* hsPerterber::IGetMesh(hsGShape3* shape)
{
hsGMesh* mesh = nil;
#if 0 // GET_RID_OF_SHAPE_LAYER_DEFER
if( shape->GetShapeType() == hsGShape3::kTypeTriMesh )
{
hsGShape3TriMesh* shp = (hsGShape3TriMesh*)shape;
mesh = shp->GetMesh();
#if 0 // move to export
if( mesh->GetKey() && strstr(mesh->GetKey()->GetName(), "create") )
{
hsTArray<hsGMaterial*> matList;
shp->AppendMaterials(matList);
hsGTriMesh* newMesh = hsOscillator::MakeWaveMesh(40, hsPoint3(0,0,0), 4.f, 75.f, 1200.f, 1200.f, 0.75f, false);
newMesh->SetMaterial(matList[0]);
hsRefCnt_SafeUnRef(matList[0]);
shp->SetMesh(newMesh);
hsRefCnt_SafeUnRef(newMesh);
mesh = newMesh;
}
else if( mesh->GetKey() && strstr(mesh->GetKey()->GetName(), "destroy") )
{
hsTArray<hsGMaterial*> matList;
shp->AppendMaterials(matList);
hsGTriMesh* newMesh = hsOscillator::MakeWaveMesh(50, hsPoint3(0,0,0), 1.5f, 30.f, 600.f, 600.f, 0.6f, true);
newMesh->SetMaterial(matList[0]);
hsRefCnt_SafeUnRef(matList[0]);
shp->SetMesh(newMesh);
hsRefCnt_SafeUnRef(newMesh);
mesh = newMesh;
}
else
#endif // move to export
{
hsGTriMesh* triMesh = (hsGTriMesh*)shp->GetMesh();
if( triMesh->GetTriangle(0)->fFlags & hsTriangle3::kHasFacePlane )
triMesh->TrashPlanes();
mesh = triMesh;
}
}
else if( shape->GetShapeType() == hsGShape3::kTypeMegaMesh )
{
hsGShape3MegaMesh* mega = (hsGShape3MegaMesh*)shape;
hsGMegaMesh* megaMesh = (hsGMegaMesh*)mega->GetMegaMesh();
hsGTriMesh* triMesh = (hsGTriMesh*)megaMesh->GetMesh(0);
if( triMesh->GetTriangle(0)->fFlags & hsTriangle3::kHasFacePlane )
{
int iMesh;
for( iMesh = 0; iMesh < megaMesh->GetMeshCount(); iMesh++ )
{
triMesh = (hsGTriMesh*)megaMesh->GetMesh(iMesh);
triMesh->TrashPlanes();
}
}
mesh = mega->GetMegaMesh();
}
#endif // GET_RID_OF_SHAPE_LAYER_DEFER
return mesh;
}
void hsPerterber::Perterb(hsScalar secs, plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l, hsGShape3* shape)
{
if( GetDisabled() )
return;
hsGMesh* mesh = IGetMesh(shape);
IUpdate(secs, pipe, l2w, w2l);
if( !mesh->HasOrigPoints() )
mesh->StoreOrigPoints();
int i;
for( i = 0; i < mesh->GetNumPoints(); i++ )
{
IPerterb(*mesh->GetOrigPoint(i), *mesh->GetVertex(i));
}
}
const int kPertCount = 6;
const int kMaxPertParams = 32;
struct hsPertDesc
{
char fName[256];
UInt32 fType;
UInt32 fNumParams;
hsScalar fParams[kMaxPertParams];
};
// NumWaves = 1
// AttenScale = 2
// WorldCenterBounds = 6
// Period = 2
// Amp = 2
// Rate = 2
// Life = 2
//
hsPertDesc sPertTable[kPertCount] =
{
{
"mystocean",
hsPerterber::kTypeOscillator,
17,
{
5.f,
1.f/100.f, 1.f/100.f,
-100.f, 100.f, 0, 100.f, 150.f, 0,
2.f, 5.f,
0.5, 0.75f,
0.68f, 0.68f,
5.f, 10.f
}
},
{
"stoneocean",
hsPerterber::kTypeOscillator,
17,
{
5.f,
1.f/100.f, 1.f/100.f,
-100.f, 100.f, 0, 100.f, 150.f, 0,
2.f, 5.f,
0.5, 0.75f,
0.68f, 0.68f,
5.f, 10.f
}
},
{
"seleniticocean",
hsPerterber::kTypeOscillator,
17,
{
5.f,
1.f/100.f, 1.f/100.f,
-100.f, 100.f, 0, 100.f, 150.f, 0,
2.f, 5.f,
0.25, 0.45f,
0.6f, 0.6f,
5.f, 10.f
}
},
{
"channelocean",
hsPerterber::kTypeOscillator,
17,
{
5.f,
1.f/30.f, 1.f/30.f,
-100.f, -100.f, 0, 100.f, 100.f, 0,
0.25f, 0.5f,
0.1, 0.2f,
0.4f, 0.8f,
5.f, 10.f
}
},
{
"mechocean",
hsPerterber::kTypeOscillator,
17,
{
5.f,
1.f/100.f, 1.f/100.f,
-100.f, 100.f, 0, 100.f, 150.f, 0,
2.f, 5.f,
0.5, 0.4f,
0.68f, 0.68f,
5.f, 10.f
}
},
{
"rimeocean",
hsPerterber::kTypeOscillator,
17,
{
5.f,
1.f/100.f, 1.f/100.f,
-100.f, 100.f, 0, 100.f, 150.f, 0,
2.f, 5.f,
0.5, 0.75,
0.68f, 0.68f,
5.f, 10.f
}
}
};
#if 0 // Used Registry...need to change paulg
void hsPerterber::InitSystem(hsRegistry* reg)
{
if( GetDisabled() )
return;
int i;
for( i = 0; i < kPertCount; i++ )
{
switch( sPertTable[i].fType )
{
case kTypeOscillator:
{
hsOscillator* oscar = new hsOscillator;
oscar->Init(sPertTable[i].fNumParams, sPertTable[i].fParams);
#ifdef PAULFIX
oscar->Register(reg, sPertTable[i].fName, 0, true);
#endif
}
break;
default:
hsAssert(false, "Unknown perterber type");
break;
}
}
}
void hsPerterber::Shutdown(hsRegistry* reg)
{
#ifdef PAULFIX
int i;
for( i = 0; i < reg->GetNumKeys(); i++ )
{
hsPerterber* pert = (hsPerterber*)(reg->GetKey(i)->GetObjectPtr());
delete pert;
}
#endif
}
#endif

View File

@ -0,0 +1,91 @@
/*==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 hsPerterber_inc
#define hsPerterber_inc
#include "../plResMgr/hsKeyedObject.h"
#include "hsGeometry3.h"
class hsStream;
class hsGShape3;
class hsBounds3Ext;
class hsGMesh;
class plPipeline;
struct hsMatrix44;
struct hsGVertex3;
class hsPerterber : public hsKeyedObject
{
public:
enum {
kTypeUndefined = 0x0,
kTypeOscillator = 0x1
};
protected:
static hsBool32 fDisabled;
virtual void IUpdate(hsScalar secs, plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l);
virtual void IPerterb(const hsPoint3& in, hsGVertex3& out) const = 0;
hsGMesh* IGetMesh(hsGShape3* shape);
public:
hsPerterber();
virtual ~hsPerterber();
static void SetDisabled(hsBool32 on) { fDisabled = on; }
static void ToggleDisabled() { fDisabled = !fDisabled; }
static hsBool32 GetDisabled() { return fDisabled; }
virtual void Perterb(hsScalar secs, plPipeline* pipe, const hsMatrix44& l2w, const hsMatrix44& w2l, hsGShape3* shape);
virtual void AdjustWorldBounds(const hsMatrix44& l2w, const hsMatrix44& w2l, hsBounds3Ext& bnd) const = 0;
virtual UInt32 GetType() const = 0;
virtual void Write(hsStream* s) = 0;
virtual void Read(hsStream* s) = 0;
virtual void Save(hsStream* s, hsScalar secs) = 0;
virtual void Load(hsStream* s, hsScalar secs) = 0;
void TimeStampAndSave(hsStream* s);
void TimeStampAndLoad(hsStream* s);
void LabelAndWrite(hsStream* s);
static hsPerterber* CreateAndRead(hsStream* s);
virtual void Init(Int32 nParams, hsScalar* params) = 0;
#if 0 // Used Registry...need to change paulg
static void InitSystem(plResMgr* reg);
static void Shutdown(plResMgr* reg);
#endif
};
#endif hsPerterber_inc

View File

@ -0,0 +1,54 @@
/*==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 plGeometryCreatable_inc
#define plGeometryCreatable_inc
#include "../pnFactory/plCreator.h"
/* Taken out 6.12.2001 mcn - You can remove this file entirely if you wish, I just left
it in in case we wanted to use it in the future...
#include "hsGVertexPool.h"
REGISTER_CREATABLE( hsGVertexPool );
#include "hsGMesh.h"
REGISTER_NONCREATABLE( hsGMesh );
#include "hsGTriMesh.h"
REGISTER_CREATABLE( hsGTriMesh );
#include "hsGMegaMesh.h"
REGISTER_CREATABLE( hsGMegaMesh );
*/
#endif plGeometryCreatable_inc