/*==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 plSpanInstance_inc #define plSpanInstance_inc #include "hsGeometry3.h" #include "hsMatrix44.h" // plClusterGroup // array of templates // array of materials (indexed by templates) // array of clusters // array of LOD blend // array of vis sets // plCluster // array of span instances that are combinable // LOD blend start and end index // vis set index // Combinable means: // same material // same format // same LOD blend // same vis set // same lights // same encoding? // plSpanInstance // template idx // 3x4 transform // encoding flags // (what components does it include, delPos? color?) // (what's the encoding? 32bit RGBA? 16Bit/Chan? 10Bit/Chan? 8Bit/Chan?) // (need an encoding per channel) // plSpanTemplate // numVerts // Format (assume pos & norm?) // kUVWMask // kColMask // kWeightMask // fPos // fNorm // fCol // fUVWs // fWeights class plSpanEncoding { public: enum { kPosNone = 0x0, kPos888 = 0x1, kPos161616 = 0x2, kPos101010 = 0x4, kPos008 = 0x8, kPosMask = kPos888 | kPos161616 | kPos101010 | kPos008, kColNone = 0x0, kColA8 = 0x10, kColI8 = 0x20, kColAI88 = 0x40, kColRGB888 = 0x80, kColARGB8888 = 0x100, kColMask = kColNone | kColA8 | kColI8 | kColAI88 | kColRGB888 | kColARGB8888, }; UInt32 fCode; hsScalar fPosScale; plSpanEncoding() : fCode(kPosNone|kColNone), fPosScale(0) {} plSpanEncoding(UInt32 c, hsScalar s) : fCode(c), fPosScale(s) {} UInt32 Code() const { return fCode; } hsScalar Scale() const { return fPosScale; } void Read(hsStream* s); void Write(hsStream* s) const; }; class plSpanInstance { protected: UInt8* fPosDelta; UInt8* fCol; hsScalar fL2W[3][4]; friend class plSpanInstanceIter; public: plSpanInstance(); ~plSpanInstance(); void Read(hsStream* s, const plSpanEncoding& encoding, UInt32 numVerts); void Write(hsStream* s, const plSpanEncoding& encoding, UInt32 numVerts) const; void Encode(const plSpanEncoding& encoding, UInt32 numVerts, const hsVector3* delPos, const UInt32* color); void Alloc(const plSpanEncoding& encoding, UInt32 numVerts); void DeAlloc(); hsMatrix44 LocalToWorld() const; hsMatrix44 WorldToLocal() const; void SetLocalToWorld(const hsMatrix44& l2w); hsBool HasPosDelta() const { return fPosDelta != nil; } hsBool HasColor() const { return fCol != nil; } static UInt16 PosStrideFromEncoding(const plSpanEncoding& encoding) { switch(encoding.fCode & plSpanEncoding::kPosMask) { case plSpanEncoding::kPos888: return 3; case plSpanEncoding::kPos161616: return 6; case plSpanEncoding::kPos101010: return 4; case plSpanEncoding::kPos008: return 1; } return 0; } static UInt16 ColStrideFromEncoding(const plSpanEncoding& encoding) { switch(encoding.fCode & plSpanEncoding::kPosMask) { case plSpanEncoding::kColNone: return 0; case plSpanEncoding::kColA8: return 1; case plSpanEncoding::kColI8: return 1; case plSpanEncoding::kColAI88: return 2; case plSpanEncoding::kColRGB888: return 3; case plSpanEncoding::kColARGB8888: return 4; } return 0; } }; class plSpanInstanceIter { protected: plSpanInstance* fInst; plSpanEncoding fEncoding; UInt32 fNumVerts; Int32 fNumVertsLeft; UInt16 fPosStride; UInt16 fColStride; union { Int8* fPos888; Int16* fPos161616; UInt32* fPos101010; }; union { UInt8* fA8; UInt8* fI8; UInt16* fAI88; UInt8* fRGB888; UInt32* fARGB8888; }; public: plSpanInstanceIter(); plSpanInstanceIter(plSpanInstance* inst, const plSpanEncoding& encoding, UInt32 numVerts) { Init(inst, encoding, numVerts); } void Init(plSpanInstance* inst, const plSpanEncoding& encoding, UInt32 numVerts) { fInst = inst; fEncoding = encoding; fNumVerts = numVerts; fPosStride = inst->PosStrideFromEncoding(fEncoding); fColStride = inst->ColStrideFromEncoding(fEncoding); fNumVertsLeft = 0; } void Begin() { fPos888 = (Int8*)fInst->fPosDelta; fA8 = fInst->fCol; fNumVertsLeft = fNumVerts; } void Advance() { fPos888 += fPosStride; fA8 += fColStride; fNumVertsLeft--; } hsBool More() const { return fNumVertsLeft > 0; } hsVector3 DelPos() const { switch(fEncoding.fCode & plSpanEncoding::kPosMask) { case plSpanEncoding::kPos888: return hsVector3(fPos888[0] * fEncoding.fPosScale, fPos888[1] * fEncoding.fPosScale, fPos888[2] * fEncoding.fPosScale); case plSpanEncoding::kPos161616: return hsVector3(fPos161616[0] * fEncoding.fPosScale, fPos161616[1] * fEncoding.fPosScale, fPos161616[2] * fEncoding.fPosScale); case plSpanEncoding::kPos101010: return hsVector3(int(*fPos101010 & 0x3f) * fEncoding.fPosScale, int((*fPos101010 >> 10) & 0x3f) * fEncoding.fPosScale, int((*fPos101010 >> 20) & 0x3f) * fEncoding.fPosScale); case plSpanEncoding::kPos008: return hsVector3(0,0, *fPos888 * fEncoding.fPosScale); } return hsVector3(0,0,0); }; hsPoint3 Position(const hsPoint3& p) const { hsPoint3 pos(p); pos += DelPos(); return pos; }; UInt32 Color(UInt32 c) const { switch(fEncoding.fCode & plSpanEncoding::kColMask) { case plSpanEncoding::kColA8: return (c & 0x00ffffff) | *fA8; case plSpanEncoding::kColI8: return (c & 0xff000000) | (*fI8 << 16) | (*fI8 << 8) | (*fI8 << 0); case plSpanEncoding::kColAI88: { const UInt32 col = *fAI88 & 0xff; return ((*fAI88 & 0xff00) << 24) | (col << 16) | (col << 8) | (col << 0); } case plSpanEncoding::kColRGB888: return (c & 0xff000000) | (fRGB888[0] << 16) | (fRGB888[1] << 8) | (fRGB888[2] << 0); case plSpanEncoding::kColARGB8888: return *fARGB8888; } return c; }; }; #endif // plSpanInstance_inc