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.
296 lines
11 KiB
296 lines
11 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==*/ |
|
////////////////////////////////////////////////////////////////////////////// |
|
// // |
|
// plGeometrySpan Header // |
|
// // |
|
// plGeometrySpans are abstract reprentations of Plasma 2.0 geometry data. // |
|
// They consist of a material, a transform, bounds and an abstract vertex // |
|
// and index buffer pair. plGeometrySpans is what is fed to plDrawableIce // |
|
// to convert into its own internal data structures; the format for the // |
|
// vertex and index data is (or should be) identical. More or less, they // |
|
// are identical to Ice's plIcicle, but this is more abstract (read: not // |
|
// internal to Ice). // |
|
// // |
|
// Also included is a temporary hacked triMesh-to-geometrySpan[] converter // |
|
// for everyone's convenience until triMeshes disappear. // |
|
// // |
|
//// Version History ///////////////////////////////////////////////////////// |
|
// // |
|
// Created 3.8.2001 mcn // |
|
// // |
|
////////////////////////////////////////////////////////////////////////////// |
|
|
|
#ifndef _plGeometrySpan_h |
|
#define _plGeometrySpan_h |
|
|
|
|
|
#include "hsTemplates.h" |
|
#include "hsBounds.h" |
|
#include "hsMatrix44.h" |
|
#include "hsColorRGBA.h" |
|
#include "hsBitVector.h" |
|
|
|
class hsGMaterial; |
|
class plFogEnvironment; |
|
|
|
|
|
//// plGeometrySpan Class Definition ///////////////////////////////////////// |
|
|
|
class plGeometrySpan |
|
{ |
|
public: |
|
enum |
|
{ |
|
kMaxNumUVChannels = 8 |
|
}; |
|
|
|
/// Duplication of the formats from plGBufferGroup; theoretically, they |
|
/// could be different, but they're identical for now |
|
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 |
|
}; |
|
|
|
enum Properties |
|
{ |
|
kPropRunTimeLight = 0x01, |
|
kPropNoPreShade = 0x02, |
|
kLiteMaterial = 0x00, |
|
kLiteVtxPreshaded = 0x04, |
|
kLiteVtxNonPreshaded = 0x08, |
|
kLiteMask = 0x0c, |
|
kRequiresBlending = 0x10, |
|
kInstanced = 0x20, |
|
kUserOwned = 0x40, |
|
kPropNoShadow = 0x80, |
|
kPropForceShadow = 0x100, |
|
kDiffuseFoldedIn = 0x200, // Sometimes we want to fold the diffuse color of the material into the vertex color (but only once). |
|
kPropReverseSort = 0x400, |
|
kWaterHeight = 0x800, |
|
kFirstInstance = 0x1000, |
|
kPartialSort = 0x2000, |
|
kVisLOS = 0x4000, |
|
kPropNoShadowCast = 0x8000 |
|
}; |
|
|
|
enum |
|
{ |
|
kNoGroupID = 0 |
|
}; |
|
|
|
// Note: these are public because this is really just a glorified |
|
// struct; no data hiding here |
|
hsGMaterial *fMaterial; |
|
hsMatrix44 fLocalToWorld; |
|
hsMatrix44 fWorldToLocal; |
|
hsBounds3Ext fLocalBounds; |
|
hsBounds3Ext fWorldBounds; |
|
plFogEnvironment *fFogEnviron; |
|
|
|
UInt32 fBaseMatrix; |
|
UInt8 fNumMatrices; |
|
UInt16 fLocalUVWChans; |
|
UInt16 fMaxBoneIdx; |
|
UInt32 fPenBoneIdx; |
|
|
|
hsScalar fMinDist; |
|
hsScalar fMaxDist; |
|
|
|
hsScalar fWaterHeight; |
|
|
|
UInt8 fFormat; |
|
UInt32 fProps; |
|
UInt32 fNumVerts, fNumIndices; |
|
|
|
/// Current vertex format: |
|
/// float position[ 3 ]; |
|
/// float normal[ 3 ]; |
|
/// float uvCoords[ ][ 3 ]; |
|
/// float weights[]; // 0-3 blending weights |
|
/// UInt32 weightIndices; // Only if there are >= 1 blending weights |
|
|
|
UInt8* fVertexData; |
|
UInt16* fIndexData; |
|
UInt32 fDecalLevel; |
|
|
|
hsColorRGBA* fMultColor; |
|
hsColorRGBA* fAddColor; |
|
|
|
UInt32* fDiffuseRGBA; |
|
UInt32* fSpecularRGBA; |
|
|
|
mutable hsTArray<plGeometrySpan *>* fInstanceRefs; |
|
mutable UInt32 fInstanceGroupID; // For writing out/reading in instance refs |
|
|
|
// The following is only used for logging during export. It is never set |
|
// at runtime. Don't even think about using it for anything. |
|
const char* fMaxOwner; |
|
|
|
// The following is ONLY used during pack; it's so we can do a reverse lookup |
|
// from the instanceRefs list to the correct span in the drawable |
|
UInt32 fSpanRefIndex; |
|
|
|
// These two matrices are inverses of each other (duh). They are only used on computing the local |
|
// bounds. fLocalBounds is always the bounds in the space defined by fWorldToLocal, but the bounds |
|
// are an OBB, and the orientation of the OBB isn't necessarily the same as fLocalToWorld's axes. |
|
// For now, it is the orientation of the pivot point in max (but might be further optimized). |
|
hsMatrix44 fLocalToOBB; |
|
hsMatrix44 fOBBToLocal; |
|
|
|
plGeometrySpan(); |
|
plGeometrySpan( const plGeometrySpan *instance ); |
|
~plGeometrySpan(); |
|
|
|
/// UV stuff |
|
UInt8 GetNumUVs( void ) const { return ( fFormat & kUVCountMask ); } |
|
void SetNumUVs( UInt8 numUVs ) |
|
{ |
|
hsAssert( numUVs < kMaxNumUVChannels, "Invalid UV count to plGeometrySpan" ); |
|
fFormat = ( fFormat & ~kUVCountMask ) | numUVs; |
|
} |
|
|
|
static UInt8 CalcNumUVs( UInt8 format ) { return ( format & kUVCountMask ); } |
|
static UInt8 UVCountToFormat( UInt8 numUVs ) { return numUVs & kUVCountMask; } |
|
|
|
/// Creation functions |
|
void BeginCreate( hsGMaterial *material, const hsMatrix44 &l2wMatrix, UInt8 format ); |
|
|
|
// Phasing these in... |
|
// Note: uvArray should be a fixed array with enough pointers for the max # of uv channels. |
|
// Any unused UVs should be nil |
|
UInt16 AddVertex( hsPoint3 *position, hsPoint3 *normal, hsColorRGBA& multColor, hsColorRGBA& addColor, |
|
hsPoint3 **uvPtrArray, float weight1 = -1.0f, float weight2 = -1.0f, float weight3 = -1.0f, UInt32 weightIndices = 0 ); |
|
UInt16 AddVertex( hsPoint3 *position, hsPoint3 *normal, UInt32 hexColor, UInt32 specularColor = 0, |
|
hsPoint3 **uvPtrArray = nil, float weight1 = -1.0f, float weight2 = -1.0f, float weight3 = -1.0f, UInt32 weightIndices = 0 ); |
|
|
|
void AddIndex( UInt16 index ); |
|
void AddTriIndices( UInt16 index1, UInt16 index2, UInt16 index3 ); |
|
void AddTriangle( hsPoint3 *vert1, hsPoint3 *vert2, hsPoint3 *vert3, UInt32 color ); |
|
|
|
// uvws is an array count*uvwsPerVtx long in order [uvw(s) for vtx0, uvw(s) for vtx1, ...], or is nil |
|
void AddVertexArray( UInt32 count, hsPoint3 *positions, hsVector3 *normals, UInt32 *colors, hsPoint3 *uvws=nil, int uvwsPerVtx=0 ); |
|
void AddIndexArray( UInt32 count, UInt16 *indices ); |
|
|
|
void EndCreate( void ); |
|
|
|
|
|
/// Manipulation--currently only used for applying static lighting, which of course needs individual vertices |
|
// Wrong. Also used for the interleaving of the multiple vertex data streams here into single vertex |
|
// stream within the plGBufferGroups. mf. |
|
void ExtractInitColor( UInt32 index, hsColorRGBA *multColor, hsColorRGBA *addColor) const; |
|
void ExtractVertex( UInt32 index, hsPoint3 *pos, hsVector3 *normal, hsColorRGBA *color, hsColorRGBA *specColor = nil ); |
|
void ExtractVertex( UInt32 index, hsPoint3 *pos, hsVector3 *normal, UInt32 *color, UInt32 *specColor = nil ); |
|
void ExtractUv( UInt32 vIdx, UInt8 uvIdx, hsPoint3* uv ); |
|
void ExtractWeights( UInt32 vIdx, float *weightArray, UInt32 *indices ); |
|
void StuffVertex( UInt32 index, hsPoint3 *pos, hsPoint3 *normal, hsColorRGBA *color, hsColorRGBA *specColor = nil ); |
|
void StuffVertex( UInt32 index, hsColorRGBA *color, hsColorRGBA *specColor = nil ); |
|
|
|
// Clear out the buffers |
|
void ClearBuffers( void ); |
|
|
|
// Duplicate this span from a given span |
|
void CopyFrom( const plGeometrySpan *source ); |
|
|
|
// Make this span an instance of the given span. Handles the instance ref array as well as copying over pointers |
|
void MakeInstanceOf( const plGeometrySpan *instance ); |
|
|
|
// Get the size of one vertex in a span, based on a format |
|
static UInt32 GetVertexSize( UInt8 format ); |
|
|
|
void Read( hsStream *stream ); |
|
void Write( hsStream *stream ); |
|
|
|
static UInt32 AllocateNewGroupID() { return IAllocateNewGroupID(); } |
|
|
|
void BreakInstance(); |
|
void ChangeInstance(plGeometrySpan* newInstance); |
|
void UnInstance(); |
|
|
|
void AdjustBounds(hsBounds3Ext& bnd) const; |
|
|
|
protected: |
|
|
|
struct TempVertex |
|
{ |
|
hsPoint3 fPosition; |
|
hsPoint3 fNormal; |
|
UInt32 fColor, fSpecularColor; |
|
hsColorRGBA fMultColor, fAddColor; |
|
hsPoint3 fUVs[ kMaxNumUVChannels ]; |
|
float fWeights[ 3 ]; |
|
UInt32 fIndices; |
|
}; |
|
|
|
hsBool fCreating; |
|
hsTArray<TempVertex> fVertAccum; |
|
hsTArray<UInt16> fIndexAccum; |
|
|
|
void IUnShareData(); |
|
void IDuplicateUniqueData( const plGeometrySpan *source ); |
|
void IClearMembers( void ); |
|
|
|
// Please don't yell at me. We can't write out the instanceRef pointers, and we can't write |
|
// out keys because we're not keyed objects, and we can't be keyed objects because we need |
|
// to be deleted eventually. So instead, we assign each geoSpan a instanceGroupID, unique |
|
// for each instance group but identical among all geoSpans in a given group (i.e. all |
|
// members of the instanceRef list). We write these IDs out, then on read, we rebuild the |
|
// instanceRef arrays by using a hash table to find insert new hsTArrays at the given groupID, |
|
// and looking up in that hash table to get pointers for each geoSpan's instanceRef array. |
|
// THIS is because we need a way of assigning unique, unused groupIDs to each geoSpan instance |
|
// group, and since we only need to know if the ID has been used yet, we can just use a bitVector. |
|
// NOTE: Group IDs start at 1, not 0, because 0 is reserved for "no instance group". So subtract |
|
// 1 from the group ID when accessing this array... |
|
// ....Please don't yell at me :( |
|
static hsBitVector fInstanceGroupIDFlags; |
|
|
|
// The following is for rebuilding the said groups on read. The sad thing is that we also |
|
// have to write out the instanceRef array count for each geoSpan, so that when we read in |
|
// to do the lookup here, we know that we've read everything and can dump the entry in this |
|
// table. |
|
static hsTArray<hsTArray<plGeometrySpan *> *> fInstanceGroups; |
|
|
|
// THIS is so we can clear fInstanceGroups as early and as efficiently as possible; see |
|
// the notes on IGetInstanceGroup(). |
|
static UInt32 fHighestReadInstanceGroup; |
|
|
|
static UInt32 IAllocateNewGroupID( void ); |
|
static void IClearGroupID( UInt32 groupID ); |
|
|
|
static hsTArray<plGeometrySpan *> *IGetInstanceGroup( UInt32 groupID, UInt32 expectedCount ); |
|
}; |
|
|
|
|
|
#endif // _plGeometrySpan_h
|
|
|