/*==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 . 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