You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

264 lines
8.5 KiB

/*==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 plSpanTemplate_inc
#define plSpanTemplate_inc
#include "hsGeometry3.h"
#include "hsBounds.h"
#include "hsColorRGBA.h"
#include "plRenderLevel.h"
class hsStream;
class INode;
class hsGMaterial;
class plSpanTemplate
{
public:
// 99% of the time, the defaults are fine. Just tell me
// how many UVWs, and whether you've got color.
static UInt16 MakeFormat(hsBool hasColor, int numUVWs,
hsBool hasWgtIdx = false,
int numWgts = 0,
hsBool hasNorm = true,
hsBool hasPos = true,
hsBool hasColor2 = true)
{
return (hasPos ? kPosMask : 0)
| (hasNorm ? kNormMask : 0)
| (hasColor ? kColorMask : 0)
| (hasWgtIdx ? kWgtIdxMask : 0)
| ((numUVWs << 4) & kUVWMask)
| ((numWgts << 8) & kWeightMask)
| (hasColor2 ? kColor2Mask : 0); // Till we can get this out of here.
};
enum
{
kPosMask = 0x1,
kNormMask = 0x2,
kColorMask = 0x4,
kWgtIdxMask = 0x8,
kUVWMask = 0xf0,
kWeightMask = 0x300,
kColor2Mask = 0x400
};
enum Channel
{
kPosition,
kWeight,
kWgtIdx,
kNormal,
kColor,
kColor2,
kUVW
};
protected:
UInt16 fNumVerts;
UInt16 fFormat;
UInt8 fStride;
UInt16 fNumTris;
// Data stored interleaved. Any channels may be omitted, but
// existing channels are in exactly the following order:
// Position
// Weights
// Indices
// Normal
// Color
// Color2
// UVWs
UInt8* fData;
UInt16* fIndices;
friend class plClusterUtil;
public:
plSpanTemplate();
virtual ~plSpanTemplate() { DeAlloc(); }
const UInt8* VertData() const { return fData; }
const UInt16* IndexData() const { return fIndices; }
UInt32 NumVerts() const { return fNumVerts; }
UInt32 Stride() const { return UInt32(fStride); }
UInt32 CalcStride();
UInt32 VertSize() const { return NumVerts() * Stride(); }
UInt32 NumTris() const { return fNumTris; }
UInt32 NumIndices() const { return NumTris() * 3; }
UInt32 IndexSize() const { return NumIndices() * sizeof(UInt16); }
UInt8 PositionOffset() const { return UInt8(0); }
UInt8 WgtIdxOffset() const { return UInt8(PositionOffset() + NumPos() * sizeof(hsPoint3)); }
UInt8 WeightOffset() const { return UInt8(WgtIdxOffset() + NumWgtIdx() * sizeof(UInt32)); }
UInt8 NormalOffset() const { return UInt8(WeightOffset() + NumWeights() * sizeof(hsScalar)); }
UInt8 ColorOffset() const { return UInt8(NormalOffset() + NumNorm() * sizeof(hsVector3)); }
UInt8 Color2Offset() const { return UInt8(ColorOffset() + NumColor() * sizeof(UInt32)); }
UInt8 UVWOffset() const { return UInt8(Color2Offset() + NumColor2() * sizeof(UInt32)); }
UInt32 NumUVWs() const { return (fFormat & kUVWMask) >> 4; }
UInt32 NumWeights() const { return (fFormat & kWeightMask) >> 8; }
UInt32 NumPos() const { return (fFormat & kPosMask) >> 0; }
UInt32 NumNorm() const { return (fFormat & kNormMask) >> 1; }
UInt32 NumColor() const { return (fFormat & kColorMask) >> 2; }
UInt32 NumColor2() const { return (fFormat & kColor2Mask) >> 10; }
UInt32 NumWgtIdx() const { return (fFormat & kWgtIdxMask) >> 3; }
hsPoint3* Position(int i) const { return (hsPoint3*)GetData(kPosition, i); }
hsVector3* Normal(int i) const { return (hsVector3*)GetData(kNormal, i); }
UInt32* Color(int i) const { return (UInt32*)GetData(kColor, i); }
UInt32* Color2(int i) const { return (UInt32*)GetData(kColor2, i); }
UInt32* WgtIdx(int i) const { return (UInt32*)GetData(kWgtIdx, i); }
hsPoint3* UVWs(int iv, int iuv) const { return (hsPoint3*)GetData(kUVW, iv, iuv); }
hsScalar* Weight(int iv, int iw) const { return (hsScalar*)GetData(kWeight, iv, iw); }
UInt8* GetData(Channel chan, int i, int j=0) const
{
ValidateInput(chan, i, j);
UInt8* base = fData + i * fStride;
switch(chan)
{
case kPosition:
return base;
case kWeight:
return base
+ NumPos() * sizeof(hsPoint3)
+ j * sizeof(hsScalar);
case kWgtIdx:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar);
case kNormal:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar)
+ NumWgtIdx() * sizeof(UInt32);
case kColor:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar)
+ NumWgtIdx() * sizeof(UInt32)
+ NumNorm() * sizeof(hsVector3);
case kColor2:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar)
+ NumWgtIdx() * sizeof(UInt32)
+ NumNorm() * sizeof(hsVector3)
+ NumColor() * sizeof(UInt32);
case kUVW:
return base
+ NumPos() * sizeof(hsPoint3)
+ NumWeights() * sizeof(hsScalar)
+ NumWgtIdx() * sizeof(UInt32)
+ NumNorm() * sizeof(hsVector3)
+ NumColor() * sizeof(UInt32)
+ NumColor2() * sizeof(UInt32)
+ j * sizeof(hsPoint3);
}
hsAssert(false, "Unrecognized vertex channel");
return nil;
}
hsBool ValidateInput(Channel chan, int i, int j) const
{
switch(chan)
{
case kPosition:
hsAssert(NumPos(), "Invalid data request");
return NumPos() > 0;
case kWeight:
hsAssert(NumWeights(), "Invalid data request");
return NumWeights() > 0;
case kWgtIdx:
hsAssert(NumWgtIdx() > j, "Invalid data request");
return NumWgtIdx() > j;
case kNormal:
hsAssert(NumNorm(), "Invalid data request");
return NumNorm() > 0;
case kColor:
hsAssert(NumColor(), "Invalid data request");
return NumColor() > 0;
case kColor2:
hsAssert(NumColor2(), "Invalid data request");
return NumColor2() > 0;
case kUVW:
hsAssert(NumUVWs() > j, "Invalid data request");
return NumUVWs() > j;
}
hsAssert(false, "Unrecognized vertex channel");
return false;
}
void Alloc(UInt16 format, UInt32 numVerts, UInt32 numTris);
void DeAlloc();
void Read(hsStream* s);
void Write(hsStream* s) const;
};
// An export only version
class plSpanTemplateB : public plSpanTemplate
{
INode* fSrc;
hsBounds3Ext fLocalBounds;
hsColorRGBA* fMultColors;
hsColorRGBA* fAddColors;
public:
plSpanTemplateB(INode* src) : plSpanTemplate(), fSrc(src), fMaterial(nil) {}
virtual ~plSpanTemplateB() { DeAllocColors(); }
void ComputeBounds();
const hsBounds3Ext& GetLocalBounds() const { return fLocalBounds; }
INode* GetSrcNode() const { return fSrc; }
hsGMaterial* fMaterial;
plRenderLevel fRenderLevel;
hsColorRGBA* MultColor(int i) const { return &fMultColors[i]; }
hsColorRGBA* AddColor(int i) const { return &fAddColors[i]; }
void AllocColors();
void DeAllocColors();
};
#endif // plSpanTemplate_inc