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.

293 lines
13 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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plGBufferGroup Class Header //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 2.21.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plGBufferGroup_h
#define _plGBufferGroup_h
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "hsColorRGBA.h"
//// plGBufferTriangle Struct Definition //////////////////////////////////////
//
// Represents a single triangle inside a plGBufferGroup, which consists of
// three indices (the indices of the three vertices) and a 3-D point
// representing the center of the triangle.
class plGBufferTriangle
{
public:
UInt16 fIndex1, fIndex2, fIndex3, fSpanIndex;
hsPoint3 fCenter;
void Read( hsStream *s );
void Write( hsStream *s );
};
//// plGBufferCell and plGBufferColor Definitions /////////////////////////////
class plGBufferCell
{
public:
UInt32 fVtxStart; // In bytes
UInt32 fColorStart; // In bytes
UInt32 fLength;
plGBufferCell( UInt32 vStart, UInt32 cStart, UInt32 len )
{
fVtxStart = vStart; fColorStart = cStart; fLength = len;
}
plGBufferCell() {}
void Read( hsStream *s );
void Write( hsStream *s );
};
class plGBufferColor
{
public:
UInt32 fDiffuse, fSpecular;
};
//// plGBufferGroup Class Definition //////////////////////////////////////////
//
// Represents a list of vertex and index buffers in a nice package.
class hsStream;
class hsResMgr;
class plPipeline;
class hsGDeviceRef;
class plGeometrySpan;
class plGBufferGroup
{
protected:
UInt8 fFormat;
UInt8 fStride;
UInt8 fLiteStride;
UInt8 fNumSkinWeights;
UInt32 fNumVerts;
UInt32 fNumIndices;
hsBool fVertsVolatile;
hsBool fIdxVolatile;
int fLOD;
hsTArray<hsGDeviceRef *> fVertexBufferRefs;
hsTArray<hsGDeviceRef *> fIndexBufferRefs;
hsTArray<UInt32> fVertBuffSizes;
hsTArray<UInt32> fIdxBuffCounts;
hsTArray<UInt32> fColorBuffCounts;
hsTArray<UInt8 *> fVertBuffStorage;
hsTArray<UInt16 *> fIdxBuffStorage;
hsTArray<UInt32> fVertBuffStarts;
hsTArray<Int32> fVertBuffEnds;
hsTArray<UInt32> fIdxBuffStarts;
hsTArray<Int32> fIdxBuffEnds;
hsTArray<plGBufferColor *> fColorBuffStorage;
hsTArray<hsTArray<plGBufferCell> *> fCells;
virtual void ISendStorageToBuffers( plPipeline *pipe, hsBool adjustForNvidiaLighting );
UInt8 ICalcVertexSize( UInt8 &liteStride );
UInt8* IVertBuffStorage(int iBuff, int iVtx) const { return fVertBuffStorage[iBuff] + iVtx*fStride; }
UInt32 IMakeCell( UInt32 vbIndex, UInt8 flags, UInt32 vStart, UInt32 cStart, UInt32 len, UInt32 *offset );
void IGetStartVtxPointer( UInt32 vbIndex, UInt32 cell, UInt32 offset, UInt8 *&tempPtr, plGBufferColor *&cPtr );
public:
static const UInt32 kMaxNumVertsPerBuffer;
static const UInt32 kMaxNumIndicesPerBuffer;
enum Formats
{
kUVCountMask = 0x0f, // Problem is, we need enough bits to store the max #, which means
// we really want ( max # << 1 ) - 1
kSkinNoWeights = 0x00, // 0000000
kSkin1Weight = 0x10, // 0010000
kSkin2Weights = 0x20, // 0100000
kSkin3Weights = 0x30, // 0110000
kSkinWeightMask = 0x30, // 0110000
kSkinIndices = 0x40, // 1000000
kEncoded = 0x80
};
enum
{
kReserveInterleaved = 0x01,
kReserveVerts = 0x02,
kReserveColors = 0x04,
kReserveSeparated = 0x08,
kReserveIsolate = 0x10
};
plGBufferGroup(UInt8 format, hsBool vertsVolatile, hsBool idxVolatile, int LOD = 0);
~plGBufferGroup();
UInt8 GetNumUVs( void ) const { return ( fFormat & kUVCountMask ); }
UInt8 GetNumWeights() const { return (fFormat & kSkinWeightMask) >> 4; }
static UInt8 CalcNumUVs( UInt8 format ) { return ( format & kUVCountMask ); }
static UInt8 UVCountToFormat( UInt8 numUVs ) { return numUVs & kUVCountMask; }
void DirtyVertexBuffer(int i);
void DirtyIndexBuffer(int i);
hsBool VertexReady(int i) const { return (i < fVertexBufferRefs.GetCount()) && fVertexBufferRefs[i]; }
hsBool IndexReady(int i) const { return (i < fIndexBufferRefs.GetCount()) && fIndexBufferRefs[i]; }
UInt8 GetVertexSize( void ) const { return fStride; }
UInt8 GetVertexLiteStride( void ) const { return fLiteStride; }
UInt8 GetVertexFormat( void ) const { return fFormat; }
UInt32 GetMemUsage( void ) const { return ( fNumVerts * GetVertexSize() ) + ( fNumIndices * sizeof( UInt16 ) ); }
UInt32 GetNumVerts( void ) const { return fNumVerts; }
UInt32 GetNumIndices( void ) const { return fNumIndices; }
UInt32 GetNumPrimaryVertsLeft( void ) const;
UInt32 GetNumVertsLeft( UInt32 idx ) const;
UInt32 GetVertBufferSize(UInt32 idx) const { return fVertBuffSizes[idx]; }
UInt32 GetVertBufferCount(UInt32 idx) const;
UInt32 GetIndexBufferCount(UInt32 idx) const { return fIdxBuffCounts[idx]; }
UInt32 GetVertStartFromCell(UInt32 idx, UInt32 cell, UInt32 offset) const;
// These should only be called by the pipeline, because only it knows when it's safe.
// If the data is volatile, these are no-ops
void PurgeVertBuffer(UInt32 idx);
void PurgeIndexBuffer(UInt32 idx);
///////////////////////////////////////////////////////////////////////////////
// The following group of functions is an advanced optimization, and a pretty
// specialized one at that. It just limits the amount of data that will get
// uploaded to video. If you don't know you are limited by bandwidth to the
// board, or you just don't know what your are doing, don't mess with them.
// If you never touch them, everything will work. If you set them correcly,
// things may work faster. If you set them incorrectly, be sure to save
// all files before running.
// All of these are indices, not bytes. from the beginning of the buffer.
UInt32 GetVertBufferStart(UInt32 idx) const { return fVertBuffStarts[idx]; }
UInt32 GetVertBufferEnd(UInt32 idx) const { return fVertBuffEnds[idx] >= 0 ? UInt32(fVertBuffEnds[idx]) : GetVertBufferCount(idx); }
UInt32 GetIndexBufferStart(UInt32 idx) const { return fIdxBuffStarts[idx]; }
UInt32 GetIndexBufferEnd(UInt32 idx) const { return fIdxBuffEnds[idx] >= 0 ? UInt32(fIdxBuffEnds[idx]) : GetIndexBufferCount(idx); }
void SetVertBufferStart(UInt32 idx, UInt32 s) { fVertBuffStarts[idx] = s; }
void SetVertBufferEnd(UInt32 idx, UInt32 e) { fVertBuffEnds[idx] = e; }
void SetIndexBufferStart(UInt32 idx, UInt32 s) { fIdxBuffStarts[idx] = s; }
void SetIndexBufferEnd(UInt32 idx, UInt32 e) { fIdxBuffEnds[idx] = e; }
///////////////////////////////////////////////////////////////////////////////
UInt32 GetNumVertexBuffers( void ) const { return fVertBuffStorage.GetCount(); }
UInt32 GetNumIndexBuffers( void ) const { return fIdxBuffStorage.GetCount(); }
UInt8 *GetVertBufferData( UInt32 idx ) { return fVertBuffStorage[ idx ]; }
UInt16 *GetIndexBufferData( UInt32 idx ) { return fIdxBuffStorage[ idx ]; }
plGBufferColor *GetColorBufferData( UInt32 idx ) { return fColorBuffStorage[ idx ]; }
hsGDeviceRef *GetVertexBufferRef( UInt32 i );
hsGDeviceRef *GetIndexBufferRef( UInt32 i );
UInt32 GetNumCells( UInt32 idx ) const { return fCells[ idx ]->GetCount(); }
plGBufferCell *GetCell( UInt32 idx, UInt32 cell ) { return &( (*fCells[ idx ])[ cell ] ); }
void SetVertexBufferRef( UInt32 index, hsGDeviceRef *vb );
void SetIndexBufferRef( UInt32 index, hsGDeviceRef *ib );
virtual void Read( hsStream* s );
virtual void Write( hsStream* s );
// Accessor functions
hsPoint3 &Position( int iBuff, UInt32 cell, int iVtx );
hsVector3 &Normal( int iBuff, UInt32 cell, int iVtx );
UInt32 &Color( int iBuff, UInt32 cell, int iVtx );
UInt32 &Specular( int iBuff, UInt32 cell, int iVtx );
hsPoint3 &UV( int iBuff, UInt32 cell, int iVtx, int channel );
UInt32 Format() const { return fFormat; }
// Take temp accumulators and actually build buffer data from them
void TidyUp( void );
// Delete the buffer data storage
void CleanUp( void );
// Take buffer data and convert it to device-specific buffers
void PrepForRendering( plPipeline *pipe, hsBool adjustForNvidiaLighting );
// Reserves space in a vertex buffer
hsBool ReserveVertStorage( UInt32 numVerts, UInt32 *vbIndex, UInt32 *cell, UInt32 *offset, UInt8 flags );
// Append vertex data to the first available storage buffer
void AppendToVertStorage( plGeometrySpan *srcSpan, UInt32 *vbIndex, UInt32 *cell, UInt32 *offset );
void AppendToVertAndColorStorage( plGeometrySpan *srcSpan, UInt32 *vbIndex, UInt32 *cell, UInt32 *offset );
void AppendToColorStorage( plGeometrySpan *srcSpan, UInt32 *vbIndex, UInt32 *cell, UInt32 *offset, UInt32 origCell );
// Reserves space in an index buffer
hsBool ReserveIndexStorage( UInt32 numIndices, UInt32 *ibIndex, UInt32 *ibStart, UInt16 **dataPtr = nil );
// Append index data to the first available storage buffer
void AppendToIndexStorage( UInt32 numIndices, UInt16 *data, UInt32 addToAll, UInt32 *ibIndex, UInt32 *ibStart );
/// Dynamic functions (addition/deletion of raw data)
void DeleteVertsFromStorage( UInt32 which, UInt32 start, UInt32 length );
void AdjustIndicesInStorage( UInt32 which, UInt16 threshhold, Int16 delta );
void DeleteIndicesFromStorage( UInt32 which, UInt32 start, UInt32 length );
// Returns an array of plGBufferTriangles representing the span of indices specified
plGBufferTriangle *ConvertToTriList( Int16 spanIndex, UInt32 whichIdx, UInt32 whichVtx, UInt32 whichCell, UInt32 start, UInt32 numTriangles );
// Stuffs the indices from an array of plGBufferTriangles into the index storage
void StuffFromTriList( UInt32 which, UInt32 start, UInt32 numTriangles, UInt16 *data );
void StuffTri( UInt32 iBuff, UInt32 iTri, UInt16 idx0, UInt16 idx1, UInt16 idx2 );
// Stuff the data from a geometry span into vertex storage
void StuffToVertStorage( plGeometrySpan *srcSpan, UInt32 vbIndex, UInt32 cell, UInt32 offset, UInt8 flags );
// Are our verts volatile?
hsBool AreVertsVolatile() const { return fVertsVolatile; }
hsBool AreIdxVolatile() const { return fIdxVolatile; }
int GetLOD() const { return fLOD; }
};
#endif // _plGBufferGroup_h