1
0
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-20 04:09:16 +00:00

Initial Commit of CyanWorlds.com Engine Open Source Client/Plugin

This commit is contained in:
JWPlatt
2011-03-12 12:34:52 -05:00
commit a20a222fc2
3976 changed files with 1301355 additions and 0 deletions

View File

@ -0,0 +1,135 @@
/*==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 hsFogControl_inc
#define hsFogControl_inc
//#include "hsSceneObject.h"
//#include "hsGEnviron.h"
class hsSceneNode;
class hsG3DDevice;
class hsGView3;
class hsPortal;
class hsFogControl : public plCreatable {
public:
enum {
kFogCtlPortal
};
protected:
plKey fNodeKey;
hsDynamicArray<plKey> fFogNodes;
// hsGEnvironment::FogState fAvgFog;
virtual hsScalar IGetStrength(hsSceneNode* node) = 0;
void IPopNodes();
void IPushNodes();
void IZeroAvgFog();
void IAverageNodes();
// void IAccumFog(hsGEnvironment* env, hsScalar wgt);
public:
hsFogControl() {}
~hsFogControl() {}
CLASSNAME_REGISTER( hsFogControl );
GETINTERFACE_ANY( hsFogControl, plCreatable );
virtual UInt32 GetType() = 0;
// virtual hsGEnvironment* GetHomeEnv() = 0;
virtual void Init(hsSceneNode* node);
virtual void Blend() = 0;
virtual void Restore() = 0;
virtual void Read(hsStream *stream, hsResMgr* mgr) = 0;
virtual void Write(hsStream *stream, hsResMgr* mgr) = 0;
};
#if 0 // Move up to FeatureLevel
class hsNodeFogControl : public hsFogControl {
public:
hsNodeFogControl();
~hsNodeFogControl();
hsSceneNode* GetFogNode(int i);
hsSceneNode *GetHomeNode();
virtual void Init(hsSceneNode* node);
virtual hsGEnvironment* GetHomeEnv();
virtual void Blend();
virtual void Restore();
virtual void Read(hsStream *stream);
virtual void Write(hsStream *stream);
};
class hsPortalFogControl : public hsNodeFogControl {
protected:
enum {
kStatusNone = 0x0,
kStatusNodesSet = 0x1
};
hsDynamicArray<plKey> fPortals;
hsScalar fDefRadius;
UInt32 fStatus;
void IFindFogNodes();
virtual hsScalar IGetStrength(hsSceneNode* node);
public:
hsPortalFogControl();
void SetDefaultRadius(hsScalar r) { fDefRadius = r; }
hsScalar GetDefaultRadius() { return fDefRadius; }
hsPortal* GetPortal(int i);
virtual UInt32 GetType() { return kFogCtlPortal; }
virtual void Init(hsSceneNode* node);
virtual void Blend();
int GetNumPortalKeys() { return fPortals.GetCount(); }
void AddPortalKey(plKey key) { fPortals.Append(key); }
plKey GetPortalKey(int i) { return fPortals[i]; }
virtual void Read(hsStream *stream);
virtual void Write(hsStream *stream);
};
#endif // Move up to FeatureLevel
#endif hsFogControl_inc

View File

@ -0,0 +1,468 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// hsG3DDeviceSelector Class Header //
// Generic device enumeration (D3D, OpenGL, etc) //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 5.21.2001 mcn - Cleaned out all the old Glide stuff, since Plasma2 will //
// not support Glide :( //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef hsG3DDeviceSelector_inc
#define hsG3DDeviceSelector_inc
#include "hsWinRef.h"
#include "hsTemplates.h"
#include "hsBitVector.h"
#ifdef HS_BUILD_FOR_WIN32
#define HS_SELECT_DIRECT3D // not supported on the Mac.
#endif // HS_BUILD_FOR_WIN32
#ifdef HS_BUILD_FOR_WIN32
#define __MSC__
#define DYNAHEADER 1
#endif // HS_BUILD_FOR_WIN32
/// #define the following to allow selection of the D3D reference driver
#define HS_ALLOW_D3D_REF_DRIVER 1
class hsStream;
struct D3DEnum_DeviceInfo;
struct D3DEnum_DriverInfo;
struct D3DEnum_DeviceInfo;
struct D3DEnum_DriverInfo;
class hsG3DDeviceMode
{
enum {
kNone = 0x0,
kDiscarded = 0x1
};
protected:
UInt32 fFlags;
UInt32 fWidth;
UInt32 fHeight;
UInt32 fDepth;
hsTArray<UInt16> fZStencilDepths; // Array of supported depth/stencil buffer formats.
// Each entry is of the form: ( stencil bit count << 8 ) | ( depth bit count )
hsTArray<UInt8> fFSAATypes; // Array of multisample types supported (each one 2-16)
hsBool fCanRenderToCubics;
public:
hsG3DDeviceMode();
~hsG3DDeviceMode();
hsBool operator< (const hsG3DDeviceMode &mode) const;
void Clear();
hsBool GetDiscarded() const { return 0 != (fFlags & kDiscarded); }
UInt32 GetWidth() const { return fWidth; }
UInt32 GetHeight() const { return fHeight; }
UInt32 GetColorDepth() const { return fDepth; }
UInt8 GetNumZStencilDepths( void ) const { return fZStencilDepths.GetCount(); }
UInt16 GetZStencilDepth( UInt8 i ) const { return fZStencilDepths[ i ]; }
UInt8 GetNumFSAATypes( void ) const { return fFSAATypes.GetCount(); }
UInt8 GetFSAAType( UInt8 i ) const { return fFSAATypes[ i ]; }
hsBool GetCanRenderToCubics( void ) const { return fCanRenderToCubics; }
void SetDiscarded(hsBool on=true) { if(on) fFlags |= kDiscarded; else fFlags &= ~kDiscarded; }
void SetWidth(UInt32 w) { fWidth = w; }
void SetHeight(UInt32 h) { fHeight = h; }
void SetColorDepth(UInt32 d) { fDepth = d; }
void ClearZStencilDepths( void ) { fZStencilDepths.Reset(); }
void AddZStencilDepth( UInt16 depth ) { fZStencilDepths.Append( depth ); }
void ClearFSAATypes( void ) { fFSAATypes.Reset(); }
void AddFSAAType( UInt8 type ) { fFSAATypes.Append( type ); }
void SetCanRenderToCubics( hsBool can ) { fCanRenderToCubics = can; }
void Read(hsStream* s);
void Write(hsStream* s) const;
};
class hsG3DDeviceRecord
{
public:
enum {
kNone = 0x0,
kDiscarded = 0x1,
kInvalid = 0x2
};
enum FogTypes {
kFogExp = 0,
kFogExp2,
kNumFogTypes
};
protected:
UInt32 fRecordVersion; /// Version starts at 2 (see .cpp for explanation)
enum {
kCurrRecordVersion = 0x0b
/// Version history:
/// 1 - Initial version (had no version #)
/// 2 - Added Z and LOD bias
/// 3 - Changed Z and LOD bias to floats, added fog tweaks
/// 4 - Changed values for fog tweaks; force reload through version #
/// 5 - Same as #4, updated fog end bias to be based solely on fog quantization/bit depth
/// 6 - Updated values for the ATI boards, Matrox, and i810
/// 7 - Added fog knee tweaks
/// 8 - Added support for multiple depth/stencil formats per mode
/// 9 - Added multisample types to the mode record
/// A - Added anisotropic sample field
/// B - Added flag for cubic textures support
};
/// Version < 2 Data
UInt32 fFlags;
UInt32 fG3DDeviceType;
UInt32 fG3DHALorHEL;
char* fG3DDriverDesc;
char* fG3DDriverName;
char* fG3DDriverVersion;
char* fG3DDeviceDesc;
hsBitVector fCaps;
UInt32 fLayersAtOnce;
UInt32 fMemoryBytes;
hsTArray<hsG3DDeviceMode> fModes;
/// New to Version 3
float fZBiasRating;
float fLODBiasRating;
float fFogExpApproxStart;
float fFogExp2ApproxStart;
float fFogEndBias; // As a percentage of the max value for fog
// (i.e. for Z fog, it's a percentage of 1 to add on,
// for W fog, it's a percentage of the yon)
/// Version 7 - Fog Knee values
float fFogKnees[ kNumFogTypes ];
float fFogKneeVals[ kNumFogTypes ];
/// Version 9 - The actual AA setting we use
UInt8 fAASetting;
/// Version A - the anisotropic level we use
UInt8 fMaxAnisotropicSamples; // 1 to disable, up to max allowed in hardware
int fPixelShaderMajorVer;
int fPixelShaderMinorVer;
public:
hsG3DDeviceRecord();
virtual ~hsG3DDeviceRecord();
hsG3DDeviceRecord(const hsG3DDeviceRecord& src);
hsG3DDeviceRecord& operator=(const hsG3DDeviceRecord& src);
UInt32 GetG3DDeviceType() const { return fG3DDeviceType; }
const char* GetG3DDeviceTypeName() const;
UInt32 GetG3DHALorHEL() const { return fG3DHALorHEL; }
UInt32 GetMemoryBytes() const { return fMemoryBytes; }
const char* GetDriverDesc() const { return fG3DDriverDesc; }
const char* GetDriverName() const { return fG3DDriverName; }
const char* GetDriverVersion() const { return fG3DDriverVersion; }
const char* GetDeviceDesc() const { return fG3DDeviceDesc; }
void SetG3DDeviceType(UInt32 t) { fG3DDeviceType = t; }
void SetG3DHALorHEL(UInt32 h) { fG3DHALorHEL = h; }
void SetMemoryBytes(UInt32 b) { fMemoryBytes = b; }
void SetDriverDesc(const char* s);
void SetDriverName(const char* s);
void SetDriverVersion(const char* s);
void SetDeviceDesc(const char* s);
hsBool GetCap(UInt32 cap) const { return fCaps.IsBitSet(cap); }
void SetCap(UInt32 cap, hsBool on=true) { fCaps.SetBit(cap, on); }
float GetZBiasRating( void ) const { return fZBiasRating; }
void SetZBiasRating( float rating ) { fZBiasRating = rating; }
float GetLODBiasRating( void ) const { return fLODBiasRating; }
void SetLODBiasRating( float rating ) { fLODBiasRating = rating; }
void GetFogApproxStarts( float &expApprox, float &exp2Approx ) const { expApprox = fFogExpApproxStart;
exp2Approx = fFogExp2ApproxStart; }
void SetFogApproxStarts( float exp, float exp2 ) { fFogExpApproxStart = exp;
fFogExp2ApproxStart = exp2; }
float GetFogEndBias( void ) const { return fFogEndBias; }
void SetFogEndBias( float rating ) { fFogEndBias = rating; }
void GetFogKneeParams( UInt8 type, float &knee, float &kneeVal ) const { knee = fFogKnees[ type ]; kneeVal = fFogKneeVals[ type ]; }
void SetFogKneeParams( UInt8 type, float knee, float kneeVal ) { fFogKnees[ type ] = knee; fFogKneeVals[ type ] = kneeVal; }
UInt32 GetLayersAtOnce() const { return fLayersAtOnce; }
void SetLayersAtOnce(UInt32 n) { fLayersAtOnce = n; }
UInt8 GetAASetting() const { return fAASetting; }
void SetAASetting( UInt8 s ) { fAASetting = s; }
UInt8 GetMaxAnisotropicSamples( void ) const { return fMaxAnisotropicSamples; }
void SetMaxAnisotropicSamples( UInt8 num ) { fMaxAnisotropicSamples = num; }
void SetDiscarded(hsBool on=true) { if(on)fFlags |= kDiscarded; else fFlags &= ~kDiscarded; }
hsBool GetDiscarded() const { return 0 != (fFlags & kDiscarded); }
void SetInvalid( hsBool on = true ) { if( on ) fFlags |= kInvalid; else fFlags &= ~kInvalid; }
hsBool IsInvalid() const { return 0 != ( fFlags & kInvalid ); }
hsTArray<hsG3DDeviceMode>& GetModes() { return fModes; }
hsG3DDeviceMode* GetMode(int i) const { return &fModes[i]; }
void ClearModes();
void Clear();
void RemoveDiscarded();
// PlaceHolder - Whether a mode can window is restricted by the current setup
// of the PC. E.g. if the user changes from 16 bit to TrueColor, the Modes that
// can window are pretty much flipped. So we'll have to pass in enough info (like
// the hWnd?) to find out what the current setup is to make sure it's compatible.
hsBool ModeCanWindow(void* ctx, hsG3DDeviceMode* mode) { return false; }
void SetPixelShaderVersion(int major, int minor) { fPixelShaderMajorVer = major; fPixelShaderMinorVer = minor; }
void GetPixelShaderVersion(int &major, int &minor) { major = fPixelShaderMajorVer; minor = fPixelShaderMinorVer; }
void Read(hsStream* s);
void Write(hsStream* s) const;
};
class hsG3DDeviceModeRecord
{
protected:
hsG3DDeviceRecord fDevice;
hsG3DDeviceMode fMode;
public:
hsG3DDeviceModeRecord();
hsG3DDeviceModeRecord(const hsG3DDeviceRecord& devRec, const hsG3DDeviceMode& devMode);
~hsG3DDeviceModeRecord();
hsG3DDeviceModeRecord(const hsG3DDeviceModeRecord& src);
hsG3DDeviceModeRecord& operator=(const hsG3DDeviceModeRecord& src);
const hsG3DDeviceRecord* GetDevice() const { return &fDevice; }
const hsG3DDeviceMode* GetMode() const { return &fMode; }
};
class hsG3DDeviceSelector : public hsRefCnt
{
public:
enum {
kDevTypeUnknown = 0,
kDevTypeGlide,
kDevTypeDirect3D,
kDevTypeOpenGL,
kDevTypeDirect3DTnL,
kNumDevTypes
};
enum {
kHHTypeUnknown = 0,
kHHD3DNullDev,
kHHD3DRampDev,
kHHD3DRGBDev,
kHHD3DHALDev,
kHHD3DMMXDev,
kHHD3DTnLHalDev,
kHHD3DRefDev,
kHHD3D3dfxDev,
kHHD3D3dfxVoodoo5Dev,
kNumHHTypes
};
enum {
kCapsNone = 0,
kCapsNoWindow,
kCapsMipmap,
kCapsPerspective,
kCapsHardware,
kCapsWBuffer,
kCapsCompressTextures,
kCapsHWTransform,
kCapsDither,
kCapsFogLinear,
kCapsFogExp,
kCapsFogExp2,
kCapsFogRange,
kCapsLODWatch,
kCapsUNUSED,
kCapsDoesSmallTextures,
kCapsPixelFog,
kCapsBadYonStuff,
kCapsNoKindaSmallTexs,
kCapsCubicTextures,
kCapsCubicMipmap,
kCapsZBias,
kCapsPixelShader,
kCapsNoAA,
kCapsDoubleFlush,
kCapsSingleFlush,
kCapsCantShadow,
kCapsMaxUVWSrc2,
kCapsCantProj,
kCapsLimitedProj,
kCapsShareDepth,
kCapsBadManaged,
kCapsNoAniso,
// etc.
kNumCaps
};
enum
{
kDefaultWidth = 800,
kDefaultHeight = 600,
kDefaultDepth = 32
};
protected:
hsTArray<hsG3DDeviceRecord> fRecords;
char fTempWinClass[ 128 ];
char fErrorString[ 128 ];
void ITryDirect3DTnLDevice(D3DEnum_DeviceInfo* devInfo, hsG3DDeviceRecord& srcDevRec);
void ITryDirect3DTnLDriver(D3DEnum_DriverInfo* drivInfo);
void ITryDirect3DTnL(hsWinRef winRef);
hsBool IInitDirect3D( void );
#ifdef HS_SELECT_DX7
void ITryDirect3DDevice(D3DEnum_DeviceInfo* devInfo, hsG3DDeviceRecord& srcDevRec);
void ITryDirect3DDriver(D3DEnum_DriverInfo* drivInfo);
void ITryDirect3D(hsWinRef winRef);
#endif // HS_SELECT_DX7
void IFudgeDirectXDevice( hsG3DDeviceRecord &record,
D3DEnum_DriverInfo *driverInfo, D3DEnum_DeviceInfo *deviceInfo );
UInt32 IAdjustDirectXMemory( UInt32 cardMem );
hsBool IGetD3DCardInfo( hsG3DDeviceRecord &record, void *driverInfo, void *deviceInfo,
DWORD *vendorID, DWORD *deviceID, char **driverString, char **descString );
#ifdef HS_SELECT_DX7
hsBool IGetD3D7CardInfo( hsG3DDeviceRecord &record, void *driverInfo, void *deviceInfo,
DWORD *vendorID, DWORD *deviceID, char **driverString, char **descString );
#endif // HS_SELECT_DX7
void ITryOpenGL( hsWinRef winRef );
void IGetExtOpenGLInfo( hsG3DDeviceRecord &devRec );
void IGetOpenGLModes( hsG3DDeviceRecord &devRec, char *driverName );
hsBool ITestOpenGLRes( int width, int height, int bitDepth,
hsG3DDeviceRecord &devRec, char *driverName );
#ifdef HS_OPEN_GL
#if HS_BUILD_FOR_WIN32
UInt32 ICreateTempOpenGLContext( HDC hDC, hsBool makeItFull );
#endif
#endif
void ISetFudgeFactors( UInt8 chipsetID, hsG3DDeviceRecord &record );
public:
hsG3DDeviceSelector();
virtual ~hsG3DDeviceSelector();
void Clear();
void RemoveDiscarded();
void RemoveUnusableDevModes(hsBool bTough); // Removes modes and devices not allowed supported in release
hsBool Init( void ); // Returns false if couldn't init
const char *GetErrorString( void ) { return fErrorString; }
void Enumerate(hsWinRef winRef);
hsTArray<hsG3DDeviceRecord>& GetDeviceRecords() { return fRecords; }
hsBool GetDefault(hsG3DDeviceModeRecord *dmr);
hsG3DDeviceRecord* GetRecord(int i) { return &fRecords[i]; }
void Read(hsStream* s);
void Write(hsStream* s);
};
#define M3DDEMOINFO 1 /// Always compiled now, but only enabled if
/// WIN_INIT has DemoInfoOutput in it
///////////////////////////////////////////////////////////////////////////////
//
// Demo Debug File header file stuff
// Created 10.10.2000 by Mathew Burrack @ Cyan, Inc.
//
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "headspin.h"
class plDemoDebugFile
{
public:
plDemoDebugFile() { fDemoDebugFP = nil; fIsOpen = false; fEnabled = false; }
~plDemoDebugFile() { IDDFClose(); }
// Static function to write a string to the DDF
static void Write( char *string );
// Static function to write two strings to the DDF
static void Write( char *string1, char *string2 );
// Static function to write a string and a signed integer value to the DDF
static void Write( char *string1, Int32 value );
// Enables or disables the DDF class
static void Enable( hsBool yes ) { fEnabled = yes; }
protected:
static hsBool fIsOpen;
static FILE *fDemoDebugFP;
static hsBool fEnabled;
// Opens the DDF for writing
static hsBool IDDFOpen( void );
// Closes the DDF
static void IDDFClose( void );
};
#endif // hsG3DDeviceSelector_inc

View File

@ -0,0 +1,69 @@
/*==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==*/
#include "hsTypes.h"
#include "plPipeline.h"
#include "hsGColorizer.h"
hsBool hsGColorizer::Colorizing()
{
return fPipeline ? 0 != (fPipeline->GetColorOverride().fFlags & hsColorOverride::kModColor) : false;
}
hsBool hsGColorizer::Alpharizing()
{
return fPipeline ? 0 != (fPipeline->GetColorOverride().fFlags & hsColorOverride::kModAlpha) : false;
}
hsColorRGBA hsGColorizer::GetCurrentColor()
{
return fPipeline ? fPipeline->GetColorOverride().fColor : hsColorRGBA().Set(1.f,1.f,1.f,1.f);
}
void hsGColorizer::Init(plPipeline* pipe)
{
fPipeline = pipe;
}
void hsGColorizer::PushColorize(hsColorRGBA& col, hsBool alphaOnly)
{
if( fPipeline )
{
hsColorOverride colorOver;
colorOver.fFlags = alphaOnly ? hsColorOverride::kModAlpha : hsColorOverride::kModColor | hsColorOverride::kModAlpha;
colorOver.fColor = col;
fResetColor = fPipeline->PushColorOverride(colorOver);
}
}
void hsGColorizer::PopColorize()
{
if( fPipeline )
{
fPipeline->PopColorOverride(fResetColor);
}
}

View File

@ -0,0 +1,50 @@
/*==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 hsGColorizer_inc
#define hsGColorizer_inc
#include "hsTypes.h"
#include "hsColorRGBA.h"
class plPipeline;
class hsGColorizer {
protected:
hsColorOverride fResetColor;
plPipeline* fPipeline;
public:
hsGColorizer() : fPipeline(nil) {}
hsBool Colorizing();
hsBool Alpharizing();
hsColorRGBA GetCurrentColor();
void Init(plPipeline* pipe);
void PushColorize(hsColorRGBA& col, hsBool alphaOnly);
void PopColorize();
};
#endif // hsGColorizer_inc

View File

@ -0,0 +1,57 @@
/*==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==*/
#include "hsTypes.h"
#include <ddraw.h>
#include "hsGDDrawDllLoad.h"
static hsGDDrawDllLoad staticDllLoad;
hsGDDrawDllLoad::hsGDDrawDllLoad()
{
hsAssert(!staticDllLoad.fD3DDll, "Don't make instances of this class, just use GetDDrawDll func");
fD3DDll = LoadLibrary( "D3D9.DLL" );
if (fD3DDll)
hsStatusMessage( "--- D3D9.DLL loaded successfully.\n" );
else
hsStatusMessage( "--- Unable to load D3D9.DLL successfully.\n" );
}
hsGDDrawDllLoad::~hsGDDrawDllLoad()
{
if (fD3DDll != nil)
{
hsStatusMessage( "--- Unloading D3D.DLL.\n" );
FreeLibrary(fD3DDll);
}
}
HMODULE hsGDDrawDllLoad::GetD3DDll()
{
return staticDllLoad.fD3DDll;
}

View File

@ -0,0 +1,43 @@
/*==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 hsGDDrawDllLoad_inc
#define hsGDDrawDllLoad_inc
class hsGDDrawDllLoad
{
private:
HMODULE fD3DDll;
public:
hsGDDrawDllLoad();
~hsGDDrawDllLoad();
static HMODULE GetD3DDll();
};
#endif hsGDDrawDllLoad_inc

View File

@ -0,0 +1,61 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// hsGDeviceRef.h - Header for the generic deviceRef class //
// Cyan, Inc. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef hsGDeviceRef_inc
#define hsGDeviceRef_inc
#include "hsRefCnt.h"
class hsGDeviceRef : public hsRefCnt
{
protected:
UInt32 fFlags;
public:
// Note, derived classes define more flags. Take care if adding flags here.
// Currently have flags 0x0 - 0x8 reserved.
enum {
kNone = 0x0,
kDirty = 0x1
};
UInt32 fUseTime; // time stamp when last used - stat gather only
hsBool IsDirty() const { return (fFlags & kDirty); }
void SetDirty(hsBool on) { if(on)fFlags |= kDirty; else fFlags &= ~kDirty; }
hsGDeviceRef() : fFlags(0), fUseTime(0) {}
virtual ~hsGDeviceRef() {}
};
#endif // hsGDeviceRef_inc

View File

@ -0,0 +1,273 @@
/*==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 hsGEnviron_inc
#define hsGEnviron_inc
#include "hsGeometry3.h" // hsPoint3
#include "../plInterp/hsTimedValue.h"
#include "../plResMgr/hsKeyedObject.h"
#include "hsColorRGBA.h"
#include "hsTemplates.h"
//
//-----------------------------------
// Environment
//-----------------------------------
//
class hsGMaterial;
class hsGDevEnvCache;
class hsFogControl;
class hsSceneNode;
class hsScene;
class hsGRenderProcs;
class hsG3DDevice;
class plKey;
class hsResMgr;
class hsGEnvironment : public hsKeyedObject {
private:
static const UInt16 kSaveMagicNumber;
static const UInt16 kSaveVersion;
public:
struct FogState {
private:
static const UInt16 kSaveMagicNumber;
static const UInt16 kSaveVersion;
public:
FogState() : fFlags(0) {};
enum {
kColorSet = 0x1,
kDistanceSet = 0x2,
kDepthSet = 0x4,
kDensitySet = 0x8,
kYonSet = 0x10,
kClearSet = 0x20,
kLinear = 0x10000000,
kExp = 0x20000000,
kExp2 = 0x40000000,
kTypeMask = kLinear | kExp | kExp2
};
UInt32 fFlags;
hsTimedValue<hsColorRGBA> fColor;
hsTimedValue<hsColorRGBA> fClear;
hsTimedValue<hsScalar> fDistance;
hsTimedValue<hsScalar> fDensity;
hsTimedValue<hsScalar> fDepth;
hsTimedValue<hsScalar> fYon;
void ValidateEnv(class hsGEnvironment* env);
void SetFromEnv(class hsGEnvironment* env);
void SetToEnv(class hsGEnvironment* env);
void Save(hsStream *stream, hsResMgr* mgr);
void Load(hsStream *stream, hsResMgr* mgr);
};
enum {
kMapSet = 0x1,
kCenterSet = 0x2,
kRadiusSet = 0x4,
kEnvironMapSet = kMapSet | kCenterSet | kRadiusSet,
kFogDepthSet = 0x8,
kFogColorSet = 0x10,
kFogDensitySet = 0x20,
kYonSet = 0x40,
kOverride = 0x80,
kFarOut = 0x100,
kFogDistanceSet = 0x200,
kCacheInvalid = 0x400,
kClearColorSet = 0x800,
kCurrentDepthSet = 0x1000,
kFogControl = 0x2000,
kSortObjects = 0x4000,
kHasRenderProcs = 0x8000,
kFogLinear = 0x10000,
kFogExp = 0x20000,
kFogExp2 = 0x40000,
kFogTypeMask = kFogLinear | kFogExp | kFogExp2,
kClearColorAmbient = 0x80000,
kFogColorAmbient = 0x100000,
kFogColorDiffuse = 0x200000
};
protected:
static hsScalar fYonScale;
UInt32 fFlags;
hsGMaterial* fMap;
char fMapName[256];
hsPoint3 fPos;
hsScalar fRadius;
hsScalar fValidScale;
hsTArray<FogState*> fFogStateStack;
hsTimedValue<hsScalar> fFogDistance;
hsTimedValue<hsScalar> fFogDepth; // value 0..1, as fraction of yon, 0 is no fog
hsTimedValue<hsScalar> fFogDensity;
hsTimedValue<hsColorRGBA> fFogColor;
hsTimedValue<hsColorRGBA> fClearColor;
hsTimedValue<hsScalar> fYon;
hsScalar fCurrentDepth; // function of Depth and Distance
FogState fResetState;
hsGDevEnvCache* fDevCache;
hsDynamicArray<hsGRenderProcs*> fRenderProcs;
hsTArray<plKey*> fNodeKeys;
hsFogControl* fFogControl;
void IReadFogControl(hsStream* s, hsResMgr* mgr);
void IWriteFogControl(hsStream* s, hsResMgr* mgr);
public:
hsGEnvironment();
virtual ~hsGEnvironment();
hsBool32 AddNode(hsSceneNode *node);
hsBool32 AddNodeKey(plKey *key);
Int32 GetNumNodes() { return fNodeKeys.GetCount(); }
hsSceneNode* GetNode(Int32 i);
plKey* GetNodeKey(Int32 i) { return fNodeKeys[i]; }
char* GetMapName() { return fMapName; }
hsGMaterial* GetMap() const { return fMap; }
hsPoint3 GetCenter() const { return fPos; }
hsScalar GetRadius() const { return fRadius; }
hsScalar GetFogDistance() const { return fFogDistance.GetValue(); }
hsScalar GetFogDepth() const { return fFogDepth.GetValue(); }
hsScalar GetCurrentDepth() const { return fCurrentDepth; }
hsScalar GetFogDensity() const { return fFogDensity.GetValue(); }
hsColorRGBA GetFogColor() const { return fFogColor.GetValue(); }
hsColorRGBA GetClearColor() const { return fClearColor.GetValue(); }
hsScalar GetYon() const { return fYonScale * fYon.GetValue(); }
hsScalar GetUnscaledYon() const { return fYon.GetValue(); }
hsBool32 GetOverride() const { return 0 != (fFlags & kOverride); }
UInt32 GetFlags() const { return fFlags; }
hsScalar GoalFogDistance() const { return fFogDistance.GetGoal(); }
hsScalar GoalFogDepth() const { return fFogDepth.GetGoal(); }
hsScalar GoalFogDensity() const { return fFogDensity.GetGoal(); }
hsColorRGBA GoalFogColor() const { return fFogColor.GetGoal(); }
hsColorRGBA GoalClearColor() const { return fClearColor.GetGoal(); }
hsScalar GoalYon() const { return fYon.GetGoal(); }
const hsTimedValue<hsScalar>& FogDistanceState() const { return fFogDistance; }
const hsTimedValue<hsScalar>& FogDepthState() const { return fFogDepth; }
const hsTimedValue<hsScalar>& FogDensityState() const { return fFogDensity; }
const hsTimedValue<hsColorRGBA>& FogColorState() const { return fFogColor; }
const hsTimedValue<hsColorRGBA>& ClearColorState() const { return fClearColor; }
const hsTimedValue<hsScalar>& YonState() const { return fYon; }
void SetFogDistance(const hsTimedValue<hsScalar>& v);
void SetFogDepth(const hsTimedValue<hsScalar>& v);
void SetFogDensity(const hsTimedValue<hsScalar>& v);
void SetFogColor(const hsTimedValue<hsColorRGBA>& v);
void SetClearColor(const hsTimedValue<hsColorRGBA>& v);
void SetYon(const hsTimedValue<hsScalar>& v);
void SetMapName(const char *name);
void SetMap(hsGMaterial *m); // refs
void SetCenter(const hsPoint3 &p);
void SetRadius(hsScalar r);
void SetFogDistance(hsScalar d);
void SetFogDepth(hsScalar f);
void SetCurrentDepth(hsScalar f);
void SetFogDensity(hsScalar f);
void SetFogColor(const hsColorRGBA &c);
void SetClearColor(const hsColorRGBA &c);
void SetYon(hsScalar f);
void SetOverride(hsBool32 on);
void SetIsFar(hsBool32 on=true);
void SetHasFogControl(hsBool32 on=true);
void SetSortObjects(hsBool32 on=true);
void SetFogType(UInt32 t);
void SetFogColorAmbient(hsBool32 on=true);
void SetFogColorDiffuse(hsBool32 on=true);
void SetClearColorAmbient(hsBool32 on=true);
void SetTimedFogDistance(const hsScalar g, const hsScalar s);
void SetTimedFogDepth(const hsScalar g, const hsScalar s);
void SetTimedFogDensity(const hsScalar g, const hsScalar s);
void SetTimedFogColor(const hsColorRGBA& g, const hsScalar s);
void SetTimedClearColor(const hsColorRGBA& g, const hsScalar s);
void SetTimedYon(const hsScalar g, const hsScalar s);
void UnSetMapName() { *fMapName = 0; }
void UnSetEnvironMap() { fFlags &= ~kEnvironMapSet; }
void UnSetFogDistance() { fFlags &= ~kFogDistanceSet; }
void UnSetFogDepth() { fFlags &= ~kFogDepthSet; }
void UnSetFogDensity() { fFlags &= ~kFogDensitySet; }
void UnSetFogColor() { fFlags &= ~kFogColorSet; }
void UnSetClearColor() { fFlags &= ~kClearColorSet; }
void UnSetYon() { fFlags &= ~kYonSet; }
hsGEnvironment* Copy(hsGEnvironment* env); // returns this
void MixEnvirons(hsGEnvironment* env, hsGEnvironment* def);
void Push(hsG3DDevice* d);
void Pop(hsG3DDevice* d);
void Blend();
void Restore();
void Init(hsSceneNode* node);
void SetDeviceCache(hsGDevEnvCache* p);
hsGDevEnvCache* GetDeviceCache(){ return fDevCache; }
void SetFogControl(hsFogControl* fc);
hsFogControl* GetFogControl() { return fFogControl; }
void SaveFogState(); // push
hsGEnvironment::FogState* PopFogState() { return fFogStateStack.GetCount() ? fFogStateStack.Pop() : nil; } // doesn't restore
void RestoreFogState(); // pop and restore
void AddRenderProc(hsGRenderProcs* rp); // refs
hsGRenderProcs* GetRenderProc(int i); // no ref
UInt32 GetNumRenderProcs();
virtual void SetResetState();
virtual void Reset();
virtual void ValidateInResetState();
virtual void Save(hsStream *stream, hsResMgr* mgr);
virtual void Load(hsStream *stream, hsResMgr* mgr);
virtual void Update(hsScalar secs, const hsPoint3& vPos);
virtual void Read(hsStream* s);
virtual void Write(hsStream* s);
virtual void Write(hsStream *stream, hsResMgr *group);
virtual void Read(hsStream *stream, hsResMgr *group);
static hsScalar GetYonScale() { return fYonScale; }
static hsScalar SetYonScale(hsScalar s);
virtual hsBool MsgReceive(plMessage* msg);
};
#endif // hsGEnviron_inc

View File

@ -0,0 +1,46 @@
/*==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 hsWinRef_inc
#define hsWinRef_inc
#ifdef HS_BUILD_FOR_WIN32
#include "hsWindows.h"
typedef HWND hsWinRef;
#elif HS_BUILD_FOR_MACPPC
typedef WindowRef hsWinRef;
#else // Whatever
typedef void* hsWinRef;
#endif
#endif // hsWinRef_inc

View File

@ -0,0 +1,219 @@
/*==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==*/
#include "hsTypes.h"
#include "plCaptureRender.h"
#ifndef MF_FRONTBUFF_CAPTURE
#include "../plGImage/plMipmap.h"
#include "../plMessage/plCaptureRenderMsg.h"
#include "plPipeline.h"
#include "plRenderTarget.h"
#include "../plScene/plPageTreeMgr.h"
#include "../plScene/plPostEffectMod.h"
#include "hsResMgr.h"
#include "../pnKeyedObject/plUoid.h"
#include "../pfGameGUIMgr/pfGameGUIMgr.h"
// CaptureRenderRequest
//
void plCaptureRenderRequest::Render(plPipeline* pipe, plPageTreeMgr* pageMgr)
{
// If we don't have a render target, something has gone horribly wrong.
if( !GetRenderTarget() )
{
hsAssert(false, "CaptureRenderRequest with no render target");
return;
}
// Set ourselves up like the current pipeline, except with our screen size.
plViewTransform vt = pipe->GetViewTransform();
vt.SetViewPort(0, 0, fRenderTarget->GetWidth(), fRenderTarget->GetHeight());
SetViewTransform(vt);
SetClearColor(pipe->GetClearColor());
SetClearDepth(pipe->GetClearDepth());
// Clear our render target
// Render the scene
pipe->PushRenderRequest(this);
pipe->ClearRenderTarget();
pageMgr->Render(pipe);
pipe->PopRenderRequest(this);
// set up state so we can clear the z-buffer for every gui dialog (and therefore not have it
// be obscured by other geometry)
SetRenderState(GetRenderState() & ~plPipeline::kRenderClearColor);
SetRenderState(GetRenderState() | plPipeline::kRenderClearDepth);
SetClearDepth(1);
// render all GUI items
std::vector<plPostEffectMod*> guiRenderMods = pfGameGUIMgr::GetInstance()->GetDlgRenderMods();
for (int i = (int)guiRenderMods.size() - 1; i >= 0; i--) // render in reverse, so dialogs on the bottom get rendered first
{
plPageTreeMgr* dlgPageMgr = guiRenderMods[i]->GetPageMgr();
if (dlgPageMgr)
{
SetViewTransform(guiRenderMods[i]->GetViewTransform());
pipe->PushRenderRequest(this);
pipe->ClearRenderTarget();
dlgPageMgr->Render(pipe);
pipe->PopRenderRequest(this);
}
}
// Callback on plCaptureRender to process the render target into a mipmap
// and send it back to the requester.
plCaptureRender::IProcess(pipe, GetAck(), GetRenderTarget());
delete fRenderTarget;
fRenderTarget = nil;
}
hsTArray<plCaptureRenderMsg*> plCaptureRender::fProcessed;
// plCaptureRender::Capture
hsBool plCaptureRender::Capture(const plKey& ack, UInt16 width, UInt16 height)
{
// Create our render target
const UInt16 flags = plRenderTarget::kIsOffscreen;
const UInt8 bitDepth(32);
const UInt8 zDepth(-1);
const UInt8 stencilDepth(-1);
plRenderTarget* rt = TRACKED_NEW plRenderTarget(flags, width, height, bitDepth, zDepth, stencilDepth);
static int idx=0;
char buff[32];
sprintf(buff, "tRT%d", idx++);
hsgResMgr::ResMgr()->NewKey(buff, rt, ack->GetUoid().GetLocation());
// Create a render request and render request message
plCaptureRenderRequest* req = TRACKED_NEW plCaptureRenderRequest;
const hsScalar pri(-100.f);
req->SetPriority(pri);
req->SetRenderTarget(rt);
const UInt32 renderState
= plPipeline::kRenderNormal
| plPipeline::kRenderClearColor
| plPipeline::kRenderClearDepth;
req->SetRenderState(renderState);
// Set the Ack to be our requestor
req->RequestAck(ack);
// Submit
plRenderRequestMsg* msg = TRACKED_NEW plRenderRequestMsg(ack, req);
hsRefCnt_SafeUnRef(req);
msg->Send();
return true;
}
// plCaptureRender::IProcess
hsBool plCaptureRender::IProcess(plPipeline* pipe, const plKey& ack, plRenderTarget* targ)
{
// We've just had a successful render into our render target
// Copy that into a plMipmap
plMipmap* mipMap = pipe->ExtractMipMap(targ);
if( !mipMap )
return false;
static int currentCapIndex = 0;
// Mipmap isn't created with a key so let's give it one now
char buff[512];
sprintf(buff, "CaptureRender_%d", currentCapIndex++);
hsgResMgr::ResMgr()->NewKey(buff, mipMap, plLocation::kGlobalFixedLoc);
mipMap->Ref();
// Stash it, and send it off during the update phase.
plCaptureRenderMsg* msg = TRACKED_NEW plCaptureRenderMsg(ack, mipMap);
fProcessed.Append(msg);
return true;
}
void plCaptureRender::Update()
{
int i;
for( i = 0; i < fProcessed.GetCount(); i++ )
{
fProcessed[i]->Send();
}
fProcessed.SetCount(0);
}
#else // MF_FRONTBUFF_CAPTURE
#include "plPipeline.h"
#include "plgDispatch.h"
#include "../plMessage/plCaptureRenderMsg.h"
#include "../plGImage/plMipmap.h"
hsTArray<plCaptureRender::CapInfo> plCaptureRender::fCapReqs;
void plCaptureRender::Update(plPipeline* pipe)
{
int i;
for( i = 0; i < fCapReqs.GetCount(); i++ )
{
plMipmap* mipmap = TRACKED_NEW plMipmap(fCapReqs[i].fWidth, fCapReqs[i].fHeight, plMipmap::kARGB32Config, 1);
pipe->CaptureScreen(mipmap, false, fCapReqs[i].fWidth, fCapReqs[i].fHeight);
plCaptureRenderMsg* msg = TRACKED_NEW plCaptureRenderMsg(fCapReqs[i].fAck, mipmap);
msg->Send();
}
fCapReqs.Reset();
}
hsBool plCaptureRender::Capture(const plKey& ack, UInt16 width, UInt16 height)
{
CapInfo capInfo;
capInfo.fAck = ack;
capInfo.fWidth = width;
capInfo.fHeight = height;
fCapReqs.Append(capInfo);
return true;
}
#endif // MF_FRONTBUFF_CAPTURE

View File

@ -0,0 +1,93 @@
/*==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 plCaptureRender_inc
#define plCaptureRender_inc
#ifndef MF_FRONTBUFF_CAPTURE
#include "../plScene/plRenderRequest.h"
class plRenderTarget;
class plCaptureRenderMsg;
class plCaptureRenderRequest : public plRenderRequest
{
public:
virtual void Render(plPipeline* pipe, plPageTreeMgr* pageMgr);
};
class plCaptureRender
{
protected:
static hsTArray<plCaptureRenderMsg*> fProcessed;
static hsBool IProcess(plPipeline* pipe, const plKey& ack, plRenderTarget* targ);
friend class plCaptureRenderRequest;
// Only the client calls this (during the update phase).
static void Update();
friend class plClient;
public:
static hsBool Capture(const plKey& ack, UInt16 width=800, UInt16 height=600);
};
#else // MF_FRONTBUFF_CAPTURE
#include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h"
class plPipeline;
class plCaptureRender
{
protected:
class CapInfo
{
public:
plKey fAck;
UInt16 fWidth;
UInt16 fHeight;
};
static hsTArray<CapInfo> fCapReqs;
// Only the client calls this (during the update phase).
static void Update(plPipeline* pipe);
friend class plClient;
public:
static hsBool Capture(const plKey& ack, UInt16 width=800, UInt16 height=600);
};
#endif // MF_FRONTBUFF_CAPTURE
#endif // plCaptureRender_inc

View File

@ -0,0 +1,121 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plCubicRenderTarget Class Header //
// Derived renderTarget class representing a collection of render targets //
// to be used for DYNAMIC cubic environment mapping. //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 6.7.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plCubicRenderTarget_h
#define _plCubicRenderTarget_h
#include "plRenderTarget.h"
#include "hsMatrix44.h"
//// Class Definition /////////////////////////////////////////////////////////
class plCubicRenderTarget : public plRenderTarget
{
protected:
//// Protected Members ////
plRenderTarget *fFaces[6];
hsMatrix44 fWorldToCameras[6];
hsMatrix44 fCameraToWorlds[6];
public:
//// Public Data ////
enum Faces
{
kLeftFace = 0,
kRightFace,
kFrontFace,
kBackFace,
kTopFace,
kBottomFace
};
//// Public Members ////
CLASSNAME_REGISTER( plCubicRenderTarget );
GETINTERFACE_ANY( plCubicRenderTarget, plRenderTarget );
plCubicRenderTarget()
{
fFaces[0] = fFaces[1] = fFaces[2] = fFaces[3] = fFaces[4] = fFaces[5] = nil;
}
plCubicRenderTarget( UInt16 flags, UInt16 width, UInt16 height, UInt8 bitDepth, UInt8 zDepth = -1, UInt8 sDepth = -1 )
: plRenderTarget( flags, width, height, bitDepth, zDepth, sDepth )
{
int i;
for( i = 0; i < 6; i++ )
{
fFaces[i] = TRACKED_NEW plRenderTarget( flags, width, height, bitDepth, zDepth, sDepth );
fFaces[i]->fParent = this;
fWorldToCameras[i].Reset();
fCameraToWorlds[i].Reset();
}
}
virtual ~plCubicRenderTarget()
{
int i;
for( i = 0; i < 6; i++ )
delete fFaces[i];
}
// Get the total size in bytes
virtual UInt32 GetTotalSize( void ) const;
virtual void SetCameraMatrix(const hsPoint3& pos);
virtual const hsMatrix44& GetWorldToCamera(UInt8 face) const { return fWorldToCameras[face]; }
virtual const hsMatrix44& GetCameraToWorld(UInt8 face) const { return fCameraToWorlds[face]; }
plRenderTarget *GetFace(UInt8 face) const { return fFaces[face]; }
virtual UInt32 Read(hsStream *s);
virtual UInt32 Write(hsStream *s);
};
#endif // _plCubicRenderTarget_h

View File

@ -0,0 +1,243 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plCubicRenderTargetModifier Class Functions //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 7.20.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plCubicRenderTargetModifier.h"
#include "plCubicRenderTarget.h"
#include "plgDispatch.h"
#include "plPipeline.h"
#include "plDrawable.h"
#include "hsBounds.h"
#include "../plScene/plRenderRequest.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../pnSceneObject/plCoordinateInterface.h"
#include "../pnSceneObject/plDrawInterface.h"
#include "../pnMessage/plTimeMsg.h"
#include "../plMessage/plRenderRequestMsg.h"
#include "hsResMgr.h"
#include "hsTimer.h"
//// Constructor & Destructor /////////////////////////////////////////////////
plCubicRenderTargetModifier::plCubicRenderTargetModifier()
{
fTarget = nil;
fCubic = nil;
fRequests[ 0 ] = fRequests[ 1 ] = fRequests[ 2 ] = fRequests[ 3 ] = fRequests[ 4 ] = fRequests[ 5 ] = nil;
}
plCubicRenderTargetModifier::~plCubicRenderTargetModifier()
{
int i;
for( i = 0; i < 6; i++ )
delete fRequests[ i ];
}
//// ICreateRenderRequest /////////////////////////////////////////////////////
// Creates a blank renderRequest to use for fun stuff.
void plCubicRenderTargetModifier::ICreateRenderRequest( int face )
{
plRenderRequest *rr = fRequests[ face ];
hsColorRGBA c;
if( rr == nil )
rr = fRequests[ face ] = TRACKED_NEW plRenderRequest;
UInt32 renderState
= plPipeline::kRenderNormal
| plPipeline::kRenderClearColor
| plPipeline::kRenderClearDepth;
rr->SetRenderState( renderState );
rr->SetDrawableMask( plDrawable::kNormal );
rr->SetSubDrawableMask( plDrawable::kSubAllTypes );
rr->SetHither(0.3f); // MF_HORSE ????
rr->SetYon(1000.f); // MF_HORSE ????
rr->SetFovX( 90 );
rr->SetFovY( 90 );
c.Set( 0, 0, 0, 1 );
rr->SetClearColor( c );
rr->SetClearDepth( 1.f );
rr->SetClearDrawable( nil );
rr->SetRenderTarget( fCubic->GetFace( face ) );
}
//// IEval ////////////////////////////////////////////////////////////////////
hsBool plCubicRenderTargetModifier::IEval( double secs, hsScalar del, UInt32 dirty )
{
hsPoint3 center;
hsMatrix44 mtx, invMtx;
int i;
plRenderRequestMsg *msg;
if( fCubic == nil || fTarget == nil )
return true;
/// Get center point for RT
plCoordinateInterface *ci = IGetTargetCoordinateInterface( 0 );
if( ci == nil )
{
plDrawInterface *di = IGetTargetDrawInterface( 0 );
center = di->GetWorldBounds().GetCenter();
}
else
center = ci->GetLocalToWorld().GetTranslate();
/// Set camera position of RT to this center
fCubic->SetCameraMatrix(center);
/// Submit render requests!
for( i = 0; i < 6; i++ )
{
if( fRequests[ i ] != nil )
{
fRequests[ i ]->SetCameraTransform(fCubic->GetWorldToCamera(i), fCubic->GetCameraToWorld(i));
msg = TRACKED_NEW plRenderRequestMsg( nil, fRequests[ i ] );
plgDispatch::MsgSend( msg );
}
}
/// Done!
return true;
}
//// MsgReceive ///////////////////////////////////////////////////////////////
hsBool plCubicRenderTargetModifier::MsgReceive( plMessage* msg )
{
plSceneObject *scene;
plCubicRenderTarget *cubic;
int i;
plEvalMsg* eval = plEvalMsg::ConvertNoRef(msg);
if( eval )
{
const double secs = eval->DSeconds();
const hsScalar del = eval->DelSeconds();
IEval( secs, del, 0 );
return true;
}
plRefMsg *refMsg = plRefMsg::ConvertNoRef( msg );
if( refMsg )
{
if( scene = plSceneObject::ConvertNoRef( refMsg->GetRef() ) )
{
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
AddTarget( scene );
else
RemoveTarget( scene );
}
if( cubic = plCubicRenderTarget::ConvertNoRef( refMsg->GetRef() ) )
{
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
{
fCubic = cubic;
for( i = 0; i < 6; i++ )
ICreateRenderRequest( i );
}
else
{
fCubic = nil;
for( i = 0; i < 6; i++ )
{
delete fRequests[ i ];
fRequests[ i ] = nil;
}
}
}
return true;
}
return plModifier::MsgReceive( msg );
}
//// AddTarget ////////////////////////////////////////////////////////////////
void plCubicRenderTargetModifier::AddTarget( plSceneObject *so )
{
if( fTarget != nil )
RemoveTarget( fTarget );
fTarget = so;
plgDispatch::Dispatch()->RegisterForExactType( plEvalMsg::Index(), GetKey() );
}
//// RemoveTarget /////////////////////////////////////////////////////////////
void plCubicRenderTargetModifier::RemoveTarget( plSceneObject *so )
{
fTarget = nil;
}
//// Read /////////////////////////////////////////////////////////////////////
void plCubicRenderTargetModifier::Read( hsStream *s, hsResMgr *mgr )
{
hsKeyedObject::Read( s, mgr );
plGenRefMsg* msg;
msg = TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, 0, 0 ); // SceneObject
mgr->ReadKeyNotifyMe( s, msg, plRefFlags::kActiveRef );
msg = TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, 0, 0 ); // cubicRT
mgr->ReadKeyNotifyMe( s, msg, plRefFlags::kActiveRef );
}
//// Write ////////////////////////////////////////////////////////////////////
void plCubicRenderTargetModifier::Write( hsStream *s, hsResMgr *mgr )
{
hsKeyedObject::Write(s, mgr);
mgr->WriteKey( s, fTarget ); // Write the SceneNode
mgr->WriteKey( s, fCubic ); // Write the cubicRT
}

View File

@ -0,0 +1,87 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plCubicRenderTargetModifier Class Header //
// Modifier applied to an object to specify the source object to render a //
// cubicRenderTarget from. Owns a key to the cubicRenderTarget in question, //
// which it updates with positions and submits renderRequests for. //
// //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 7.20.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plCubicRenderTargetModifier_h
#define _plCubicRenderTargetModifier_h
#include "../../NucleusLib/pnModifier/plModifier.h"
#include "../pnNetCommon/plSynchedValue.h"
class plCubicRenderTarget;
class plRenderRequest;
//// Class Definition /////////////////////////////////////////////////////////
class plCubicRenderTargetModifier : public plModifier
{
public:
plCubicRenderTargetModifier();
virtual ~plCubicRenderTargetModifier();
CLASSNAME_REGISTER( plCubicRenderTargetModifier );
GETINTERFACE_ANY( plCubicRenderTargetModifier, plModifier);
// Functions related to/required by plModifier
virtual int GetNumTargets( void ) const { return fTarget ? 1 : 0; }
virtual plSceneObject *GetTarget( int w ) const { hsAssert(w < GetNumTargets(), "Bad target"); return fTarget; }
virtual void AddTarget( plSceneObject* so );
virtual void RemoveTarget( plSceneObject* so );
virtual void Read( hsStream* s, hsResMgr* mgr );
virtual void Write( hsStream* s, hsResMgr* mgr );
virtual hsBool MsgReceive( plMessage* msg );
protected:
plSceneObject *fTarget;
plCubicRenderTarget *fCubic;
plRenderRequest *fRequests[ 6 ];
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // required by plModifier
void ICreateRenderRequest( int face );
};
#endif //_plCubicRenderTargetModifier_h

View File

@ -0,0 +1,207 @@
/*==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 plCullTree_inc
#define plCullTree_inc
#include "hsBounds.h"
#include "hsGeometry3.h"
#include "hsBitVector.h"
#include "plCuller.h"
#include "../plScene/plCullPoly.h"
#ifdef HS_DEBUGGING
#define DEBUG_POINTERS
#endif // HS_DEBUGGING
class plCullTree;
class plCullNode;
// for vis
struct hsPoint3;
struct hsVector3;
struct hsColorRGBA;
class plCullTree : public plCuller
{
protected:
// Visualization stuff, to be nuked from production version.
mutable hsBool fCapturePolys;
mutable hsTArray<hsPoint3> fVisVerts;
mutable hsTArray<hsVector3> fVisNorms;
mutable hsTArray<hsColorRGBA> fVisColors;
mutable hsTArray<UInt16> fVisTris;
mutable hsScalar fVisYon;
mutable hsTArray<plCullPoly> fScratchPolys;
mutable hsLargeArray<Int16> fScratchClear;
mutable hsLargeArray<Int16> fScratchSplit;
mutable hsLargeArray<Int16> fScratchCulled;
mutable hsBitVector fScratchBitVec;
mutable hsBitVector fScratchTotVec;
void IVisPolyShape(const plCullPoly& poly, hsBool dark) const;
void IVisPolyEdge(const hsPoint3& p0, const hsPoint3& p1, hsBool dark) const;
void IVisPoly(const plCullPoly& poly, hsBool dark) const;
hsPoint3 fViewPos;
Int16 fRoot;
mutable hsTArray<plCullNode> fNodeList; // Scratch list we make the tree from.
plCullNode* IGetRoot() const { return IGetNode(fRoot); }
plCullNode* IGetNode(Int16 i) const { return i >= 0 ? &fNodeList[i] : nil; }
void ITestNode(const plSpaceTree* space, Int16 who, hsTArray<Int16>& outList) const; // Appends to outlist
void ITestList(const plSpaceTree* space, const hsTArray<Int16>& inList, hsTArray<Int16>& outList) const;
Int16 IAddPolyRecur(const plCullPoly& poly, Int16 iNode);
Int16 IMakeHoleSubTree(const plCullPoly& poly) const;
Int16 IMakePolySubTree(const plCullPoly& poly) const;
Int16 IMakePolyNode(const plCullPoly& poly, int i0, int i1) const;
// Some scratch areas for the nodes use when building the tree etc.
hsTArray<plCullPoly>& ScratchPolys() const { return fScratchPolys; }
hsLargeArray<Int16>& ScratchClear() const { return fScratchClear; }
hsLargeArray<Int16>& ScratchSplit() const { return fScratchSplit; }
hsLargeArray<Int16>& ScratchCulled() const { return fScratchCulled; }
hsBitVector& ScratchBitVec() const { return fScratchBitVec; }
hsBitVector& ScratchTotVec() const { return fScratchTotVec; }
void ISetupScratch(UInt16 nNodes);
friend class plCullNode;
public:
plCullTree();
~plCullTree();
void Reset(); // Called before starting to add polys for this frame.
void InitFrustum(const hsMatrix44& world2NDC);
void SetViewPos(const hsPoint3& pos);
void AddPoly(const plCullPoly& poly);
UInt32 GetNumNodes() const { return fNodeList.GetCount(); }
virtual void Harvest(const plSpaceTree* space, hsTArray<Int16>& outList) const;
virtual hsBool BoundsVisible(const hsBounds3Ext& bnd) const;
virtual hsBool SphereVisible(const hsPoint3& center, hsScalar rad) const;
// Visualization stuff. Only to be called by the pipeline (or some other vis manager).
void SetVisualizationYon(hsScalar y) const { fVisYon = y; }
void BeginCapturePolys() const { fCapturePolys = true; }
void EndCapturePolys() const { fCapturePolys = false; }
hsTArray<hsPoint3>& GetCaptureVerts() const { return fVisVerts; }
hsTArray<hsVector3>& GetCaptureNorms() const { return fVisNorms; }
hsTArray<hsColorRGBA>& GetCaptureColors() const { return fVisColors; }
hsTArray<UInt16>& GetCaptureTris() const { return fVisTris; }
void ReleaseCapture() const;
};
class plCullNode
{
public:
enum plCullStatus
{
kClear,
kCulled,
kSplit,
kPureSplit
};
protected:
hsVector3 fNorm;
hsScalar fDist;
hsBool fIsFace;
Int16 fInnerChild;
Int16 fOuterChild;
const plCullTree* fTree;
plCullNode* IGetNode(Int16 i) const;
#ifdef DEBUG_POINTERS
mutable plCullNode* fInnerPtr;
mutable plCullNode* fOuterPtr;
void ISetPointersRecur() const;
#else // DEBUG_POINTERS
void ISetPointersRecur() const {}
#endif // DEBUG_POINTERS
// Bounds only version
plCullNode::plCullStatus ITestBoundsRecur(const hsBounds3Ext& bnd) const;
plCullNode::plCullStatus ITestSphereRecur(const hsPoint3& center, hsScalar rad) const;
// Using the nodes
plCullNode::plCullStatus ITestNode(const plSpaceTree* space, Int16 who, hsLargeArray<Int16>& clear, hsLargeArray<Int16>& split, hsLargeArray<Int16>& culled) const;
void ITestNode(const plSpaceTree* space, Int16 who, hsBitVector& totList, hsBitVector& outList) const;
void IHarvest(const plSpaceTree* space, hsTArray<Int16>& outList) const;
// Constructing the tree
hsScalar IInterpVert(const hsPoint3& p0, const hsPoint3& p1, hsPoint3& out) const;
plCullNode::plCullStatus ISplitPoly(const plCullPoly& poly, plCullPoly*& innerPoly, plCullPoly*& outerPoly) const;
void IMarkClipped(const plCullPoly& poly, const hsBitVector& onVerts) const;
void ITakeHalfPoly(const plCullPoly& scrPoly,
const hsTArray<int>& vtxIdx,
const hsBitVector& onVerts,
plCullPoly& outPoly) const;
void IBreakPoly(const plCullPoly& poly, const hsTArray<hsScalar>& depths,
hsBitVector& inVerts,
hsBitVector& outVerts,
hsBitVector& onVerts,
plCullPoly& srcPoly) const;
hsTArray<plCullPoly>& ScratchPolys() const { return fTree->ScratchPolys(); }
hsLargeArray<Int16>& ScratchClear() const { return fTree->ScratchClear(); }
hsLargeArray<Int16>& ScratchSplit() const { return fTree->ScratchSplit(); }
hsLargeArray<Int16>& ScratchCulled() const { return fTree->ScratchCulled(); }
hsBitVector& ScratchBitVec() const { return fTree->ScratchBitVec(); }
hsBitVector& ScratchTotVec() const { return fTree->ScratchTotVec(); }
friend class plCullTree;
public:
void Init(const plCullTree* t, const hsVector3& n, hsScalar d) { fIsFace = false; fTree = t; fInnerChild = fOuterChild = -1; SetPlane(n, d); }
void Init(const plCullTree* t, const plCullPoly& poly) { Init(t, poly.fNorm, poly.fDist); }
void SetPlane(const hsVector3& n, hsScalar d) { fNorm = n; fDist = d; }
const hsVector3& GetNormal() const { return fNorm; }
const hsScalar GetDist() const { return fDist; }
plCullStatus TestBounds(const hsBounds3Ext& bnd) const;
plCullStatus TestSphere(const hsPoint3& center, hsScalar rad) const;
};
inline plCullNode* plCullNode::IGetNode(Int16 i) const
{
return fTree->IGetNode(i);
}
#endif // plCullTree_inc

View File

@ -0,0 +1,44 @@
/*==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 plCuller_inc
#define plCuller_inc
#include "hsTemplates.h"
class plSpaceTree;
class plCuller
{
public:
plCuller() {}
~plCuller() {}
virtual void Harvest(const plSpaceTree* space, hsTArray<Int16>& outList) const = 0;
};
#endif // plCuller_inc

View File

@ -0,0 +1,238 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plDTProgressMgr Functions //
// //
//// History /////////////////////////////////////////////////////////////////
// //
// 2.28.2001 mcn - Created //
// //
//////////////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include "hsTypes.h"
#include "plDTProgressMgr.h"
#include "plPipeline.h"
#include "plDebugText.h"
#include "plPlates.h"
#include "../Apps/plClient/res/resource.h"
#include "hsTimer.h"
//// Constructor & Destructor ////////////////////////////////////////////////
plDTProgressMgr::plDTProgressMgr() :
fCurrentImage(0),
fLastDraw(0.0f),
fStaticTextPlate(nil),
fActivePlate(nil)
{
}
plDTProgressMgr::~plDTProgressMgr()
{
}
void plDTProgressMgr::DeclareThyself( void )
{
static plDTProgressMgr thyself;
}
void plDTProgressMgr::Activate()
{
if (fStaticTextPlate == nil && fCurrentStaticText != plProgressMgr::kNone)
{
plPlateManager::Instance().CreatePlate(&fStaticTextPlate);
fStaticTextPlate->CreateFromJPEGResource(MAKEINTRESOURCE(plProgressMgr::GetStaticTextID(fCurrentStaticText)), 0);
fStaticTextPlate->SetVisible(true);
fStaticTextPlate->SetOpacity(1.0f);
fStaticTextPlate->SetSize(2 * 0.192f, 2 * 0.041f, true);
fStaticTextPlate->SetPosition(0, 0.5f, 0);
}
if (fActivePlate == nil)
{
plPlateManager::Instance().CreatePlate( &fActivePlate );
fActivePlate->CreateFromJPEGResource( MAKEINTRESOURCE( plProgressMgr::GetLoadingFrameID(fCurrentImage) ), 0 );
fActivePlate->SetVisible(true);
fActivePlate->SetOpacity(1.0f);
fActivePlate->SetSize(0.6, 0.6, true);
fActivePlate->SetPosition(0, 0, 0);
}
}
void plDTProgressMgr::Deactivate()
{
if (fStaticTextPlate)
{
fStaticTextPlate->SetVisible(false);
plPlateManager::Instance().DestroyPlate( fStaticTextPlate );
fStaticTextPlate = nil;
}
if (fActivePlate)
{
fActivePlate->SetVisible(false);
plPlateManager::Instance().DestroyPlate( fActivePlate );
fActivePlate = nil;
}
}
//// Draw ////////////////////////////////////////////////////////////////////
void plDTProgressMgr::Draw( plPipeline *p )
{
UInt16 scrnWidth, scrnHeight, width, height, x, y;
plDebugText &text = plDebugText::Instance();
plOperationProgress *prog;
if( fOperations == nil )
return;
scrnWidth = (UInt16)p->Width();
scrnHeight = (UInt16)p->Height();
width = scrnWidth - 64;
height = 16;
x = ( scrnWidth - width ) >> 1;
y = scrnHeight - 32 - height;
if( fOperations->GetNext() == nil )
y -= text.GetFontSize() + 8 + height + 4;
text.SetDrawOnTopMode( true );
if (fActivePlate)
{
float currentMs = hsTimer::FullTicksToMs(hsTimer::GetFullTickCount());
if ((currentMs - fLastDraw) > 30)
{
fCurrentImage++;
if (fCurrentImage >= 18)
fCurrentImage = 0;
fLastDraw = currentMs;
fActivePlate->ReloadFromJPEGResource(MAKEINTRESOURCE(plProgressMgr::GetInstance()->GetLoadingFrameID(fCurrentImage)), 0);
fActivePlate->SetVisible(true);
fActivePlate->SetOpacity(1.0f);
fActivePlate->SetSize(0.6, 0.6, true);
fActivePlate->SetPosition(0, 0, 0);
}
}
for( prog = fOperations; prog != nil; prog = prog->GetNext() )
{
IDrawTheStupidThing( p, prog, x, y, width, height );
y -= text.GetFontSize() + 8 + height + 4;
}
text.SetDrawOnTopMode( false );
}
//// IDrawTheStupidThing /////////////////////////////////////////////////////
void plDTProgressMgr::IDrawTheStupidThing( plPipeline *p, plOperationProgress *prog,
UInt16 x, UInt16 y, UInt16 width, UInt16 height )
{
plDebugText &text = plDebugText::Instance();
// Lets just set the color to blue
UInt32 color = 0xff302b3a;
if( prog->GetMax() > 0.f )
{
text.Draw3DBorder(x, y, x + width - 1, y + height - 1, color, color);
x += 2;
y += 2;
width -= 4;
height -= 4;
UInt16 drawWidth = width;
Int16 drawX = x;
UInt16 rightX = drawX + drawWidth;
if (prog->GetProgress() <= prog->GetMax())
drawWidth = (UInt16)( (hsScalar)width * prog->GetProgress() / prog->GetMax() );
rightX = drawX + drawWidth;
if( drawWidth > 0 )
text.DrawRect( drawX, y, rightX, y + height, color );
int timeRemain = prog->fRemainingSecs;
char remainStr[1024];
strcpy(remainStr, "APPROXIMATELY ");
if (timeRemain > 3600)
{
const char* term = ((timeRemain / 3600) > 1) ? "HOURS" : "HOUR";
sprintf(remainStr, "%s%d %s ", remainStr, (timeRemain / 3600), term);
timeRemain %= 3600;
}
if (timeRemain > 60)
{
const char* term = ((timeRemain / 60) > 1) ? "MINUTES" : "MINUTE";
sprintf(remainStr, "%s%d %s ", remainStr, (timeRemain / 60), term);
timeRemain %= 60;
}
const char* unitTerm = (timeRemain == 1) ? "SECOND" : "SECONDS";
sprintf(remainStr, "%s%d %s REMAINING", remainStr, timeRemain, unitTerm);
text.DrawString(x, y + height + 2, remainStr, (UInt32)0xff635e6d );
x -= 2;
y -= 2;
}
y -= ( text.GetFontSize() << 1 ) + 4;
#ifndef PLASMA_EXTERNAL_RELEASE
bool drawText = true;
#else
bool drawText = false;
#endif
if (drawText)
{
if( prog->GetTitle()[ 0 ] != 0 )
{
text.DrawString( x, y, prog->GetTitle(), (UInt32)0xccb0b0b0 );
x += (UInt16)text.CalcStringWidth( prog->GetTitle() );
}
if( prog->GetStatusText()[ 0 ] != 0 )
text.DrawString( x, y, prog->GetStatusText(), (UInt32)0xccb0b0b0 );
}
}

View File

@ -0,0 +1,72 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plDTProgressMgr Header //
// //
//// Description /////////////////////////////////////////////////////////////
// //
// Derived class of plProgressMgr to draw the progress bars via debug text.//
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plDTProgressMgr_h
#define _plDTProgressMgr_h
#include "../plProgressMgr/plProgressMgr.h"
class plPipeline;
//// Manager Class Definition ////////////////////////////////////////////////
class plDTProgressMgr : public plProgressMgr
{
protected:
Int32 fCurrentImage;
float fLastDraw;
plPlate* fActivePlate;
plPlate* fStaticTextPlate;
StaticText fShowingStaticText;
void Activate();
void Deactivate();
void IDrawTheStupidThing( plPipeline *p, plOperationProgress *prog,
UInt16 x, UInt16 y, UInt16 width, UInt16 height );
public:
plDTProgressMgr();
~plDTProgressMgr();
virtual void Draw( plPipeline *p );
static void DeclareThyself( void );
};
#endif //_plDTProgressMgr_h

View File

@ -0,0 +1,155 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDXBufferRefs.h - Hardware Vertex and Index Buffer DeviceRef //
// Definitions //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 4.25.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDXBufferRefs_h
#define _plDXBufferRefs_h
#include "hsMatrix44.h"
#include "hsGeometry3.h"
#include "hsTemplates.h"
#include "plDXDeviceRef.h"
struct IDirect3DVertexShader9;
//// Definitions //////////////////////////////////////////////////////////////
class plDXVertexBufferRef : public plDXDeviceRef
{
public:
IDirect3DVertexBuffer9* fD3DBuffer;
UInt32 fCount;
UInt32 fIndex;
UInt32 fVertexSize;
Int32 fOffset;
UInt8 fFormat;
plGBufferGroup* fOwner;
UInt8* fData;
IDirect3DDevice9* fDevice; // For releasing the VertexShader
UInt32 fRefTime;
enum {
kRebuiltSinceUsed = 0x10, // kDirty = 0x1 is in hsGDeviceRef
kVolatile = 0x20,
kSkinned = 0x40
};
hsBool HasFlag(UInt32 f) const { return 0 != (fFlags & f); }
void SetFlag(UInt32 f, hsBool on) { if(on) fFlags |= f; else fFlags &= ~f; }
hsBool RebuiltSinceUsed() const { return HasFlag(kRebuiltSinceUsed); }
void SetRebuiltSinceUsed(hsBool b) { SetFlag(kRebuiltSinceUsed, b); }
hsBool Volatile() const { return HasFlag(kVolatile); }
void SetVolatile(hsBool b) { SetFlag(kVolatile, b); }
hsBool Skinned() const { return HasFlag(kSkinned); }
void SetSkinned(hsBool b) { SetFlag(kSkinned, b); }
hsBool Expired(UInt32 t) const { return Volatile() && (IsDirty() || (fRefTime != t)); }
void SetRefTime(UInt32 t) { fRefTime = t; }
void Link( plDXVertexBufferRef **back ) { plDXDeviceRef::Link( (plDXDeviceRef **)back ); }
plDXVertexBufferRef* GetNext() { return (plDXVertexBufferRef *)fNext; }
plDXVertexBufferRef() :
fD3DBuffer(nil),
fCount(0),
fIndex(0),
fVertexSize(0),
fOffset(0),
fOwner(nil),
fData(nil),
fFormat(0),
fRefTime(0),
fDevice(nil)
{
}
virtual ~plDXVertexBufferRef();
void Release();
};
class plDXIndexBufferRef : public plDXDeviceRef
{
public:
IDirect3DIndexBuffer9* fD3DBuffer;
UInt32 fCount;
UInt32 fIndex;
Int32 fOffset;
plGBufferGroup* fOwner;
UInt32 fRefTime;
D3DPOOL fPoolType;
enum {
kRebuiltSinceUsed = 0x10, // kDirty = 0x1 is in hsGDeviceRef
kVolatile = 0x20
};
hsBool HasFlag(UInt32 f) const { return 0 != (fFlags & f); }
void SetFlag(UInt32 f, hsBool on) { if(on) fFlags |= f; else fFlags &= ~f; }
hsBool RebuiltSinceUsed() const { return HasFlag(kRebuiltSinceUsed); }
void SetRebuiltSinceUsed(hsBool b) { SetFlag(kRebuiltSinceUsed, b); }
hsBool Volatile() const { return HasFlag(kVolatile); }
void SetVolatile(hsBool b) { SetFlag(kVolatile, b); }
hsBool Expired(UInt32 t) const { return Volatile() && (IsDirty() || (fRefTime != t)); }
void SetRefTime(UInt32 t) { fRefTime = t; }
void Link( plDXIndexBufferRef **back ) { plDXDeviceRef::Link( (plDXDeviceRef **)back ); }
plDXIndexBufferRef* GetNext() { return (plDXIndexBufferRef *)fNext; }
plDXIndexBufferRef() :
fD3DBuffer(nil),
fCount(0),
fIndex(0),
fOffset(0),
fOwner(nil),
fRefTime(0),
fPoolType(D3DPOOL_MANAGED)
{
}
virtual ~plDXIndexBufferRef();
void Release();
};
#endif // _plDXBufferRefs_h

View File

@ -0,0 +1,66 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDXDeviceRef.h - Header for the generic DX DeviceRef type //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 4.25.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDXDeviceRef_h
#define _plDXDeviceRef_h
#include "hsTypes.h"
#include "hsGDeviceRef.h"
//// Definition ///////////////////////////////////////////////////////////////
class plDXDeviceRef : public hsGDeviceRef
{
protected:
plDXDeviceRef *fNext;
plDXDeviceRef **fBack;
public:
void Unlink( void );
void Link( plDXDeviceRef **back );
plDXDeviceRef *GetNext( void ) { return fNext; }
hsBool IsLinked( void ) { return fBack != nil; }
virtual void Release( void ) { }
plDXDeviceRef();
virtual ~plDXDeviceRef();
};
#endif // _plDXDeviceRef_h

View File

@ -0,0 +1,514 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDXDeviceRefs.cpp - Functions for the various DX DeviceRef classes //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 4.25.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include <d3d9.h>
#include <ddraw.h>
#include "hsWinRef.h"
#include "plDXPipeline.h"
#include "plDXDeviceRef.h"
#include "plDXBufferRefs.h"
#include "plDXLightRef.h"
#include "plDXTextureRef.h"
#include "plDXRenderTargetRef.h"
#include "plGBufferGroup.h"
#include "../plDrawable/plGeometrySpan.h"
#include "../plDrawable/plDrawableSpans.h"
#include "../plGLight/plLightInfo.h"
#include "plRenderTarget.h"
#include "plCubicRenderTarget.h"
#include "plDynamicEnvMap.h"
#include "plProfile.h"
#include "../plStatusLog/plStatusLog.h"
plProfile_CreateMemCounter("Vertices", "Memory", MemVertex);
plProfile_CreateMemCounter("Indices", "Memory", MemIndex);
plProfile_CreateMemCounter("Textures", "Memory", MemTexture);
///////////////////////////////////////////////////////////////////////////////
//// Generic plDXDeviceRef Functions /////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
plDXDeviceRef::plDXDeviceRef()
{
fNext = nil;
fBack = nil;
}
plDXDeviceRef::~plDXDeviceRef()
{
if( fNext != nil || fBack != nil )
Unlink();
}
void plDXDeviceRef::Unlink( void )
{
hsAssert( fBack, "plDXDeviceRef not in list" );
if( fNext )
fNext->fBack = fBack;
*fBack = fNext;
fBack = nil;
fNext = nil;
}
void plDXDeviceRef::Link( plDXDeviceRef **back )
{
hsAssert( fNext == nil && fBack == nil, "Trying to link a plDXDeviceRef that's already linked" );
fNext = *back;
if( *back )
(*back)->fBack = &fNext;
fBack = back;
*back = this;
}
///////////////////////////////////////////////////////////////////////////////
//// plDXVertex/IndexBufferRef Funktions /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//// Destructors //////////////////////////////////////////////////////////////
plDXVertexBufferRef::~plDXVertexBufferRef()
{
Release();
}
plDXIndexBufferRef::~plDXIndexBufferRef()
{
Release();
}
//// Releases /////////////////////////////////////////////////////////////////
void plDXVertexBufferRef::Release( void )
{
if( fD3DBuffer != nil )
{
ReleaseObject(fD3DBuffer);
if (!Volatile())
{
plProfile_DelMem(MemVertex, fCount * fVertexSize);
PROFILE_POOL_MEM(D3DPOOL_MANAGED, fCount * fVertexSize, false, "VtxBuff");
plDXPipeline::FreeManagedVertex(fCount * fVertexSize);
}
}
delete [] fData;
fData = nil;
SetDirty( true );
}
void plDXIndexBufferRef::Release( void )
{
if( fD3DBuffer != nil )
{
plProfile_DelMem(MemIndex, fCount * sizeof(UInt16));
PROFILE_POOL_MEM(fPoolType, fCount * sizeof(UInt16), false, "IndexBuff");
ReleaseObject( fD3DBuffer );
}
SetDirty( true );
}
///////////////////////////////////////////////////////////////////////////////
//// plDXTextureRef Funktions ////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//// Set //////////////////////////////////////////////////////////////////////
plDXTextureRef& plDXTextureRef::Set( D3DFORMAT ft, UInt32 ml, UInt32 mw, UInt32 mh, UInt32 np,
UInt32 sz, UInt32 manSize, UInt32* lSz, void* pd, hsBool ed, hsBool renderTarget )
{
if( fDataSize > 0 )
plProfile_DelMem(MemTexture, fDataSize + sizeof(plDXTextureRef));
if( ( fFormatType != ft || fMMLvs != ml || fMaxWidth != mw || fMaxHeight != mh ) && fD3DTexture != nil )
ReleaseObject( fD3DTexture );
if( !fD3DTexture )
fUseTime = 0;
fFormatType = ft;
fMMLvs = ml;
fMaxWidth = mw;
fMaxHeight = mh;
fNumPix = np;
fDataSize = manSize;
if( fLevelSizes != nil )
delete [] fLevelSizes;
if( lSz )
fLevelSizes = lSz;
else
{
fLevelSizes = TRACKED_NEW UInt32[1];
fLevelSizes[0] = sz;
}
fData = pd;
fFlags = ( ed ? kExternData : 0 ) | ( renderTarget ? kRenderTarget : 0 );
plProfile_NewMem(MemTexture, fDataSize + sizeof(plDXTextureRef));
return *this;
}
//// Constructor & Destructor /////////////////////////////////////////////////
plDXTextureRef::plDXTextureRef( D3DFORMAT ft, UInt32 ml, UInt32 mw, UInt32 mh, UInt32 np,
UInt32 sz, UInt32 manSize, UInt32* lSz, void* pd, hsBool ed, hsBool renderTarget )
{
fLevelSizes = nil;
fOwner = nil;
fD3DTexture = nil;
fDataSize = 0;
fFlags = 0;
fFormatType = D3DFMT_UNKNOWN;
fMMLvs = 0;
fMaxWidth = 0;
fMaxHeight = 0;
Set( ft, ml, mw, mh, np, sz, manSize, lSz, pd, ed, renderTarget );
}
plDXTextureRef::~plDXTextureRef()
{
Release();
delete [] fLevelSizes;
}
//// Release //////////////////////////////////////////////////////////////////
void plDXTextureRef::Release( void )
{
plProfile_DelMem(MemTexture, fDataSize + sizeof(plDXTextureRef));
plProfile_Extern(ManagedMem);
PROFILE_POOL_MEM(D3DPOOL_MANAGED, fDataSize, false, (fOwner ? fOwner->GetKey() ? fOwner->GetKey()->GetUoid().GetObjectName() : "(UnknownTexture)" : "(UnknownTexture)"));
plDXPipeline::FreeManagedTexture(fDataSize);
fDataSize = 0;
ReleaseObject( fD3DTexture );
SetDirty( true );
}
///////////////////////////////////////////////////////////////////////////////
//// plDXLightRef Funktions //////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//// UpdateD3DInfo ////////////////////////////////////////////////////////////
#define SET_D3DCOLORVALUE( v, color ) { v.r = color.r; v.g = color.g; v.b = color.b; v.a = color.a; }
void plDXLightRef::UpdateD3DInfo( IDirect3DDevice9 *dev, plDXLightSettings *settings )
{
plDirectionalLightInfo *dirOwner;
plOmniLightInfo *omniOwner;
plSpotLightInfo *spotOwner;
const float maxRange = 32767.f;
/// Properties that are set for all types
fD3DDevice = dev;
fParentSettings = settings;
memset( &fD3DInfo, 0, sizeof( D3DLIGHT9 ) );
SET_D3DCOLORVALUE( fD3DInfo.Diffuse, fOwner->GetDiffuse() );
SET_D3DCOLORVALUE( fD3DInfo.Ambient, fOwner->GetAmbient() );
SET_D3DCOLORVALUE( fD3DInfo.Specular, fOwner->GetSpecular() );
if( ( omniOwner = plOmniLightInfo::ConvertNoRef( fOwner ) ) != nil )
{
fD3DInfo.Type = D3DLIGHT_POINT;
hsPoint3 position = omniOwner->GetWorldPosition();
fD3DInfo.Position.x = position.fX;
fD3DInfo.Position.y = position.fY;
fD3DInfo.Position.z = position.fZ;
if( omniOwner->GetRadius() == 0 )
fD3DInfo.Range = maxRange;
else
fD3DInfo.Range = omniOwner->GetRadius();
fD3DInfo.Attenuation0 = omniOwner->GetConstantAttenuation();
fD3DInfo.Attenuation1 = omniOwner->GetLinearAttenuation();
fD3DInfo.Attenuation2 = omniOwner->GetQuadraticAttenuation();
// If the light is a spot, but it has a projected texture, then
// the cone attenuation is handled by the texture. We're only using
// the D3D light for distance attenuation and the N*L term. So
// we can just leave the D3D light as the cheaper and more stable
// Omni light. This sort of obviates the change below. - mf
if( !omniOwner->GetProjection()
&& (spotOwner = plSpotLightInfo::ConvertNoRef(fOwner)) )
{
fD3DInfo.Type = D3DLIGHT_SPOT;
hsVector3 direction = spotOwner->GetWorldDirection();
fD3DInfo.Direction.x = direction.fX;
fD3DInfo.Direction.y = direction.fY;
fD3DInfo.Direction.z = direction.fZ;
fD3DInfo.Falloff = spotOwner->GetFalloff();
fD3DInfo.Theta = spotOwner->GetSpotInner() * 2;
// fD3DInfo.Phi = spotOwner->GetProjection() ? hsScalarPI : spotOwner->GetSpotOuter() * 2;
// D3D doesn't seem to like a Phi of PI, even though that's supposed to be the
// largest legal value. Symptom is an erratic, intermitant, unpredictable failure
// of the light to light, with bizarreness like lighting one object but not the object
// next to it, alternating which object it fails on each frame (or less often).
// So, whatever. - mf
fD3DInfo.Phi = spotOwner->GetSpotOuter() * 2;
}
}
else if( ( dirOwner = plDirectionalLightInfo::ConvertNoRef( fOwner ) ) != nil )
{
fD3DInfo.Type = D3DLIGHT_DIRECTIONAL;
hsVector3 direction = dirOwner->GetWorldDirection();
fD3DInfo.Direction.x = direction.fX;
fD3DInfo.Direction.y = direction.fY;
fD3DInfo.Direction.z = direction.fZ;
}
else
{
hsAssert( false, "Unrecognized light type passed to plDXLightRef::UpdateD3DInfo()" );
return;
}
fD3DDevice->SetLight( fD3DIndex, &fD3DInfo );
fScale = 1.f;
}
//// Destructor ///////////////////////////////////////////////////////////////
plDXLightRef::~plDXLightRef()
{
Release();
}
//// Release //////////////////////////////////////////////////////////////////
void plDXLightRef::Release( void )
{
// Ensure that this light is disabled
if( fD3DDevice )
{
fD3DDevice->LightEnable( fD3DIndex, false );
fD3DDevice = nil;
}
if( fParentSettings )
{
fParentSettings->fEnabledFlags.SetBit( fD3DIndex, false );
fParentSettings->ReleaseD3DIndex( fD3DIndex );
fParentSettings = nil;
}
fD3DIndex = 0;
SetDirty( true );
}
///////////////////////////////////////////////////////////////////////////////
//// plDXRenderTargetRef Functions ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//// Constructor //////////////////////////////////////////////////////////////
plDXRenderTargetRef::plDXRenderTargetRef( D3DFORMAT tp, UInt32 ml, plRenderTarget *owner, hsBool releaseDepthOnDelete )
: plDXTextureRef( tp, ml, owner->GetWidth(), owner->GetHeight(),
owner->GetWidth() * owner->GetHeight(),
owner->GetWidth() * owner->GetHeight() * ( owner->GetPixelSize() >> 3 ),
0,
nil,
nil, true, true )
{
fD3DColorSurface = nil;
fD3DDepthSurface = nil;
fReleaseDepth = releaseDepthOnDelete;
fOwner = owner;
if( owner->GetFlags() & plRenderTarget::kIsTexture )
fFlags |= kOffscreenRT;
if( owner->GetFlags() & plRenderTarget::kIsProjected )
{
if( owner->GetFlags() & plRenderTarget::kIsOrtho )
fFlags |= kOrthoProjection;
else
fFlags |= kPerspProjection;
}
if( plCubicRenderTarget::ConvertNoRef( owner ) != nil )
fFlags |= kCubicMap;
}
//// Set //////////////////////////////////////////////////////////////////////
plDXRenderTargetRef& plDXRenderTargetRef::Set( D3DFORMAT tp, UInt32 ml, plRenderTarget *owner )
{
fOwner = owner;
plDXTextureRef::Set( tp, ml, owner->GetWidth(), owner->GetHeight(),
owner->GetWidth() * owner->GetHeight(),
owner->GetWidth() * owner->GetHeight() * ( owner->GetPixelSize() >> 3 ),
0,
nil,
nil, true, true );
if( owner->GetFlags() & plRenderTarget::kIsTexture )
fFlags |= kOffscreenRT;
if( owner->GetFlags() & plRenderTarget::kIsProjected )
{
if( owner->GetFlags() & plRenderTarget::kIsOrtho )
fFlags |= kOrthoProjection;
else
fFlags |= kPerspProjection;
}
if( plCubicRenderTarget::ConvertNoRef( owner ) != nil )
fFlags |= kCubicMap;
return *this;
}
//// SetTexture ///////////////////////////////////////////////////////////////
void plDXRenderTargetRef::SetTexture( IDirect3DSurface9 *surface, IDirect3DSurface9 *depth )
{
fD3DColorSurface = surface;
fD3DTexture = nil;
fD3DDepthSurface = depth;
}
void plDXRenderTargetRef::SetTexture( IDirect3DTexture9 *surface, IDirect3DSurface9 *depth )
{
fD3DTexture = surface;
fD3DColorSurface = nil;
fD3DDepthSurface = depth;
}
void plDXRenderTargetRef::SetTexture( IDirect3DCubeTexture9 *surface, IDirect3DSurface9 *depth )
{
int i;
IDirect3DSurface9 *surf;
plDXRenderTargetRef *ref;
plCubicRenderTarget *cubic;
D3DCUBEMAP_FACES faces[ 6 ] = { D3DCUBEMAP_FACE_NEGATIVE_X, // Left
D3DCUBEMAP_FACE_POSITIVE_X, // Right
D3DCUBEMAP_FACE_POSITIVE_Z, // Front
D3DCUBEMAP_FACE_NEGATIVE_Z, // Back
D3DCUBEMAP_FACE_POSITIVE_Y, // Top
D3DCUBEMAP_FACE_NEGATIVE_Y }; // Bottom
fD3DTexture = surface;
fD3DDepthSurface = depth;
fD3DColorSurface = nil;
/// Get the faces and assign to each of the child targets
cubic = plCubicRenderTarget::ConvertNoRef( fOwner );
for( i = 0; i < 6; i++ )
{
if( surface->GetCubeMapSurface( faces[ i ], 0, &surf ) != D3D_OK )
{
hsAssert( false, "Unable to get cube map surface" );
continue;
}
ref = (plDXRenderTargetRef *)cubic->GetFace( i )->GetDeviceRef();
ref->SetTexture( surf, depth );
}
}
//// Destructor ///////////////////////////////////////////////////////////////
plDXRenderTargetRef::~plDXRenderTargetRef()
{
Release();
}
//// Release //////////////////////////////////////////////////////////////////
void plDXRenderTargetRef::Release( void )
{
int i;
plCubicRenderTarget *cubic;
plDXRenderTargetRef *ref;
/// Get rid of the children's deviceRefs
if( fFlags & kCubicMap )
{
cubic = plCubicRenderTarget::ConvertNoRef( fOwner );
for( i = 0; i < 6; i++ )
{
ref = (plDXRenderTargetRef *)cubic->GetFace( i )->GetDeviceRef();
ref->Release();
ref->SetDirty( true );
}
// No need to call D3DSURF_MEMDEL on our fD3DTexture. It'll get
// accounted for by our children's surfaces.
}
else
{
// We do internal accounting here. Actual release of fD3DTexture
// happens in plDXTextureRef::Release()
D3DSURF_MEMDEL((IDirect3DTexture9*)fD3DTexture);
}
D3DSURF_MEMDEL(fD3DColorSurface);
ReleaseObject( fD3DColorSurface );
if( fReleaseDepth )
{
// TODO:
// We don't know who all is sharing this depth surface, so we can't
// confidently say this memory is free now. We're reffing and releasing
// it properly as far as DirectX is concerned, but our internal memory
// counter is ignoring it.
//D3DSURF_MEMDEL(fD3DDepthSurface);
ReleaseObject( fD3DDepthSurface );
}
plDXTextureRef::Release();
SetDirty( true );
}

View File

@ -0,0 +1,893 @@
/*==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==*/
#include "plDXEnumerate.h"
#include <ddraw.h>
#include "hsGDDrawDllLoad.h"
#include "hsG3DDeviceSelector.h"
#include "hsUtils.h"
//// Local Typedefs ///////////////////////////////////////////////////////////
typedef LPDIRECT3D9 (WINAPI * Direct3DCreateProc)( UINT sdkVersion );
const UInt8 hsGDirect3DTnLEnumerate::kNumDisplayFormats = 6;
const D3DFORMAT hsGDirect3DTnLEnumerate::kDisplayFormats[] =
{
D3DFMT_A1R5G5B5,
D3DFMT_A2B10G10R10,
D3DFMT_A8R8G8B8,
D3DFMT_R5G6B5,
D3DFMT_X1R5G5B5,
D3DFMT_X8R8G8B8,
};
HRESULT hsGDirect3DTnLEnumerate::SelectFromDevMode(const hsG3DDeviceRecord* devRec, const hsG3DDeviceMode* devMode)
{
int i;
for( i = 0; i < GetNumDrivers(); i++ )
{
if( !stricmp(GetDriver(i)->fAdapterInfo.Description, devRec->GetDriverDesc()) )
{
int j;
for( j = 0; j < GetDriver(i)->fDevices.GetCount(); j++ )
{
if( !stricmp(GetDriver(i)->fDevices[j].fStrName, devRec->GetDeviceDesc()) )
{
SetCurrentDriver(GetDriver(i));
SetCurrentDevice(&GetDriver(i)->fDevices[j]);
D3DEnum_SelectDefaultMode(
devMode->GetWidth(),
devMode->GetHeight(),
devMode->GetColorDepth());
return false;
}
}
}
}
char errStr[256];
sprintf(errStr, "Can't find requested device - %s:%s:%s:%s:%s",
devRec->GetG3DDeviceTypeName(),
devRec->GetDriverDesc(),
devRec->GetDriverName(),
devRec->GetDriverVersion(),
devRec->GetDeviceDesc());
DWORD enumFlags = 0;
int width = devMode->GetWidth();
int height = devMode->GetHeight();
int colorDepth = devMode->GetColorDepth();
// for a window, take whatever colordepth we can get.
if( !colorDepth )
enumFlags |= D3DENUM_CANWINDOW;
enumFlags |= D3DENUM_TNLHAL;
#ifdef HS_ALLOW_D3D_REF_DRIVER
enumFlags |= D3DENUM_REFERENCERAST;
#endif
D3DEnum_SelectDefaultDriver(enumFlags);
// If we didn't get what we want, try for anything.
if( !GetCurrentDriver() || !GetCurrentDevice() )
{
enumFlags = colorDepth ? 0 : D3DENUM_CANWINDOW;
D3DEnum_SelectDefaultDriver(enumFlags);
}
if( !GetCurrentDriver() || !GetCurrentDevice() )
D3DEnum_SelectDefaultDriver(0);
if( !GetCurrentDriver() || !GetCurrentDevice() )
{
if( !*GetEnumeErrorStr() )
SetEnumeErrorStr("Error finding device");
return true;
}
D3DEnum_SelectDefaultMode(width, height, colorDepth);
if( !GetCurrentMode() )
{
if( !*GetEnumeErrorStr() )
SetEnumeErrorStr("Error finding mode");
return true;
}
return false;
}
HRESULT hsGDirect3DTnLEnumerate::D3DEnum_SelectDefaultMode(int width, int height, int depth)
{
hsAssert(GetCurrentDriver() && GetCurrentDevice(), "Must have selected device already");
BOOL windowed = false;
if (depth == 0)
{
// Legacy code writes out 0 bit depth to mean windowed
windowed = true;
depth = 32;
}
D3DEnum_DeviceInfo* device = GetCurrentDevice();
int i;
for( i = 0; i < device->fModes.GetCount(); i++ )
{
D3DEnum_ModeInfo* mode = &device->fModes[i];
if (mode->fWindowed != windowed)
continue;
if( depth )
{
if( width < mode->fDDmode.Width )
continue;
if( height < mode->fDDmode.Height )
continue;
}
if( depth < mode->fBitDepth )
continue;
if( GetCurrentMode() )
{
D3DEnum_ModeInfo* curMode = GetCurrentDriver()->fCurrentMode;
if( depth )
{
if( curMode->fDDmode.Width > mode->fDDmode.Width )
continue;
if( curMode->fDDmode.Height > mode->fDDmode.Height )
continue;
}
if( curMode->fBitDepth > mode->fBitDepth )
continue;
}
SetCurrentMode(mode);
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_SelectDefaultDriver()
// Desc: Picks a default driver according to the passed in flags.
//-----------------------------------------------------------------------------
HRESULT hsGDirect3DTnLEnumerate::D3DEnum_SelectDefaultDriver( DWORD dwFlags )
{
// If a specific driver was requested, perform that search here
if( dwFlags & D3DENUM_MASK )
{
int i;
for( i = 0; i < fDrivers.GetCount(); i++ )
{
D3DEnum_DriverInfo* pDriver = &fDrivers[i];
int j;
for( j = 0; j < pDriver->fDevices.GetCount(); j++ )
{
D3DEnum_DeviceInfo* pDevice = &pDriver->fDevices[j];
BOOL bFound = FALSE;
if( pDevice->fDDType == D3DDEVTYPE_REF )
{
if( dwFlags & D3DENUM_REFERENCERAST )
bFound = TRUE;
}
else if( pDevice->fDDType == D3DDEVTYPE_HAL &&
pDevice->fDDCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
if( dwFlags & D3DENUM_TNLHAL )
bFound = TRUE;
}
else
{
#if !HS_BUILD_FOR_XBOX
if( dwFlags & D3DENUM_CANWINDOW )
{
if( (pDriver == &fDrivers[0])
&&( pDevice->fDDCaps.Caps2 & DDCAPS2_CANRENDERWINDOWED ) )
{
if( ( pDevice->fDDCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
^ !(dwFlags & D3DENUM_TNLHAL) )
bFound = TRUE;
}
}
else
#endif
if( dwFlags & D3DENUM_PRIMARYHAL )
{
if( pDriver == &fDrivers[0] )
bFound = TRUE;
}
else
if( dwFlags & D3DENUM_SECONDARYHAL )
{
if( pDriver != &fDrivers[0] )
bFound = TRUE;
}
}
if( bFound )
{
SetCurrentDriver(pDriver);
SetCurrentDevice(pDevice);
return S_OK;
}
}
}
return D3DENUMERR_NOTFOUND;
}
int i;
for( i = 0; i < fDrivers.GetCount(); i++ )
{
D3DEnum_DriverInfo* pDriver = &fDrivers[i];
int j;
for( j = 0; j < pDriver->fDevices.GetCount(); j++ )
{
D3DEnum_DeviceInfo* pDevice = &pDriver->fDevices[j];
if( !pDevice->fIsHardware )
continue;
SetCurrentDriver(pDriver);
SetCurrentDevice(pDevice);
return S_OK;
}
}
// No compatible devices were found. Return an error code
return D3DENUMERR_NOCOMPATIBLEDEVICES;
}
//// Constructor //////////////////////////////////////////////////////////////
//
// Inits the enumeration and builds our list of devices/whatever.
hsGDirect3DTnLEnumerate::hsGDirect3DTnLEnumerate()
{
memset( &fEnumeErrorStr[0], 0x00, sizeof(fEnumeErrorStr) );
fCurrentDriver = NULL; // The selected DD driver
fDrivers.Reset(); // List of DD drivers
/// New DX Enumeration
// Get a pointer to the creation function
#if !HS_BUILD_FOR_XBOX
if( hsGDDrawDllLoad::GetD3DDll() == nil )
{
strcpy( fEnumeErrorStr, "Cannot load Direct3D driver!" );
return;
}
Direct3DCreateProc procPtr;
procPtr = (Direct3DCreateProc)GetProcAddress( hsGDDrawDllLoad::GetD3DDll(), "Direct3DCreate9" );
if( procPtr == nil )
{
strcpy( fEnumeErrorStr, "Cannot load D3D Create Proc!" );
return;
}
// Create a D3D object to use
IDirect3D9 *pD3D = procPtr( D3D_SDK_VERSION );
#else
IDirect3D9 *pD3D = Direct3DCreate9( D3D_SDK_VERSION );
#endif
if( pD3D == nil )
{
strcpy( fEnumeErrorStr, "Cannot load DirectX!" );
return;
}
/// Loop through the "adapters" (we don't call them drivers anymore)
UINT iAdapter;
for( iAdapter = 0; iAdapter < pD3D->GetAdapterCount(); iAdapter++ )
{
D3DEnum_DriverInfo* newDriver = fDrivers.Push();
ZeroMemory( newDriver, sizeof( *newDriver ) );
// Copy data to a device info structure
D3DADAPTER_IDENTIFIER9 adapterInfo;
pD3D->GetAdapterIdentifier( iAdapter, 0, &adapterInfo );
pD3D->GetAdapterDisplayMode( iAdapter, &newDriver->fDesktopMode );
memcpy( &newDriver->fAdapterInfo, &adapterInfo, sizeof( adapterInfo ) );
strncpy( newDriver->fStrName, adapterInfo.Driver, 39 );
strncpy( newDriver->fStrDesc, adapterInfo.Description, 39 );
newDriver->fGuid = adapterInfo.DeviceIdentifier;
newDriver->fMemory = 16 * 1024 * 1024; /// Simulate 16 MB
/// Do the mode and device enumeration for this adapter
IEnumAdapterDevices( pD3D, iAdapter, newDriver );
}
// Cleanup
pD3D->Release();
}
//// IEnumAdapterDevices //////////////////////////////////////////////////////
//
// DirectX: Enumerates all the modes for a given adapter, then using the
// two faked modes for HAL and REF, attaches the modes to each "device" that
// can support them.
void hsGDirect3DTnLEnumerate::IEnumAdapterDevices( IDirect3D9 *pD3D, UINT iAdapter, D3DEnum_DriverInfo *drivInfo )
{
// A bit backwards from DX8... First we have to go through our list of formats and check for validity.
// Then we can enum through the modes for each format.
const DWORD numDeviceTypes = 2;
const TCHAR* strDeviceDescs[] = { "HAL", "REF" };
const D3DDEVTYPE deviceTypes[] = { D3DDEVTYPE_HAL, D3DDEVTYPE_REF };
BOOL *formatWorks = TRACKED_NEW BOOL[kNumDisplayFormats + 1]; // One for each format
DWORD *behavior = TRACKED_NEW DWORD[kNumDisplayFormats + 1];
UINT iDevice;
for (iDevice = 0; iDevice < numDeviceTypes; iDevice++)
{
D3DEnum_DeviceInfo *deviceInfo = drivInfo->fDevices.Push();
ZeroMemory(deviceInfo, sizeof(*deviceInfo));
pD3D->GetDeviceCaps(iAdapter, deviceTypes[iDevice], &deviceInfo->fDDCaps);
strncpy(deviceInfo->fStrName, strDeviceDescs[iDevice], 39);
deviceInfo->fDDType = deviceTypes[iDevice];
deviceInfo->fIsHardware = deviceInfo->fDDCaps.DevCaps & D3DDEVCAPS_HWRASTERIZATION;
/// Loop through the formats, checking each against this device to see
/// if it will work. If so, add all modes matching that format
UInt8 iFormat;
for (iFormat = 0; iFormat < kNumDisplayFormats + 1; iFormat++ )
{
// the desktop format gets to be first, everything else is nudged over one.
D3DFORMAT currFormat = (iFormat == 0 ? drivInfo->fDesktopMode.Format : kDisplayFormats[iFormat - 1]);
formatWorks[iFormat] = FALSE;
int bitDepth = IGetDXBitDepth(currFormat);
if (bitDepth == 0)
continue; // Don't like this mode, skip it
/// Can it be used as a render target?
if (FAILED(pD3D->CheckDeviceType(iAdapter, deviceTypes[iDevice],
currFormat,
currFormat,
FALSE)))
continue; // Nope--skip it
if (deviceInfo->fDDCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{
/// Confirm that HW vertex processing works on this device
if (deviceInfo->fDDCaps.DevCaps & D3DDEVCAPS_PUREDEVICE)
{
#if 0
behavior[iFormat] = D3DCREATE_HARDWARE_VERTEXPROCESSING |
D3DCREATE_PUREDEVICE;
#else
behavior[iFormat] = D3DCREATE_HARDWARE_VERTEXPROCESSING;
#endif
if (SUCCEEDED(IConfirmDevice(&deviceInfo->fDDCaps, behavior[iFormat],
currFormat)))
{
formatWorks[iFormat] = TRUE;
}
}
if (!formatWorks[iFormat])
{
/// HW vertex & Pure didn't work--just try HW vertex
behavior[iFormat] = D3DCREATE_HARDWARE_VERTEXPROCESSING;
if (SUCCEEDED(IConfirmDevice(&deviceInfo->fDDCaps, behavior[iFormat],
currFormat)))
{
formatWorks[iFormat] = TRUE;
}
}
if (!formatWorks[iFormat])
{
/// HW vertex didn't work--can we do mixed?
behavior[iFormat] = D3DCREATE_MIXED_VERTEXPROCESSING;
if (SUCCEEDED(IConfirmDevice(&deviceInfo->fDDCaps, behavior[iFormat],
currFormat)))
{
formatWorks[iFormat] = TRUE;
}
}
}
if (!formatWorks[iFormat])
{
/// Egads. Try SW vertex processing
behavior[iFormat] = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
if (SUCCEEDED(IConfirmDevice(&deviceInfo->fDDCaps, behavior[iFormat],
currFormat)))
{
formatWorks[iFormat] = TRUE;
}
}
if (formatWorks[iFormat])
{
/// Now go through all the modes. If a given mode has a format that works,
/// add it to the device
UINT numAdapterModes = pD3D->GetAdapterModeCount(iAdapter, currFormat);
DWORD iMode;
for (iMode = 0; iMode < numAdapterModes; iMode++)
{
// TODO: Check for modes that only differ by refresh rate and exclude duplicates.
/// Get the mode attributes
D3DDISPLAYMODE dispMode;
pD3D->EnumAdapterModes(iAdapter, currFormat, iMode, &dispMode);
{
/// Add it to our driver's global mode list
D3DEnum_ModeInfo *modeInfo = drivInfo->fModes.Push();
ZeroMemory( modeInfo, sizeof( *modeInfo ) );
modeInfo->fDDmode = dispMode;
sprintf( modeInfo->fStrDesc, TEXT( "%ld x %ld x %ld" ), dispMode.Width, dispMode.Height, bitDepth );
modeInfo->fBitDepth = bitDepth;
// Add it to the device
modeInfo->fDDBehavior = behavior[ iFormat ];
IFindDepthFormats( pD3D, iAdapter, deviceInfo->fDDType, modeInfo );
IFindFSAATypes( pD3D, iAdapter, deviceInfo->fDDType, modeInfo );
ICheckCubicRenderTargets( pD3D, iAdapter, deviceInfo->fDDType, modeInfo );
deviceInfo->fModes.Append( *modeInfo );
// Special check for the desktop, which we know is the first entry, because we put it there.
if (iFormat == 0)
{
/// Check if the device can window and/or is compatible with the desktop display mode
deviceInfo->fCompatibleWithDesktop = TRUE;
// As of DirectX 9, any device supports windowed mode
//if (deviceInfo->fDDCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED)
{
deviceInfo->fCanWindow = TRUE;
/// Add a fake mode to represent windowed. Silly, but here for legacy
D3DEnum_ModeInfo *pModeInfo = drivInfo->fModes.Push();
ZeroMemory(pModeInfo, sizeof(*pModeInfo));
pModeInfo->fDDmode = dispMode;
pModeInfo->fDDBehavior = behavior[iFormat];
pModeInfo->fBitDepth = bitDepth;
sprintf(pModeInfo->fStrDesc, TEXT("Windowed"));
pModeInfo->fWindowed = true;
IFindDepthFormats(pD3D, iAdapter, deviceInfo->fDDType, pModeInfo);
IFindFSAATypes(pD3D, iAdapter, deviceInfo->fDDType, pModeInfo);
ICheckCubicRenderTargets(pD3D, iAdapter, deviceInfo->fDDType, pModeInfo);
deviceInfo->fModes.Append( *pModeInfo );
}
}
}
}
}
}
}
delete [] formatWorks;
delete [] behavior;
}
//// IFindDepthFormats ////////////////////////////////////////////////////////
// DirectX: Given a device and mode, find ALL available depth/stencil
// formats and add them to the mode info struct.
hsBool hsGDirect3DTnLEnumerate::IFindDepthFormats( IDirect3D9 *pD3D, UINT iAdapter, D3DDEVTYPE deviceType,
D3DEnum_ModeInfo *modeInfo )
{
#if HS_BUILD_FOR_XBOX
D3DFORMAT formats[] = { D3DFMT_D16, D3DFMT_D24S8, D3DFMT_UNKNOWN };
#else
D3DFORMAT formats[] = { D3DFMT_D16, D3DFMT_D24X8, D3DFMT_D32,
D3DFMT_D15S1, D3DFMT_D24X4S4, D3DFMT_D24S8, D3DFMT_UNKNOWN };
#endif
/// Try 'em
for( int i = 0; formats[ i ] != D3DFMT_UNKNOWN; i++ )
{
if( SUCCEEDED( pD3D->CheckDeviceFormat( iAdapter, deviceType, modeInfo->fDDmode.Format,
D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE,
formats[ i ] ) ) )
{
if( SUCCEEDED( pD3D->CheckDepthStencilMatch( iAdapter, deviceType,
modeInfo->fDDmode.Format, modeInfo->fDDmode.Format, formats[ i ] ) ) )
{
modeInfo->fDepthFormats.Append( formats[ i ] );
}
}
}
return( modeInfo->fDepthFormats.GetCount() > 0 ? true : false );
}
//// IFindFSAATypes ///////////////////////////////////////////////////////////
// DirectX: Given a device and mode, find ALL available multisample types
// and add them to the mode info struct.
hsBool hsGDirect3DTnLEnumerate::IFindFSAATypes( IDirect3D9 *pD3D, UINT iAdapter, D3DDEVTYPE deviceType,
D3DEnum_ModeInfo *modeInfo )
{
/// Try 'em
for (int type = 2; type <= 16; type++)
{
if (SUCCEEDED(pD3D->CheckDeviceMultiSampleType(iAdapter, deviceType, modeInfo->fDDmode.Format,
modeInfo->fWindowed ? TRUE : FALSE,
(D3DMULTISAMPLE_TYPE)type, NULL)))
{
modeInfo->fFSAATypes.Append((D3DMULTISAMPLE_TYPE)type);
}
}
return (modeInfo->fFSAATypes.GetCount() > 0 ? true : false);
}
//// ICheckCubicRenderTargets /////////////////////////////////////////////////
hsBool hsGDirect3DTnLEnumerate::ICheckCubicRenderTargets( IDirect3D9 *pD3D, UINT iAdapter, D3DDEVTYPE deviceType,
D3DEnum_ModeInfo *modeInfo )
{
if( SUCCEEDED( pD3D->CheckDeviceFormat( iAdapter, deviceType, modeInfo->fDDmode.Format,
D3DUSAGE_RENDERTARGET, D3DRTYPE_CUBETEXTURE,
modeInfo->fDDmode.Format ) ) )
{
modeInfo->fCanRenderToCubic = true;
return true;
}
modeInfo->fCanRenderToCubic = false;
return false;
}
//// IConfirmDevice ///////////////////////////////////////////////////////////
//
// Nice, encapsulated way of testing for specific caps on a particular device
HRESULT hsGDirect3DTnLEnumerate::IConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
D3DFORMAT Format )
{
short bits;
bits = IGetDXBitDepth( Format );
if( bits == 16 || bits == 24 || bits == 32 )
return S_OK;
return E_FAIL;
}
//-----------------------------------------------------------------------------
// Name: ~hsGDirect3DTnLEnumerate()
// Desc:
//-----------------------------------------------------------------------------
hsGDirect3DTnLEnumerate::~hsGDirect3DTnLEnumerate()
{
D3DEnum_FreeResources();
}
//-----------------------------------------------------------------------------
// Name: D3DEnum_FreeResources()
// Desc: Frees all resources used for driver enumeration
//-----------------------------------------------------------------------------
VOID hsGDirect3DTnLEnumerate::D3DEnum_FreeResources()
{
}
//-----------------------------------------------------------------------------
// Name: SetEnumeErrorStr()
// Desc:
//-----------------------------------------------------------------------------
void hsGDirect3DTnLEnumerate::SetEnumeErrorStr(const char* s)
{
hsStrncpy(fEnumeErrorStr, s, 128);
}
//// IGetDXBitDepth //////////////////////////////////////////////////////////
//
// From a D3DFORMAT enumeration, return the bit depth associated with it.
// Copied from hsGDirect3DDevice to prevent inclusion of that class in
// the RenderMenu project (for some reason, VC can't figure out we're only
// calling one static function!)
short hsGDirect3DTnLEnumerate::IGetDXBitDepth( D3DFORMAT format )
{
#define ReturnDepth(type, depth) if (format == type) return depth
ReturnDepth(D3DFMT_UNKNOWN, 0);
ReturnDepth(D3DFMT_A8R8G8B8, 32);
ReturnDepth(D3DFMT_X8R8G8B8, 32);
ReturnDepth(D3DFMT_R5G6B5, 16);
ReturnDepth(D3DFMT_X1R5G5B5, 16);
ReturnDepth(D3DFMT_A1R5G5B5, 16);
// Supported by DX9, but we don't currently support it. Can add support if needed.
//ReturnDepth(D3DFMT_A2B10G10R10, 32);
// Unsupported translation format--return 0
return 0;
}
///////////////////////////////////////////////////////////////////////////////
//// Direct3D DeviceSelector Code ///////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//// IGetD3DCardInfo /////////////////////////////////////////////////////////
// Given two enum structs, strips out and produces the vendor ID, device ID
// and the driver name. Returns true if processed, false otherwise.
hsBool hsG3DDeviceSelector::IGetD3DCardInfo( hsG3DDeviceRecord &record, // In
void *driverInfo,
void *deviceInfo,
DWORD *vendorID, DWORD *deviceID, // Out
char **driverString, char **descString )
{
D3DEnum_DriverInfo *driverD3DInfo = (D3DEnum_DriverInfo *)driverInfo;
D3DEnum_DeviceInfo *deviceD3DInfo = (D3DEnum_DeviceInfo *)deviceInfo;
D3DADAPTER_IDENTIFIER9 *adapterInfo;
adapterInfo = &driverD3DInfo->fAdapterInfo;
/// Print out to our demo data file
plDemoDebugFile::Write( "DeviceSelector detected DX Direct3D device. Info:" );
plDemoDebugFile::Write( " Driver Description", (char *)adapterInfo->Description );
plDemoDebugFile::Write( " Driver Name", (char *)adapterInfo->Driver );
plDemoDebugFile::Write( " Vendor ID", (Int32)adapterInfo->VendorId );
plDemoDebugFile::Write( " Device ID", (Int32)adapterInfo->DeviceId );
plDemoDebugFile::Write( " Version", (char *)record.GetDriverVersion() );
plDemoDebugFile::Write( " Memory size (in MB)", record.GetMemoryBytes() / ( 1024 * 1024 ) );
plDemoDebugFile::Write( " Memory size (in bytes)", record.GetMemoryBytes() );
*vendorID = adapterInfo->VendorId;
*deviceID = adapterInfo->DeviceId;
*driverString = adapterInfo->Driver;
*descString = adapterInfo->Description;
return true;
}
//// IInitDirect3D ////////////////////////////////////////////////////////////
hsBool hsG3DDeviceSelector::IInitDirect3D( void )
{
if( hsGDDrawDllLoad::GetD3DDll() == nil )
{
strcpy( fErrorString, "Cannot load Direct3D driver!" );
return false;
}
Direct3DCreateProc procPtr;
procPtr = (Direct3DCreateProc)GetProcAddress( hsGDDrawDllLoad::GetD3DDll(), "Direct3DCreate9" );
if( procPtr == nil )
{
strcpy( fErrorString, "Cannot load D3D Create Proc!" );
return false;
}
// Create a D3D object to use
IDirect3D9 *pD3D = procPtr( D3D_SDK_VERSION );
if( pD3D == nil )
{
strcpy( fErrorString, "Cannot load DirectX!" );
return false;
}
pD3D->Release();
fErrorString[ 0 ] = 0;
return true;
}
//// ITryDirect3DTnL //////////////////////////////////////////////////////////
void hsG3DDeviceSelector::ITryDirect3DTnL(hsWinRef winRef)
{
hsGDirect3DTnLEnumerate d3dEnum;
int i;
for( i = 0; i < d3dEnum.GetNumDrivers(); i++ )
{
ITryDirect3DTnLDriver(d3dEnum.GetDriver(i));
}
}
//// ITryDirect3DDriver ///////////////////////////////////////////////////////
//
// New DirectX Way
void hsG3DDeviceSelector::ITryDirect3DTnLDriver(D3DEnum_DriverInfo* drivInfo)
{
hsG3DDeviceRecord devRec;
devRec.Clear();
devRec.SetG3DDeviceType( kDevTypeDirect3DTnL );
devRec.SetDriverName( drivInfo->fAdapterInfo.Driver );
devRec.SetDriverDesc( drivInfo->fAdapterInfo.Description );
char buff[ 256 ];
sprintf( buff, "%d.%02d.%02d.%04d",
HIWORD( drivInfo->fAdapterInfo.DriverVersion.u.HighPart ),
LOWORD( drivInfo->fAdapterInfo.DriverVersion.u.HighPart ),
HIWORD( drivInfo->fAdapterInfo.DriverVersion.u.LowPart ),
LOWORD( drivInfo->fAdapterInfo.DriverVersion.u.LowPart ) );
devRec.SetDriverVersion(buff);
devRec.SetMemoryBytes(drivInfo->fMemory);
int i;
for( i = 0; i < drivInfo->fDevices.GetCount(); i++ )
{
/// 9.6.2000 mcn - Changed here so we can do fudging here, rather
/// than passing all the messy driver data to the function
hsG3DDeviceRecord currDevRec = devRec;
/// Done first now, so we can alter the D3D type later
ITryDirect3DTnLDevice( &drivInfo->fDevices[i], currDevRec );
/// Check the vendor ID to see if it's 3dfx (#0x121a). If it is, don't add it.
/// (we don't support 3dfx D3D devices) -mcn
/// 11.25.2000 mcn - Knew this was going to come back and bite me. Now we just
/// append (3dfx) to the end of the device description, so that our latter test
/// can throw it out or not, depending on whether we're "strong".
if( drivInfo->fAdapterInfo.VendorId == 0x121a &&
( currDevRec.GetG3DHALorHEL() == hsG3DDeviceSelector::kHHD3DHALDev ||
currDevRec.GetG3DHALorHEL() == hsG3DDeviceSelector::kHHD3DTnLHalDev ) )
{
if( drivInfo->fAdapterInfo.DeviceId >= 0x00000009 )
{
currDevRec.SetG3DHALorHEL( kHHD3D3dfxVoodoo5Dev );
plDemoDebugFile::Write( " Tagging device as a 3dfx Voodoo5 or above" );
}
else
{
currDevRec.SetG3DHALorHEL( kHHD3D3dfxDev );
plDemoDebugFile::Write( " Tagging device as a non-V5 3dfx card" );
}
}
IFudgeDirectXDevice( currDevRec, (D3DEnum_DriverInfo *)drivInfo, (D3DEnum_DeviceInfo *)&drivInfo->fDevices[ i ] );
if( currDevRec.GetModes().GetCount() )
fRecords.Append( currDevRec );
}
}
//// ITryDirect3DTnLDevice ////////////////////////////////////////////////////
//
// New DirectX Way
void hsG3DDeviceSelector::ITryDirect3DTnLDevice(D3DEnum_DeviceInfo* devInfo, hsG3DDeviceRecord& devRec)
{
devRec.SetDeviceDesc(devInfo->fStrName);
if( devInfo->fDDType == D3DDEVTYPE_REF )
devRec.SetG3DHALorHEL( kHHD3DRefDev );
else if( devInfo->fDDType == D3DDEVTYPE_HAL )
{
if( devInfo->fDDCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
devRec.SetG3DHALorHEL( kHHD3DTnLHalDev );
devRec.SetCap( kCapsHWTransform );
}
else
devRec.SetG3DHALorHEL( kHHD3DHALDev );
}
if( devInfo->fDDCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP )
devRec.SetCap( kCapsCubicTextures );
devRec.SetLayersAtOnce( devInfo->fDDCaps.MaxSimultaneousTextures );
if( devInfo->fDDCaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR )
devRec.SetCap( kCapsMipmap );
if( devInfo->fDDCaps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP )
devRec.SetCap( kCapsCubicMipmap );
if( devInfo->fDDCaps.TextureCaps & D3DPTEXTURECAPS_PERSPECTIVE )
devRec.SetCap(kCapsPerspective);
if( devInfo->fIsHardware )
devRec.SetCap( kCapsHardware );
if( devInfo->fDDCaps.RasterCaps & D3DPRASTERCAPS_DITHER )
devRec.SetCap(kCapsDither);
if( devInfo->fDDCaps.RasterCaps & D3DPRASTERCAPS_WBUFFER )
devRec.SetCap(kCapsWBuffer);
if( devInfo->fDDCaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE )
{
devRec.SetCap( kCapsFogLinear );
devRec.SetCap( kCapsFogExp );
devRec.SetCap( kCapsFogExp2 );
devRec.SetCap( kCapsPixelFog );
}
else
{
devRec.SetCap( kCapsFogLinear );
}
if( devInfo->fDDCaps.RasterCaps & D3DPRASTERCAPS_FOGRANGE )
devRec.SetCap( kCapsFogRange );
if( devInfo->fDDCaps.MaxAnisotropy <= 1 )
devRec.SetMaxAnisotropicSamples( 0 );
else
devRec.SetMaxAnisotropicSamples( (UInt8)devInfo->fDDCaps.MaxAnisotropy );
if (D3DSHADER_VERSION_MAJOR(devInfo->fDDCaps.PixelShaderVersion) > 0)
devRec.SetCap(kCapsPixelShader);
/// Assume these by default
devRec.SetCap( kCapsCompressTextures );
devRec.SetCap( kCapsDoesSmallTextures );
#if 1 // mf - want to leave this one off by default
// if( devInfo->fCanAntialias )
// devRec.SetCap( kCapsAntiAlias );
#endif // mf - want to leave this one off by default
hsG3DDeviceMode devMode;
int i, j;
const struct
{
D3DFORMAT fmt; UInt16 depth;
} depths[] = { { D3DFMT_D16, 0x0010 }, { D3DFMT_D24X8, 0x0018 }, { D3DFMT_D32, 0x0020 },
{ D3DFMT_D15S1, 0x010f }, { D3DFMT_D24X4S4, 0x0418 }, { D3DFMT_D24S8, 0x0818 }, { D3DFMT_UNKNOWN, 0 } };
for( i = 0; i < devInfo->fModes.GetCount(); i++ )
{
D3DEnum_ModeInfo* modeInfo = &devInfo->fModes[i];
devMode.Clear();
devMode.SetWidth( modeInfo->fDDmode.Width );
devMode.SetHeight( modeInfo->fDDmode.Height );
devMode.SetColorDepth( modeInfo->fBitDepth );
if( modeInfo->fCanRenderToCubic )
devMode.SetCanRenderToCubics( true );
else
devMode.SetCanRenderToCubics( false );
for( j = 0; depths[ j ].depth != 0; j++ )
{
if( modeInfo->fDepthFormats.Find( depths[ j ].fmt ) != modeInfo->fDepthFormats.kMissingIndex )
devMode.AddZStencilDepth( depths[ j ].depth );
}
for( j = 2; j <= 16; j++ )
{
if( modeInfo->fFSAATypes.Find( (D3DMULTISAMPLE_TYPE)j ) != modeInfo->fFSAATypes.kMissingIndex )
devMode.AddFSAAType( j );
}
devRec.GetModes().Append( devMode );
}
}

View File

@ -0,0 +1,184 @@
/*==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 hsGDirect3DTnLEnumerate_h
#define hsGDirect3DTnLEnumerate_h
#include "hsConfig.h"
#include "hsTemplates.h"
//#include "plMemTrackerOff.h"
#include <d3d9.h>
//#include "plMemTrackerOn.h"
//-----------------------------------------------------------------------------
// Name: D3DEnum_ModeInfo
// Desc: Structure to hold information about a display mode. This
// info is stored as a width, height, bpp, and pixelformat within a
// DDSURFACEDESC2.
//-----------------------------------------------------------------------------
struct D3DEnum_ModeInfo
{
D3DDISPLAYMODE fDDmode;
CHAR fStrDesc[40];
BOOL fWindowed;
char fBitDepth;
DWORD fDDBehavior;
hsTArray<D3DFORMAT> fDepthFormats;
hsTArray<D3DMULTISAMPLE_TYPE> fFSAATypes;
BOOL fCanRenderToCubic;
};
//-----------------------------------------------------------------------------
// Name: D3DEnum_DeviceInfo
// Desc: Linked-list structure to hold information about a Direct3D device. The
// primary information recorded here is the D3DDEVICEDESC and a ptr to a
// list of valid display modes.
//-----------------------------------------------------------------------------
struct D3DEnum_DeviceInfo
{
D3DDEVTYPE fDDType;
CHAR fStrName[40];
D3DCAPS9 fDDCaps;
BOOL fCanWindow;
BOOL fCompatibleWithDesktop;
BOOL fIsHardware;
hsTArray<D3DEnum_ModeInfo> fModes;
};
//-----------------------------------------------------------------------------
// Name: D3DEnum_DriverInfo
// Desc: Linked-list structure to hold information about a DirectX driver. The
// info stored is the capability bits for the driver plus a list
// of valid Direct3D devices for the driver. Note: most systems will only
// have one driver. The exception are multi-monitor systems, and systems
// with non-GDI 3D video cards.
//-----------------------------------------------------------------------------
struct D3DEnum_DriverInfo
{
GUID fGuid;
CHAR fStrDesc[40];
CHAR fStrName[40];
unsigned int fMemory;
D3DADAPTER_IDENTIFIER9 fAdapterInfo;
D3DDISPLAYMODE fDesktopMode;
hsTArray<D3DEnum_ModeInfo> fModes;
D3DEnum_ModeInfo* fCurrentMode;
hsTArray<D3DEnum_DeviceInfo> fDevices;
D3DEnum_DeviceInfo* fCurrentDevice;
};
class hsG3DDeviceRecord;
class hsG3DDeviceMode;
class hsGDirect3DTnLEnumerate
{
protected:
HMODULE fDDrawDLL;
char fEnumeErrorStr[128]; // <20>h<EFBFBD><68><EFBFBD>C<EFBFBD>o<EFBFBD>A<EFBFBD>f<EFBFBD>o<EFBFBD>C<EFBFBD>X<EFBFBD>񋓃G<F18B9383><47><EFBFBD>[<5B><><EFBFBD>b<EFBFBD>Z<EFBFBD>[<5B>W<EFBFBD>i<EFBFBD>[<5B>o<EFBFBD>b<EFBFBD>t<EFBFBD>@
hsTArray<D3DEnum_DriverInfo> fDrivers;
D3DEnum_DriverInfo* fCurrentDriver; // The selected DD driver
static short IGetDXBitDepth( D3DFORMAT format );
/// DirectX Helper Functions
void IEnumAdapterDevices( IDirect3D9 *pD3D, UINT iAdapter, D3DEnum_DriverInfo *drivInfo );
hsBool IFindDepthFormats( IDirect3D9 *pD3D, UINT iAdapter, D3DDEVTYPE deviceType, D3DEnum_ModeInfo *modeInfo );
hsBool IFindFSAATypes( IDirect3D9 *pD3D, UINT iAdapter, D3DDEVTYPE deviceType, D3DEnum_ModeInfo *modeInfo );
hsBool ICheckCubicRenderTargets( IDirect3D9 *pD3D, UINT iAdapter, D3DDEVTYPE deviceType, D3DEnum_ModeInfo *modeInfo );
HRESULT IConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior, D3DFORMAT format );
static const UInt8 kNumDisplayFormats;
static const D3DFORMAT kDisplayFormats[];
public:
hsGDirect3DTnLEnumerate();
virtual ~hsGDirect3DTnLEnumerate();
VOID D3DEnum_FreeResources();
char* GetErrorString() { return (fEnumeErrorStr[0] ? fEnumeErrorStr : nil); }
HRESULT SelectFromDevMode(const hsG3DDeviceRecord* devRec, const hsG3DDeviceMode* devMode);
HRESULT D3DEnum_SelectDefaultMode(int width, int height, int depth);
HRESULT D3DEnum_SelectDefaultDriver( DWORD dwFlags );
UInt32 GetNumDrivers() { return fDrivers.GetCount(); }
D3DEnum_DriverInfo* GetDriver(int i) { return &fDrivers[i]; }
D3DEnum_DriverInfo* GetCurrentDriver() { return fCurrentDriver; }
D3DEnum_DeviceInfo* GetCurrentDevice() { return GetCurrentDriver() ? GetCurrentDriver()->fCurrentDevice : nil; }
D3DEnum_ModeInfo* GetCurrentMode() { return GetCurrentDevice() ? GetCurrentDriver()->fCurrentMode : nil; }
void SetCurrentDriver(D3DEnum_DriverInfo* d) { fCurrentDriver = d; }
void SetCurrentDevice(D3DEnum_DeviceInfo* d) { hsAssert(GetCurrentDriver(), "Set Driver first"); GetCurrentDriver()->fCurrentDevice = d; }
void SetCurrentMode(D3DEnum_ModeInfo* m) { hsAssert(GetCurrentDriver(), "Set Driver first"); GetCurrentDriver()->fCurrentMode = m; }
char* GetEnumeErrorStr() { return fEnumeErrorStr; }
void SetEnumeErrorStr(const char* s);
};
//-----------------------------------------------------------------------------
// Name: D3DEnum_SelectDefaultDriver()
// Desc: Picks a driver based on a set of passed in criteria.
//-----------------------------------------------------------------------------
#define D3DENUM_SOFTWAREONLY 0x00000001
#define D3DENUM_FULLSCREENONLY 0x00000002
#define D3DENUM_RGBEMULATION 0x00000004
#define D3DENUM_REFERENCERAST 0x00000008
#define D3DENUM_PRIMARYHAL 0x00000010
#define D3DENUM_SECONDARYHAL 0x00000020
#define D3DENUM_TNLHAL 0x00000040
#define D3DENUM_CANWINDOW 0x00000080
#define D3DENUM_MASK 0x000000ff
//-----------------------------------------------------------------------------
// Error codes
//-----------------------------------------------------------------------------
#define D3DENUMERR_ENUMERATIONFAILED 0x81000001 // Enumeration failed
#define D3DENUMERR_SUGGESTREFRAST 0x81000002 // Suggest using the RefRast
#define D3DENUMERR_NOCOMPATIBLEDEVICES 0x81000003 // No devices were found that
// meet the app's desired
// capabilities
#define D3DENUMERR_NODIRECTDRAW 0x81000004 // DDraw couldn't initialize
#define D3DENUMERR_NOTFOUND 0x81000005 // Requested device not found
#endif //hsGDirect3DTnLEnumerate_h

View File

@ -0,0 +1,81 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDXLightRef.h - Hardware Light DeviceRef Definition //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 4.25.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDXLightRef_h
#define _plDXLightRef_h
#include "hsMatrix44.h"
#include "hsGeometry3.h"
#include "hsTemplates.h"
#include "plDXDeviceRef.h"
//// Definition ///////////////////////////////////////////////////////////////
class plLightInfo;
class plDXLightSettings;
class plDXLightRef : public plDXDeviceRef
{
public:
plLightInfo *fOwner;
D3DLIGHT9 fD3DInfo;
UInt32 fD3DIndex;
hsScalar fScale;
plDXLightSettings *fParentSettings;
IDirect3DDevice9 *fD3DDevice;
void Link( plDXLightRef **back ) { plDXDeviceRef::Link( (plDXDeviceRef **)back ); }
plDXLightRef *GetNext( void ) { return (plDXLightRef *)fNext; }
plDXLightRef()
{
fOwner = nil;
fParentSettings = nil;
fD3DDevice = nil;
fD3DIndex = -1;
fScale = 1.f;
}
virtual ~plDXLightRef();
void Release( void );
void UpdateD3DInfo( IDirect3DDevice9 *dev, plDXLightSettings *settings );
};
#endif // _plDXLightRef_h

View File

@ -0,0 +1,818 @@
/*==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 _plDX9Pipeline_h
#define _plDX9Pipeline_h
#include "plPipeline.h"
#include "plDXSettings.h"
#include "../plSurface/plLayerInterface.h"
#include "hsMatrix44.h"
#include "plFogEnvironment.h"
#include "hsG3DDeviceSelector.h"
#include "hsGeometry3.h"
#include "hsTemplates.h"
#include "hsColorRGBA.h"
#include "hsGDeviceRef.h"
#include "hsPoint2.h"
class plAccessSpan;
class plAuxSpan;
class plVertexSpan;
#include "plPlates.h" // Used to define plDXPlateManager
//// Defines and Konstants and Other Nifty Stuff //////////////////////////////
class plDXLightRef;
class plDXVertexBufferRef;
class plDXIndexBufferRef;
class plDXTextureRef;
class plDXCubeTextureRef;
class plDXVertexShader;
class plDXPixelShader;
class plShader;
class plVisMgr;
//#define HS_D3D_USE_SPECULAR
class hsGMaterial;
class plMipmap;
class plLightInfo;
class plCullTree;
class plShadowSlave;
class plShadowCaster;
struct D3DXMATRIX;
#ifdef HS_DEBUGGING
#define HS_CHECK_RELEASE
#endif
#ifndef PLASMA_EXTERNAL_RELEASE
#define PROFILE_POOL_MEM(pool, size, add, id) plDXPipeline::ProfilePoolMem(pool, size, add, id);
#else
#define PROFILE_POOL_MEM(pool, size, add, id)
#endif // PLASMA_EXTERNAL_RELEASE
extern void D3DSURF_MEMNEW(IDirect3DSurface9* surf);
extern void D3DSURF_MEMNEW(IDirect3DTexture9* tex);
extern void D3DSURF_MEMNEW(IDirect3DCubeTexture9* cTex);
extern void D3DSURF_MEMDEL(IDirect3DSurface9* surf);
extern void D3DSURF_MEMDEL(IDirect3DTexture9* tex);
extern void D3DSURF_MEMDEL(IDirect3DCubeTexture9* cTex);
extern void plReleaseObject(IUnknown* x);
#define ReleaseObject(x) if(x){ plReleaseObject(x); x=NULL; }
typedef LPDIRECT3D9 (WINAPI * Direct3DCreateProc)( UINT sdkVersion );
//// Helper Classes ///////////////////////////////////////////////////////////
//// The RenderPrimFunc lets you have one function which does a lot of stuff
// around the actual call to render whatever type of primitives you have, instead
// of duplicating everything because the one line to render is different.
class plRenderPrimFunc
{
public:
virtual hsBool RenderPrims() const = 0; // return true on error
};
//// DX-specific Plate Manager implementation
class plDXPlateManager : public plPlateManager
{
friend class plDXPipeline;
public:
virtual ~plDXPlateManager();
protected:
const long PLD3D_PLATEFVF;
struct plPlateVertex
{
hsPoint3 fPoint;
UInt32 fColor;
hsPoint3 fUV;
};
IDirect3DDevice9 *fD3DDevice;
IDirect3DVertexBuffer9 *fVertBuffer;
plDXPlateManager( plDXPipeline *pipe, IDirect3DDevice9 *device );
void ICreateGeometry(plDXPipeline* pipe);
void IReleaseGeometry();
virtual void IDrawToDevice( plPipeline *pipe );
};
//// Class Definition /////////////////////////////////////////////////////////
class plDebugTextManager;
struct D3DEnum_DriverInfo;
struct D3DEnum_DeviceInfo;
struct D3DEnum_ModeInfo;
class plGeometrySpan;
class plDrawableSpans;
class plSpan;
class plIcicle;
class hsG3DDeviceModeRecord;
class plDXDeviceRef;
class plParticleSpan;
class plCubicEnvironmap;
class plDXRenderTargetRef;
class plStatusLogDrawer;
class plBinkPlayer;
class plDXPipeline : public plPipeline
{
protected:
enum {
kCapsNone = 0x0,
kCapsCompressTextures = 0x1,
kCapsMipmap = 0x2,
kCapsHWTransform = 0x4,
kCapsHWLighting = 0x8,
kCapsZBias = 0x10,
kCapsLinearFog = 0x20,
kCapsExpFog = 0x40,
kCapsExp2Fog = 0x80,
kCapsRangeFog = 0x100,
kCapsWBuffer = 0x200,
kCapsTexBoundToStage = 0x400,
kCapsDither = 0x800,
kCapsLODWatch = 0x1000,
kCapsFSAntiAlias = 0x2000,
kCapsLuminanceTextures = 0x4000,
kCapsDoesSmallTextures = 0x8000,
kCapsDoesWFog = 0x10000,
kCapsPixelFog = 0x20000,
kCapsHasBadYonStuff = 0x40000,
kCapsNoKindaSmallTexs = 0x80000,
kCapsCubicTextures = 0x200000,
kCapsCubicMipmap = 0x400000
};
enum {
kKNone = 0x0,
kKTNT = 0x1
};
plDebugTextManager* fDebugTextMgr;
plDXPlateManager* fPlateMgr;
// The main D3D interfaces
LPDIRECT3D9 fD3DObject; // The main D3D object
LPDIRECT3DDEVICE9 fD3DDevice; // The D3D rendering device
IDirect3DSurface9* fD3DMainSurface;
IDirect3DSurface9* fD3DDepthSurface;
IDirect3DSurface9* fD3DBackBuff;
IDirect3DSurface9* fSharedDepthSurface[2];
D3DFORMAT fSharedDepthFormat[2];
// Dynamic buffers
UInt32 fVtxRefTime;
UInt32 fNextDynVtx;
UInt32 fDynVtxSize;
IDirect3DVertexBuffer9* fDynVtxBuff;
hsBool fManagedAlloced;
hsBool fAllocUnManaged;
// States
plDXGeneralSettings fSettings;
plDXTweakSettings fTweaks;
plDXStencilSettings fStencil;
hsBool fDeviceLost;
hsBool fDevWasLost;
hsTArray<const plCullPoly*> fCullPolys;
hsTArray<const plCullPoly*> fCullHoles;
plDrawableSpans* fCullProxy;
plDXVertexBufferRef* fVtxBuffRefList;
plDXIndexBufferRef* fIdxBuffRefList;
plDXTextureRef* fTextureRefList;
plTextFont* fTextFontRefList;
plDXRenderTargetRef* fRenderTargetRefList;
plDXVertexShader* fVShaderRefList;
plDXPixelShader* fPShaderRefList;
hsGMaterial* fCurrMaterial;
plLayerInterface* fCurrLay;
UInt32 fCurrLayerIdx, fCurrNumLayers, fCurrRenderLayer;
UInt32 fCurrLightingMethod; // Based on plSpan flags
D3DCULL fCurrCullMode;
hsGMatState fMatOverOn;
hsGMatState fMatOverOff;
hsTArray<hsGMaterial*> fOverrideMat;
hsGMaterial* fHoldMat;
hsBool fCurrD3DLiteState;
hsMatrix44 fBumpDuMatrix;
hsMatrix44 fBumpDvMatrix;
hsMatrix44 fBumpDwMatrix;
hsTArray<plLayerInterface*> fOverLayerStack;
plLayerInterface* fOverBaseLayer;
plLayerInterface* fOverAllLayer;
hsTArray<plLayerInterface*> fPiggyBackStack;
Int32 fMatPiggyBacks;
Int32 fActivePiggyBacks;
UINT fCurrentAdapter;
D3DEnum_DriverInfo* fCurrentDriver;
D3DEnum_DeviceInfo* fCurrentDevice;
D3DEnum_ModeInfo* fCurrentMode;
hsGDeviceRef* fLayerRef[ 8 ];
hsGMatState fLayerState[ 8 ]; // base stage (0) state is held in base class
hsGMatState fOldLayerState[ 8 ];
hsBool fLayerTransform[ 8 ];
float fLayerLODBias[ 8 ];
UInt32 fLayerUVWSrcs[ 8 ];
UInt32 fLayerXformFlags[ 8 ];
UInt32 fLastEndingStage;
hsBool fTexturing;
hsBool fForceMatHandle;
UInt32 fInSceneDepth;
UInt32 fTextUseTime; // inc'd every frame - stat gather only
static UInt32 fTexManaged;
static UInt32 fTexUsed;
static UInt32 fVtxManaged;
static UInt32 fVtxUsed;
UInt32 fEvictTime;
UInt32 fManagedSeen;
UInt32 fManagedCutoff;
double fTime; // World time.
UInt32 fFrame; // inc'd every time the camera moves.
UInt32 fRenderCnt; // inc'd every begin scene.
// View stuff
plDXViewSettings fView;
hsBitVector fDebugFlags;
UInt32 fDebugSpanGraphY;
// Fog
plDXFogSettings fCurrFog;
// Light
plDXLightSettings fLights;
// Shadows
hsTArray<plShadowSlave*> fShadows;
hsTArray<plRenderTarget*> fRenderTargetPool512;
hsTArray<plRenderTarget*> fRenderTargetPool256;
hsTArray<plRenderTarget*> fRenderTargetPool128;
hsTArray<plRenderTarget*> fRenderTargetPool64;
hsTArray<plRenderTarget*> fRenderTargetPool32;
enum { kMaxRenderTargetNext = 10 };
UInt32 fRenderTargetNext[kMaxRenderTargetNext];
plDXTextureRef* fULutTextureRef;
plRenderTarget* fBlurScratchRTs[kMaxRenderTargetNext];
plRenderTarget* fBlurDestRTs[kMaxRenderTargetNext];
IDirect3DVertexBuffer9* fBlurVBuffers[kMaxRenderTargetNext];
UInt32 fBlurVSHandle;
hsTArray<plClothingOutfit*> fClothingOutfits;
hsTArray<plClothingOutfit*> fPrevClothingOutfits;
// Debug stuff
plDrawableSpans *fBoundsSpans;
hsGMaterial *fBoundsMat;
hsTArray<UInt32> fBSpansToDelete;
plStatusLogDrawer *fLogDrawer;
hsBool fVSync;
hsBool fForceDeviceReset;
void IBeginAllocUnManaged();
void IEndAllocUnManaged();
void ICheckTextureUsage();
void ICheckVtxUsage();
inline void ICheckVBUsage(plDXVertexBufferRef* vRef);
hsBool IRefreshDynVertices(plGBufferGroup* group, plDXVertexBufferRef* vRef);
hsBool ICheckAuxBuffers(const plAuxSpan* span);
hsBool ICheckDynBuffers(plDrawableSpans* drawable, plGBufferGroup* group, const plSpan* span);
void ICheckStaticVertexBuffer(plDXVertexBufferRef* vRef, plGBufferGroup* owner, UInt32 idx);
void ICheckIndexBuffer(plDXIndexBufferRef* iRef);
void IFillStaticVertexBufferRef(plDXVertexBufferRef *ref, plGBufferGroup *group, UInt32 idx);
void IFillIndexBufferRef(plDXIndexBufferRef* iRef, plGBufferGroup* owner, UInt32 idx);
void ISetupVertexBufferRef(plGBufferGroup* owner, UInt32 idx, plDXVertexBufferRef* vRef);
void ISetupIndexBufferRef(plGBufferGroup* owner, UInt32 idx, plDXIndexBufferRef* iRef);
void ICreateDynamicBuffers();
void IReleaseDynamicBuffers();
void IAddBoundsSpan( plDrawableSpans *ice, const hsBounds3Ext *bounds, UInt32 bndColor = 0xffff0000 );
void IAddNormalsSpan( plDrawableSpans *ice, plIcicle *span, plDXVertexBufferRef *vRef, UInt32 bndColor );
// Rendering
hsBool IFlipSurface();
long IGetBufferD3DFormat(UInt8 format) const;
UInt32 IGetBufferFormatSize(UInt8 format) const;
void IGetVisibleSpans( plDrawableSpans* drawable, hsTArray<Int16>& visList, plVisMgr* visMgr );
void IRenderSpans( plDrawableSpans *ice, const hsTArray<Int16>& visList );
hsBool ILoopOverLayers(const plRenderPrimFunc& render, hsGMaterial* material, const plSpan& span);
void IRenderBufferSpan( const plIcicle& span,
hsGDeviceRef *vb, hsGDeviceRef *ib,
hsGMaterial *material,
UInt32 vStart, UInt32 vLength, UInt32 iStart, UInt32 iLength );
void IRenderAuxSpan(const plSpan& span, const plAuxSpan* aux);
void IRenderAuxSpans(const plSpan& span);
// Fog
void IGetVSFogSet(float* const set) const;
void ISetFogParameters(const plSpan* span, const plLayerInterface* baseLay);
// Lighting
hsGDeviceRef *IMakeLightRef( plLightInfo *owner );
void IScaleD3DLight( plDXLightRef *ref, hsScalar scale);
void ICalcLighting( const plLayerInterface *currLayer, const plSpan *currSpan );
void IDisableSpanLights();
void IRestoreSpanLights();
void ISelectLights( plSpan *span, int numLights, hsBool proj );
void IEnableLights( plSpan *span );
void IMakeLightLists(plVisMgr* visMgr);
void ICheckLighting(plDrawableSpans* drawable, hsTArray<Int16>& visList, plVisMgr* visMgr);
inline void inlEnsureLightingOff();
inline void inlEnsureLightingOn();
void IRenderProjection(const plRenderPrimFunc& render, plLightInfo* li);
void IRenderProjections(const plRenderPrimFunc& render);
void IRenderProjectionEach(const plRenderPrimFunc& render, hsGMaterial* material, int iPass, const plSpan& span);
void IRenderOverWire(const plRenderPrimFunc& render, hsGMaterial* material, const plSpan& span);
hsBool ISkipBumpMap(hsGMaterial* newMat, UInt32& layer, const plSpan* currSpan) const;
void ISetBumpMatrices(const plLayerInterface* layer, const plSpan* span);
const hsMatrix44& IGetBumpMatrix(UInt32 miscFlags) const;
// Materials
const hsGMatState& ICompositeLayerState(int which, plLayerInterface* layer);
Int32 IHandleMaterial(hsGMaterial* newMat, UInt32 which, const plSpan* currSpan);
void IHandleFirstTextureStage( plLayerInterface* layer );
void IHandleShadeMode();
void IHandleZMode();
void IHandleMiscMode();
void IHandleTextureStage(UInt32 stage, plLayerInterface* layer);
void IHandleFirstStageBlend();
void IHandleBumpEnv(int stage, UInt32 blendFlags);
void IHandleStageBlend(int stage);
void IHandleStageClamp(int stage);
void IHandleStageTransform(int stage, plLayerInterface* layer);
void IHandleTextureMode(plLayerInterface* layer);
void IUseTextureRef(int stage, hsGDeviceRef* dRef, plLayerInterface* layer);
void IStageStop(UInt32 stage);
UInt32 ILayersAtOnce(hsGMaterial* mat, UInt32 which);
hsBool ICanEatLayer(plLayerInterface* lay);
void ISetLayer(UInt32 lay);
void IBottomLayer();
// Push special effects
plLayerInterface* IPushOverBaseLayer(plLayerInterface* li);
plLayerInterface* IPopOverBaseLayer(plLayerInterface* li);
plLayerInterface* IPushOverAllLayer(plLayerInterface* li);
plLayerInterface* IPopOverAllLayer(plLayerInterface* li);
int ISetNumActivePiggyBacks();
void IPushPiggyBacks(hsGMaterial* mat);
void IPopPiggyBacks();
void IPushProjPiggyBack(plLayerInterface* li);
void IPopProjPiggyBacks();
void ISetPipeConsts(plShader* shader);
HRESULT ISetShaders(plShader* vShader, plShader* pShader);
// Stenciling
virtual hsBool StencilEnable( hsBool enable );
virtual void StencilSetCompareFunc( UInt8 func, UInt32 refValue );
virtual void StencilSetMask( UInt32 mask, UInt32 writeMask );
virtual void StencilSetOps( UInt8 passOp, UInt8 failOp, UInt8 passButZFailOp );
virtual hsBool StencilGetCaps( plStencilCaps *caps );
hsGDeviceRef *MakeTextureRef( plLayerInterface* layer, plMipmap *b );
void IReloadTexture( plDXTextureRef *ref );
void IFillD3DTexture( plDXTextureRef *ref );
void IFillD3DCubeTexture( plDXCubeTextureRef *ref );
void IGetD3DTextureFormat( plBitmap *b, D3DFORMAT &formatType, UInt32& texSize );
void IFormatTextureData( UInt32 formatType, UInt32 numPix, hsRGBAColor32* const src, void *dst );
void *IGetPixelScratch( UInt32 size );
hsGDeviceRef *IMakeCubicTextureRef( plLayerInterface* layer, plCubicEnvironmap *cubic );
hsBool IProcessMipmapLevels( plMipmap *mipmap, UInt32 &numLevels,
UInt32 *&levelSizes, UInt32 &totalSize,
UInt32 &numPixels, void *&textureData, hsBool noMip );
IDirect3DTexture9 *IMakeD3DTexture( plDXTextureRef *ref, D3DFORMAT formatType );
IDirect3DCubeTexture9 *IMakeD3DCubeTexture( plDXTextureRef *ref, D3DFORMAT formatType );
// Visualization of active occluders
void IMakeOcclusionSnap();
hsBool IAvatarSort(plDrawableSpans* d, const hsTArray<Int16>& visList);
void IBlendVertsIntoBuffer( plSpan* span,
hsMatrix44* matrixPalette, int numMatrices,
UInt8 *src, UInt8 format, UInt32 srcStride,
UInt8 *dest, UInt32 destStride, UInt32 count, UInt16 localUVWChans );
hsBool ISoftwareVertexBlend( plDrawableSpans* drawable, const hsTArray<Int16>& visList );
void ILinkDevRef( plDXDeviceRef *ref, plDXDeviceRef **refList );
void IUnlinkDevRef( plDXDeviceRef *ref );
// Properties
inline DWORD inlGetD3DColor( const hsColorRGBA &c ) const;
inline D3DCOLORVALUE inlPlToD3DColor(const hsColorRGBA& c, float a) const;
// Error handling
void IAddErrorMessage( char *errStr );
void ISetErrorMessage( char *errStr = nil );
void IGetD3DError();
void IShowErrorMessage( char *errStr = nil );
hsBool ICreateFail( char *errStr );
// FPU mode check
void IFPUCheck();
// Device initialization
void IInvalidateState();
void IInitDeviceState();
void IClearMembers();
void ISetCaps();
void IRestrictCaps( const hsG3DDeviceRecord& devRec );
void ISetGraphicsCapability(UInt32 v);
hsBool IFindDepthFormat(D3DPRESENT_PARAMETERS& params);
hsBool IFindCompressedFormats();
hsBool IFindLuminanceFormats();
hsBool ITextureFormatAllowed( D3DFORMAT format );
void ISetCurrentDriver( D3DEnum_DriverInfo *driv );
void ISetCurrentDevice( D3DEnum_DeviceInfo *dev );
void ISetCurrentMode( D3DEnum_ModeInfo *mode );
hsBool ICreateMaster();
hsBool ICreateDevice(hsBool windowed);
hsBool ICreateNormalSurfaces();
hsBool ICreateDeviceObjects();
void IReleaseDeviceObjects();
hsBool ICreateDynDeviceObjects();
void IReleaseDynDeviceObjects();
void IReleaseShaders();
hsBool IResetDevice();
// View and clipping
void ISetViewport();
void IUpdateViewVectors() const;
void IRefreshCullTree();
void ISetAnisotropy(hsBool on);
// Transforms
D3DXMATRIX& IMatrix44ToD3DMatrix( D3DXMATRIX& dst, const hsMatrix44& src );
void ITransformsToD3D();
hsMatrix44 IGetCameraToNDC();
void IProjectionMatrixToD3D();
void IWorldToCameraToD3D();
void ILocalToWorldToD3D();
void ISavageYonHack();
void ISetLocalToWorld( const hsMatrix44& l2w, const hsMatrix44& w2l );
void ISetCullMode(hsBool flip=false);
hsBool inline IIsViewLeftHanded();
hsBool IGetClearViewPort(D3DRECT& r);
plViewTransform& IGetViewTransform() { return fView.fTransform; }
void IUpdateViewFlags();
void ISetupTransforms(plDrawableSpans* drawable, const plSpan& span, hsMatrix44& lastL2W);
// Plate management
friend plDXPlateManager;
friend plBinkPlayer;
void IDrawPlate( plPlate *plate );
void ISetRenderTarget( plRenderTarget *target );
hsBool IPrepRenderTargetInfo( plRenderTarget *owner, D3DFORMAT &surfFormat,
D3DFORMAT &depthFormat, D3DRESOURCETYPE &resType );
hsBool IFindRenderTargetInfo( plRenderTarget *owner, D3DFORMAT &surfFormat, D3DRESOURCETYPE &resType );
// From a D3DFORMAT enumeration, return the string literal for it
static const char *IGetDXFormatName( D3DFORMAT format );
/////// Shadow internals
// Generation
void IClearShadowSlaves();
void IPreprocessShadows();
hsBool IPrepShadowCaster(const plShadowCaster* caster);
void IRenderShadowCasterSpan(plShadowSlave* slave, plDrawableSpans* drawable, const plIcicle& span);
void ISetupShadowCastTextureStages(plShadowSlave* slave);
hsBool IRenderShadowCaster(plShadowSlave* slave);
void ISetupShadowLight(plShadowSlave* slave);
plDXLightRef* INextShadowLight(plShadowSlave* slave);
hsBool IPushShadowCastState(plShadowSlave* slave);
hsBool IPopShadowCastState(plShadowSlave* slave);
plDXTextureRef* IGetULutTextureRef();
hsBool ICreateBlurVBuffers();
void IReleaseBlurVBuffers();
void IMakeRenderTargetPools();
void IResetRenderTargetPools();
plRenderTarget* IFindRenderTarget(UInt32& w, UInt32& h, hsBool ortho);
void IReleaseRenderTargetPools();
// Selection
void IAttachSlaveToReceivers(int iSlave, plDrawableSpans* drawable, const hsTArray<Int16>& visList);
void IAttachShadowsToReceivers(plDrawableSpans* drawable, const hsTArray<Int16>& visList);
hsBool IAcceptsShadow(const plSpan* span, plShadowSlave* slave);
hsBool IReceivesShadows(const plSpan* span, hsGMaterial* mat);
void ISetShadowFromGroup(plDrawableSpans* drawable, const plSpan* span, plLightInfo* liInfo);
// Application
void IRenderShadowsOntoSpan(const plRenderPrimFunc& render, const plSpan* span, hsGMaterial* mat);
void ISetupShadowRcvTextureStages(hsGMaterial* mat);
void ISetShadowLightState(hsGMaterial* mat);
void IDisableLightsForShadow();
void IEnableShadowLight(plShadowSlave* slave);
void ISetupShadowSlaveTextures(plShadowSlave* slave);
// Postprocess (blurring)
hsBool ISetBlurQuadToRender(plRenderTarget* smap);
void IRenderBlurBackToShadowMap(plRenderTarget* smap, plRenderTarget* scratch, plRenderTarget* dst);
void IRenderBlurFromShadowMap(plRenderTarget* scratchRT, plRenderTarget* smap, hsScalar scale);
void IBlurSetRenderTarget(plRenderTarget* rt);
int IGetScratchRenderTarget(plRenderTarget* smap);
void IBlurShadowMap(plShadowSlave* slave);
// Avatar Texture Rendering
double fAvRTShrinkValidSince;
hsTArray<plRenderTarget*> fAvRTPool;
UInt16 fAvRTWidth;
UInt32 fAvNextFreeRT;
void IFillAvRTPool();
hsBool IFillAvRTPool(UInt16 numRTs, UInt16 width); // Returns true if we successfully filled the pool. Otherwise cleans up.
void IReleaseAvRTPool();
plRenderTarget* IGetNextAvRT();
void IFreeAvRT(plRenderTarget* tex);
void IPreprocessAvatarTextures();
void IDrawClothingQuad(hsScalar x, hsScalar y, hsScalar w, hsScalar h, hsScalar uOff, hsScalar vOff, plMipmap *tex);
void IClearClothingOutfits(hsTArray<plClothingOutfit*>* outfits);
void IPrintDeviceInitError();
void IResetToDefaults(D3DPRESENT_PARAMETERS *params);
public:
plDXPipeline( hsWinRef hWnd, const hsG3DDeviceModeRecord *devMode );
virtual ~plDXPipeline();
CLASSNAME_REGISTER( plDXPipeline );
GETINTERFACE_ANY( plDXPipeline, plPipeline );
virtual IDirect3DDevice9* GetD3DDevice() const { return fD3DDevice; }
// Typical 3D device
virtual hsBool PreRender(plDrawable* drawable, hsTArray<Int16>& visList, plVisMgr* visMgr=nil);
virtual hsBool PrepForRender(plDrawable* drawable, hsTArray<Int16>& visList, plVisMgr* visMgr=nil);
virtual void Render(plDrawable* d, const hsTArray<Int16>& visList);
virtual void Draw(plDrawable* d);
virtual void PushRenderRequest(plRenderRequest* req);
virtual void PopRenderRequest(plRenderRequest* req);
void ResetDisplayDevice(int Width, int Height, int ColorDepth, hsBool Windowed, int NumAASamples, int MaxAnisotropicSamples, hsBool VSync = false );
virtual void ClearRenderTarget( plDrawable* d );
virtual void ClearRenderTarget( const hsColorRGBA* col = nil, const hsScalar* depth = nil );
virtual void SetClear(const hsColorRGBA* col=nil, const hsScalar* depth=nil);
virtual hsColorRGBA GetClearColor() const;
virtual hsScalar GetClearDepth() const;
virtual hsGDeviceRef* MakeRenderTargetRef( plRenderTarget *owner );
virtual hsGDeviceRef* SharedRenderTargetRef(plRenderTarget* sharer, plRenderTarget *owner);
virtual void PushRenderTarget( plRenderTarget *target );
virtual plRenderTarget* PopRenderTarget();
virtual hsBool BeginRender();
virtual hsBool EndRender();
virtual void RenderScreenElements();
virtual hsBool BeginDrawable(plDrawable* d);
virtual hsBool EndDrawable(plDrawable* d);
virtual void BeginVisMgr(plVisMgr* visMgr);
virtual void EndVisMgr(plVisMgr* visMgr);
virtual hsBool IsFullScreen() const { return fSettings.fFullscreen; }
virtual UInt32 Width() const { return fView.fTransform.GetViewPortWidth(); }
virtual UInt32 Height() const { return fView.fTransform.GetViewPortHeight(); }
virtual UInt32 ColorDepth() const { return fSettings.fColorDepth; }
virtual void Resize( UInt32 width, UInt32 height );
// Culling. Might be used in Update before bothering to do any serious computation.
virtual hsBool TestVisibleWorld(const hsBounds3Ext& wBnd);
virtual hsBool TestVisibleWorld(const plSceneObject* sObj);
virtual hsBool HarvestVisible(plSpaceTree* space, hsTArray<Int16>& visList);
virtual hsBool SubmitOccluders(const hsTArray<const plCullPoly*>& polyList);
// Debug flags
virtual void SetDebugFlag( UInt32 flag, hsBool on );
virtual hsBool IsDebugFlagSet( UInt32 flag ) const;
// These are also only for debugging.
virtual void SetMaxCullNodes(UInt16 n) { fView.fCullMaxNodes = n; }
virtual UInt16 GetMaxCullNodes() const { return fView.fCullMaxNodes; }
virtual hsBool CheckResources();
virtual void LoadResources(); // Tells us where it's a good time to load in unmanaged resources.
// Properties
virtual void SetProperty( UInt32 prop, hsBool on ) { on ? fSettings.fProperties |= prop : fSettings.fProperties &= ~prop; }
virtual hsBool GetProperty( UInt32 prop ) const { return ( fSettings.fProperties & prop ) ? true : false; }
virtual UInt32 GetMaxLayersAtOnce() const { return fSettings.fMaxLayersAtOnce; }
// Drawable type mask
virtual void SetDrawableTypeMask( UInt32 mask ) { fView.fDrawableTypeMask = mask; }
virtual UInt32 GetDrawableTypeMask() const { return fView.fDrawableTypeMask; }
virtual void SetSubDrawableTypeMask( UInt32 mask ) { fView.fSubDrawableTypeMask = mask; }
virtual UInt32 GetSubDrawableTypeMask() const { return fView.fSubDrawableTypeMask; }
// Create a debug text font object
virtual plTextFont *MakeTextFont( char *face, UInt16 size );
// Create and/or Refresh geometry buffers
virtual void CheckVertexBufferRef(plGBufferGroup* owner, UInt32 idx);
virtual void CheckIndexBufferRef(plGBufferGroup* owner, UInt32 idx);
virtual hsBool OpenAccess(plAccessSpan& dst, plDrawableSpans* d, const plVertexSpan* span, hsBool readOnly);
virtual hsBool CloseAccess(plAccessSpan& acc);
virtual void CheckTextureRef(plLayerInterface* lay);
static void FreeManagedTexture(UInt32 sz) { hsAssert(fTexManaged >= sz, "Freeing mem we don't have"); fTexManaged -= sz; }
static void AllocManagedTexture(UInt32 sz) { fTexManaged += sz; }
static void FreeManagedVertex(UInt32 sz) { hsAssert(fVtxManaged >= sz, "Freeing mem we don't have"); fVtxManaged -= sz; }
static void AllocManagedVertex(UInt32 sz) { fVtxManaged += sz; }
#ifndef PLASMA_EXTERNAL_RELEASE
static void ProfilePoolMem(D3DPOOL poolType, UInt32 size, hsBool add, char *id);
#endif // PLASMA_EXTERNAL_RELEASE
// From a D3DFORMAT enumeration, return the bit depth associated with it.
static short GetDXBitDepth( D3DFORMAT format );
// Default fog settings
virtual void SetDefaultFogEnviron( plFogEnvironment *fog ) { fView.fDefaultFog = *fog; fCurrFog.fEnvPtr = nil; }
virtual const plFogEnvironment &GetDefaultFogEnviron() const { return fView.fDefaultFog; }
// View state
virtual hsPoint3 GetViewPositionWorld() const { return GetViewTransform().GetPosition(); }
virtual hsVector3 GetViewAcrossWorld() const { return GetViewTransform().GetAcross(); }
virtual hsVector3 GetViewUpWorld() const { return GetViewTransform().GetUp(); }
virtual hsVector3 GetViewDirWorld() const { return GetViewTransform().GetDirection(); }
virtual void GetViewAxesWorld(hsVector3 axes[3] /* ac,up,at */ ) const;
virtual void GetFOV(hsScalar& fovX, hsScalar& fovY) const;
virtual void SetFOV(hsScalar fovX, hsScalar fovY);
virtual void GetSize(hsScalar& width, hsScalar& height) const;
virtual void SetSize(hsScalar width, hsScalar height);
virtual void GetDepth(hsScalar& hither, hsScalar& yon) const;
virtual void SetDepth(hsScalar hither, hsScalar yon);
virtual hsScalar GetZBiasScale() const;
virtual void SetZBiasScale(hsScalar scale);
virtual const hsMatrix44& GetWorldToCamera() const;
virtual const hsMatrix44& GetCameraToWorld() const;
virtual void SetWorldToCamera(const hsMatrix44& w2c, const hsMatrix44& c2w);
virtual void SetViewTransform(const plViewTransform& trans);
virtual const plViewTransform& GetViewTransform() const { return fView.fTransform; }
virtual const hsMatrix44& GetWorldToLocal() const;
virtual const hsMatrix44& GetLocalToWorld() const;
virtual void ScreenToWorldPoint( int n, UInt32 stride, Int32 *scrX, Int32 *scrY,
hsScalar dist, UInt32 strideOut, hsPoint3 *worldOut );
virtual void RefreshMatrices();
virtual void RefreshScreenMatrices();
virtual void RegisterLight(plLightInfo* light);
virtual void UnRegisterLight(plLightInfo* light);
// Overrides, always push returns whatever is necessary to restore on pop.
virtual hsGMaterial* PushOverrideMaterial(hsGMaterial* mat);
virtual void PopOverrideMaterial(hsGMaterial* restore);
virtual hsGMaterial* GetOverrideMaterial() const;
virtual plLayerInterface* AppendLayerInterface(plLayerInterface* li, hsBool onAllLayers = false);
virtual plLayerInterface* RemoveLayerInterface(plLayerInterface* li, hsBool onAllLayers = false);
virtual plLayerInterface* PushPiggyBackLayer(plLayerInterface* li);
virtual plLayerInterface* PopPiggyBackLayer(plLayerInterface* li);
virtual UInt32 GetMaterialOverrideOn(hsGMatState::StateIdx category) const;
virtual UInt32 GetMaterialOverrideOff(hsGMatState::StateIdx category) const;
virtual hsGMatState PushMaterialOverride(const hsGMatState& state, hsBool on);
virtual hsGMatState PushMaterialOverride(hsGMatState::StateIdx cat, UInt32 which, hsBool on);
virtual void PopMaterialOverride(const hsGMatState& restore, hsBool on);
virtual const hsGMatState& GetMaterialOverride(hsBool on) const;
virtual hsColorOverride PushColorOverride(const hsColorOverride& over);
virtual void PopColorOverride(const hsColorOverride& restore);
virtual const hsColorOverride& GetColorOverride() const;
virtual void SubmitShadowSlave(plShadowSlave* slave);
virtual void SubmitClothingOutfit(plClothingOutfit* co);
virtual hsBool SetGamma(hsScalar eR, hsScalar eG, hsScalar eB);
virtual hsBool SetGamma(const UInt16* const tabR, const UInt16* const tabG, const UInt16* const tabB);
virtual hsBool CaptureScreen( plMipmap *dest, bool flipVertical = false, UInt16 desiredWidth = 0, UInt16 desiredHeight = 0 );
virtual plMipmap* ExtractMipMap(plRenderTarget* targ);
/// Error handling
virtual const char *GetErrorString();
hsBool ManagedAlloced() const { return fManagedAlloced; }
virtual void GetSupportedColorDepths(hsTArray<int> &ColorDepths);
virtual void GetSupportedDisplayModes(std::vector<plDisplayMode> *res, int ColorDepth = 32 );
virtual int GetMaxAnisotropicSamples();
virtual int GetMaxAntiAlias(int Width, int Height, int ColorDepth);
};
//// Direct3D Inlines //////////////////////////////////////////////////////
// ??.?? - Some mild optimizations PBG
// MMW - take advantage of the 32 bit float representation on a PC
#define CONVERT_FLOAT_TO_BYTE_COLOR( f, dest ) \
{ \
LONG const floatBitsOne = 0x3f800000; \
LONG const floatBits = *( (LONG const *)( &f ) ); \
if( floatBits <= 0 ) dest = 0; \
else if( floatBits >= floatBitsOne ) dest = 255; \
else \
{ \
LONG const times256 = floatBits + ( 8 << 23 ); \
dest = (DWORD)( *( (float const *)( &times256 ) ) ); \
} \
}
inline DWORD plDXPipeline::inlGetD3DColor( const hsColorRGBA &col ) const
{
DWORD dr, dg, db, da;
CONVERT_FLOAT_TO_BYTE_COLOR( col.r, dr );
CONVERT_FLOAT_TO_BYTE_COLOR( col.g, dg );
CONVERT_FLOAT_TO_BYTE_COLOR( col.b, db );
CONVERT_FLOAT_TO_BYTE_COLOR( col.a, da );
return( ( da << 24 ) | ( dr << 16 ) | ( dg << 8 ) | db );
}
#endif // _plDX9Pipeline_h

View File

@ -0,0 +1,149 @@
/*==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==*/
#include "hsConfig.h"
#include "hsWindows.h"
#include <D3d9.h>
#include <D3dx9core.h>
#include "hsTypes.h"
#include "plDXPixelShader.h"
#include "../plSurface/plShader.h"
#include "plDXPipeline.h"
plDXPixelShader::plDXPixelShader(plShader* owner)
: plDXShader(owner), fHandle(nil)
{
}
plDXPixelShader::~plDXPixelShader()
{
Release();
}
void plDXPixelShader::Release()
{
ReleaseObject(fHandle);
fHandle = nil;
fPipe = nil;
ISetError(nil);
}
hsBool plDXPixelShader::VerifyFormat(UInt8 format) const
{
return (fOwner->GetInputFormat() & format) == fOwner->GetInputFormat();
}
IDirect3DPixelShader9 *plDXPixelShader::GetShader(plDXPipeline* pipe)
{
HRESULT hr = S_OK;
if ( !fHandle )
{
if( FAILED(hr = ICreate(pipe)) )
return nil;
}
if( FAILED(hr = ISetConstants(pipe)) )
return nil;
return fHandle;
}
HRESULT plDXPixelShader::ICreate(plDXPipeline* pipe)
{
fHandle = nil; // in case something goes wrong.
fPipe = nil;
ISetError(nil);
#ifdef HS_DEBUGGING
DWORD flags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
#else // HS_DEBUGGING
DWORD flags = 0;
#endif // HS_DEBUGGING
DWORD* shaderCodes = nil;
HRESULT hr = S_OK;
if( plShaderTable::LoadFromFile() || !fOwner->GetDecl()->GetCodes() )
{
if( fOwner->GetDecl()->GetFileName() )
{
LPD3DXBUFFER compiledShader = nil;
LPD3DXBUFFER compilationErrors = nil;
hr = D3DXAssembleShaderFromFile(
fOwner->GetDecl()->GetFileName(),
NULL, NULL, flags,
&compiledShader,
&compilationErrors);
if( FAILED(hr) )
{
return IOnError(hr, compilationErrors ? (char*)compilationErrors->GetBufferPointer() : "File not found");
}
shaderCodes = (DWORD*)(compiledShader->GetBufferPointer());
}
}
if( !shaderCodes )
{
shaderCodes = (DWORD*)(fOwner->GetDecl()->GetCodes());
}
if( !shaderCodes )
return IOnError(-1, "No file and no compiled codes");
hr = pipe->GetD3DDevice()->CreatePixelShader(shaderCodes, &fHandle);
if( FAILED(hr) )
{
return IOnError(hr, "Error on CreatePixelShader");
}
hsAssert(fHandle, "No error, but no pixel shader handle. Grrrr.");
fPipe = pipe;
return S_OK;
}
HRESULT plDXPixelShader::ISetConstants(plDXPipeline* pipe)
{
hsAssert(fHandle, "Pixel shader called to set constants without initialization");
if( fOwner->GetNumConsts() )
{
HRESULT hr = pipe->GetD3DDevice()->SetPixelShaderConstantF(0,
(float*)fOwner->GetConstBasePtr(),
fOwner->GetNumConsts());
if( FAILED(hr) )
return IOnError(hr, "Error setting constants");
}
return S_OK;
}

View File

@ -0,0 +1,56 @@
/*==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 plDXPixelShader_inc
#define plDXPixelShader_inc
#include "plDXShader.h"
class plShader;
class plDXPipeline;
struct IDirect3DPixelShader9;
class plDXPixelShader : public plDXShader
{
virtual HRESULT ICreate(plDXPipeline* pipe); // On error, sets error string.
virtual HRESULT ISetConstants(plDXPipeline* pipe);
IDirect3DPixelShader9 *fHandle;
public:
plDXPixelShader(plShader* owner);
virtual ~plDXPixelShader();
void Release();
void Link(plDXPixelShader** back) { plDXDeviceRef::Link((plDXDeviceRef**)back); }
hsBool VerifyFormat(UInt8 format) const;
IDirect3DPixelShader9 *GetShader(plDXPipeline* pipe);
};
#endif // plDXPixelShader_inc

View File

@ -0,0 +1,89 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDXRenderTargetRef.h - RenderTarget DeviceRef Definitions //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 7.19.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDXRenderTargetRef_h
#define _plDXRenderTargetRef_h
#include "hsMatrix44.h"
#include "hsTemplates.h"
#include "plDXTextureRef.h"
//// Definition ///////////////////////////////////////////////////////////////
class plRenderTarget;
class plDXRenderTargetRef: public plDXTextureRef
{
public:
IDirect3DSurface9 *fD3DColorSurface;
IDirect3DSurface9 *fD3DDepthSurface;
hsBool fReleaseDepth;
void Link( plDXRenderTargetRef **back ) { plDXDeviceRef::Link( (plDXDeviceRef **)back ); }
plDXRenderTargetRef *GetNext( void ) { return (plDXRenderTargetRef *)fNext; }
plDXRenderTargetRef( D3DFORMAT tp, UInt32 ml, plRenderTarget *owner, hsBool releaseDepthOnDelete = true );
plDXRenderTargetRef& Set( D3DFORMAT tp, UInt32 ml, plRenderTarget *owner );
virtual void SetOwner( plRenderTarget *targ ) { fOwner = (plBitmap *)targ; }
void SetTexture( IDirect3DSurface9 *surface, IDirect3DSurface9 *depth );
void SetTexture( IDirect3DTexture9 *surface, IDirect3DSurface9 *depth );
void SetTexture( IDirect3DCubeTexture9 *surface, IDirect3DSurface9 *depth );
IDirect3DSurface9 *GetColorSurface( void ) const
{
if( fD3DTexture != nil )
{
IDirect3DSurface9* psurf;
((IDirect3DTexture9*)fD3DTexture)->GetSurfaceLevel(0, &psurf);
if( psurf )
psurf->Release();
return psurf;
}
return fD3DColorSurface;
}
virtual ~plDXRenderTargetRef();
void Release( void );
};
#endif // _plDXRenderTargetRef_h

View File

@ -0,0 +1,285 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDXSettings - Header for the various settings groups for plDXPipeline //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 4.25.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDXSettings_h
#define _plDXSettings_h
#include "hsMatrix44.h"
#include "plFogEnvironment.h"
#include "hsGeometry3.h"
#include "hsTemplates.h"
#include "hsColorRGBA.h"
#include "hsBitVector.h"
#include "plStencil.h"
#include "hsPoint2.h"
#include "plCullTree.h"
#include "hsWinRef.h"
#include "plViewTransform.h"
//// General Settings /////////////////////////////////////////////////////////
class plRenderRequest;
class plRenderTarget;
struct IDirect3DSurface9;
class plDXDeviceRef;
class plDXVertexBufferRef;
class plDXIndexBufferRef;
class plDXViewSettings
{
public:
UInt32 fRenderState;
plRenderRequest* fRenderRequest;
UInt32 fDrawableTypeMask;
UInt32 fSubDrawableTypeMask;
DWORD fClearColor;
float fClearDepth;
plFogEnvironment fDefaultFog;
plCullTree fCullTree;
hsBool fCullTreeDirty;
UInt16 fCullMaxNodes;
enum XformResets
{
kResetProjection = 0x01,
kResetCamera = 0x02,
kResetL2W = 0x04,
kResetAll = 0x07
};
UInt8 fXformResetFlags;
hsBool fLocalToWorldLeftHanded;
hsBool fWorldToCamLeftHanded;
mutable hsVector3 fDirection;
mutable hsVector3 fUp;
mutable hsVector3 fAcross;
hsPoint3 fWorldPos;
mutable hsBool fViewVectorsDirty;
hsMatrix44 fLocalToWorld;
hsMatrix44 fWorldToLocal;
const hsMatrix44& GetLocalToWorld() const { return fLocalToWorld; }
const hsMatrix44& GetWorldToLocal() const { return fWorldToLocal; }
plViewTransform fTransform;
const hsMatrix44& GetWorldToCamera() const { return fTransform.GetWorldToCamera(); }
const hsMatrix44& GetCameraToWorld() const { return fTransform.GetCameraToWorld(); }
hsBool IsPerspective() const { return fTransform.GetPerspective(); }
void Reset();
};
class plDXGeneralSettings
{
public:
hsBool fFullscreen;
hsWinRef fHWnd;
UInt32 fColorDepth;
UInt8 fNumAASamples;
UInt32 fD3DCaps, fBoardKluge, fStageEnd;
UInt32 fMaxNumLights;
UInt32 fMaxNumProjectors;
UInt32 fMaxLayersAtOnce;
UInt32 fMaxPiggyBacks;
Int32 fBoundsDrawLevel;
UInt32 fProperties;
DWORD fClearColor;
UInt8 fMaxAnisotropicSamples;
D3DPRESENT_PARAMETERS fPresentParams;
hsBool fVeryAnnoyingTextureInvalidFlag;
hsBool fNoGammaCorrect;
int fMaxUVWSrc;
hsBool fCantProj;
hsBool fLimitedProj;
hsBool fBadManaged;
hsBool fShareDepth;
hsBool fCurrAnisotropy;
hsBool fIsIntel;
IDirect3DSurface9 *fCurrD3DMainSurface;
IDirect3DSurface9 *fCurrD3DDepthSurface;
hsTArray<plDXViewSettings> fViewStack; // One for the main view, then one for each rendertarget
hsTArray<plRenderTarget *> fRenderTargets;
plRenderTarget *fCurrRenderTarget;
plRenderTarget *fCurrBaseRenderTarget;
plDXDeviceRef *fCurrRenderTargetRef;
plDXVertexBufferRef *fCurrVertexBuffRef;
plDXIndexBufferRef *fCurrIndexBuffRef;
UInt32 fOrigWidth, fOrigHeight;
IDirect3DVertexShader9 *fCurrVertexShader;
IDirect3DPixelShader9 *fCurrPixelShader;
DWORD fCurrFVFFormat;
HRESULT fDXError;
char fErrorStr[ 256 ];
void Reset( void );
};
//// Tweak Settings ///////////////////////////////////////////////////////////
class plDXTweakSettings
{
public:
float fDefaultPerspLayerScale;
float fPerspLayerScale;
float fPerspLayerTrans;
float fDefaultLODBias;
float fFogExpApproxStart;
float fFogExp2ApproxStart;
float fFogEndBias;
float fExp2FogKnee;
float fExp2FogKneeVal;
float fExpFogKnee;
float fExpFogKneeVal;
void Reset( void )
{
fDefaultPerspLayerScale = 0.00001f;
fPerspLayerScale = 0.00001f;
fPerspLayerTrans = 0.00002f;
fDefaultLODBias = -0.25f;
fFogExpApproxStart = 0.0f;
fFogExp2ApproxStart = 0.0f;
fFogEndBias = 0.0f;
fExpFogKnee = fExp2FogKnee = 0.5f;
fExpFogKneeVal = fExp2FogKneeVal = 0.15f;
}
};
//// Fog Settings /////////////////////////////////////////////////////////////
class plDXFogSettings
{
public:
plFogEnvironment* fEnvPtr; // nil means no fog
D3DFOGMODE fMode;
UInt8 fIsVertex;
UInt8 fIsShader;
UInt32 fHexColor;
float fStart;
float fEnd;
float fDensity;
hsColorRGBA fColor;
void Reset( void )
{
fEnvPtr = nil;
fMode = D3DFOG_NONE;
fIsVertex = 0;
fIsShader = 0;
fHexColor = 0;
fStart = fEnd = fDensity = 0.0f;
fColor.Set( 0, 0, 0, 0 );
}
};
//// Light Settings ///////////////////////////////////////////////////////////
class plDXLightRef;
class plDXPipeline;
class plDXLightSettings
{
public:
hsBitVector fUsedFlags;
hsBitVector fEnabledFlags;
hsBitVector fHoldFlags;
UInt32 fNextIndex, fLastIndex;
UInt16 fTime;
plLightInfo* fActiveList;
plDXLightRef* fRefList;
plDXPipeline* fPipeline;
hsTArray<plLightInfo*> fProjEach;
hsTArray<plLightInfo*> fProjAll;
hsTArray<plLightInfo*> fCharLights;
hsTArray<plLightInfo*> fVisLights;
UInt32 fNextShadowLight;
hsTArray<plDXLightRef*> fShadowLights;
plDXLightSettings();
// Sets member variables to initial states. Does NOT release anything.
void Reset( plDXPipeline *pipe );
// Releases/deletes anything associated with these settings
void Release( void );
// Reserve a D3D light index
UInt32 ReserveD3DIndex( void );
// Release a reserved D3D light index
void ReleaseD3DIndex( UInt32 idx );
};
//// Stencil Settings /////////////////////////////////////////////////////////
class plDXStencilSettings
{
public:
UInt8 fDepth;
hsBool fEnabled;
UInt8 fCmpFunc;
UInt8 fFailOp, fPassOp, fPassButZFailOp;
UInt32 fRefValue;
UInt32 fMask;
UInt32 fWriteMask;
void Reset( void )
{
fEnabled = false;
fCmpFunc = 0;
fFailOp = fPassOp = fPassButZFailOp = 0;
fRefValue = 0;
fMask = 0xffffffff;
fWriteMask = 0xffffffff;
}
};
#endif // _plDXSettings_h

View File

@ -0,0 +1,86 @@
/*==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==*/
#include "hsConfig.h"
#include "hsWindows.h"
#include <D3d9.h>
#include <D3dx9core.h>
#include "hsTypes.h"
#include "plDXShader.h"
#include "../plSurface/plShader.h"
#include "plDXPipeline.h"
plDXShader::plDXShader(plShader* owner)
: fOwner(owner),
fErrorString(nil),
fPipe(nil)
{
owner->SetDeviceRef(this);
}
plDXShader::~plDXShader()
{
fPipe = nil;
ISetError(nil);
}
void plDXShader::SetOwner(plShader* owner)
{
if( owner != fOwner )
{
Release();
fOwner = owner;
owner->SetDeviceRef(this);
}
}
const char* plDXShader::ISetError(const char* errStr)
{
delete [] fErrorString;
if( errStr )
fErrorString = hsStrcpy(errStr);
else
fErrorString = nil;
return fErrorString;
}
HRESULT plDXShader::IOnError(HRESULT hr, const char* errStr)
{
ISetError(errStr);
fOwner->Invalidate();
hsStatusMessage(errStr);
return hr;
}

View File

@ -0,0 +1,56 @@
/*==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 plDXShader_inc
#define plDXShader_inc
#include "plDXDeviceRef.h"
class plShader;
class plDXPipeline;
class plDXShader : public plDXDeviceRef
{
protected:
plShader* fOwner;
char* fErrorString;
plDXPipeline* fPipe;
HRESULT IOnError(HRESULT hr, const char* errStr);
const char* ISetError(const char* errStr);
virtual HRESULT ICreate(plDXPipeline* pipe) = 0;
virtual HRESULT ISetConstants(plDXPipeline* pipe) = 0; // On error, sets error string.
public:
plDXShader(plShader* owner);
virtual ~plDXShader();
const char* GetErrorString() const { return fErrorString; }
void SetOwner(plShader* owner);
};
#endif // plDXShader_inc

View File

@ -0,0 +1,308 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDXTextFont Class Functions //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 2.19.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsConfig.h"
#include "hsWindows.h"
#include <d3d9.h>
#include <ddraw.h>
#include <d3dx9mesh.h>
#if HS_BUILD_FOR_MAC
#include <QuickDraw.h>
#endif
#include "hsWinRef.h"
#include "hsTypes.h"
#include "plDXTextFont.h"
#include "plDXPipeline.h"
//// Local Stuff //////////////////////////////////////////////////////////////
static const long PLD3D_FONTFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE
| D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0);
static D3DXMATRIX d3dIdentityMatrix( 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f );
// Following number needs to be at least: 64 chars max in plTextFont drawn at any one time
// * 4 primitives per char max (for bold text)
// * 3 verts per primitive
//const UInt32 kNumVertsInBuffer(32768);
const UInt32 kNumVertsInBuffer(4608);
// See the declaration for plFontVertex in plTextFont.h for info
const DWORD plDXTextFont::kFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0);
IDirect3DVertexBuffer9* plDXTextFont::fBuffer = nil;
UInt32 plDXTextFont::fBufferCursor = 0;
//// Constructor & Destructor /////////////////////////////////////////////////
plDXTextFont::plDXTextFont( plPipeline *pipe, IDirect3DDevice9 *device ) : plTextFont( pipe )
{
fDevice = device;
fD3DTexture = nil;
fOldStateBlock = fTextStateBlock = 0;
}
plDXTextFont::~plDXTextFont()
{
DestroyObjects();
}
//// ICreateTexture ///////////////////////////////////////////////////////////
void plDXTextFont::ICreateTexture( UInt16 *data )
{
HRESULT hr;
D3DLOCKED_RECT lockInfo;
D3DCAPS9 d3dCaps;
// Check to make sure we can support it
fDevice->GetDeviceCaps( &d3dCaps );
hsAssert( fTextureWidth <= d3dCaps.MaxTextureWidth, "Cannot initialize DX font--texture size too big" );
// Create our texture object
hr = fDevice->CreateTexture( fTextureWidth, fTextureHeight, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &fD3DTexture, NULL );
hsAssert( !FAILED( hr ), "Cannot create D3D texture" );
// Lock the texture and write our values out
fD3DTexture->LockRect( 0, &lockInfo, 0, 0 );
memcpy( lockInfo.pBits, data, fTextureWidth * fTextureHeight * sizeof( UInt16 ) );
fD3DTexture->UnlockRect( nil );
}
void plDXTextFont::CreateShared(IDirect3DDevice9* device)
{
if( FAILED( device->CreateVertexBuffer( sizeof( plFontVertex ) * kNumVertsInBuffer,
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &fBuffer, NULL ) ) )
{
hsAssert( false, "CreateVertexBuffer() call failed!" );
}
}
void plDXTextFont::ReleaseShared(IDirect3DDevice9* device)
{
ReleaseObject( fBuffer );
}
//// IInitStateBlocks /////////////////////////////////////////////////////////
void plDXTextFont::IInitStateBlocks( void )
{
for( int i = 0; i < 2; i++ )
{
fDevice->BeginStateBlock();
fDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
fDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
fDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
fDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
fDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 );
fDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
fDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
fDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
fDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
fDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS );
fDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
fDevice->SetRenderState( D3DRS_DEPTHBIAS, 0 );
fDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE );
fDevice->SetRenderState( D3DRS_CLIPPING, TRUE );
fDevice->SetRenderState( D3DRS_ANTIALIASEDLINEENABLE, FALSE );
fDevice->SetRenderState( D3DRS_VERTEXBLEND, FALSE );
fDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
fDevice->SetRenderState( D3DRS_FOGENABLE, FALSE );
fDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
fDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
fDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
fDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
fDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
fDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
fDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
fDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
fDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE );
fDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 );
fDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
fDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
fDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
fDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
if( i == 0 )
fDevice->EndStateBlock( &fOldStateBlock );
else
fDevice->EndStateBlock( &fTextStateBlock );
}
}
//// DestroyObjects ///////////////////////////////////////////////////////////
void plDXTextFont::DestroyObjects()
{
ReleaseObject(fOldStateBlock);
ReleaseObject(fTextStateBlock);
ReleaseObject(fD3DTexture);
fOldStateBlock = fTextStateBlock = 0;
fD3DTexture = nil;
fInitialized = false;
}
//// IDrawPrimitive ///////////////////////////////////////////////////////////
void plDXTextFont::IDrawPrimitive( UInt32 count, plFontVertex *array )
{
plFontVertex *v;
if( !fBuffer )
return;
/// Lock the buffer and write to it
if( fBufferCursor && (fBufferCursor + count * 3 < kNumVertsInBuffer) )
{
// We can lock part of it
if( FAILED( fBuffer->Lock( fBufferCursor * sizeof( plFontVertex ),
count * 3 * sizeof( plFontVertex ),
(void **)&v, D3DLOCK_NOOVERWRITE ) ) )
{
hsAssert( false, "Failed to lock vertex buffer for writing" );
return;
}
fBufferCursor += count * 3;
}
else
{
// Gotta start over
FlushDraws();
fBufferCursor = count * 3;
if( FAILED( fBuffer->Lock( 0, count * 3 * sizeof( plFontVertex ),
(void **)&v, D3DLOCK_DISCARD ) ) )
{
hsAssert( false, "Failed to lock vertex buffer for writing" );
return;
}
}
if( v != nil && array != nil )
{
memcpy( v, array, count * sizeof( plFontVertex ) * 3 );
}
fBuffer->Unlock();
}
//// IDrawLines ///////////////////////////////////////////////////////////////
void plDXTextFont::IDrawLines( UInt32 count, plFontVertex *array )
{
if( !fBuffer )
return;
if( count == 0 || array == nil )
return;
fDevice->SetVertexShader(NULL);
fDevice->SetFVF(kFVF);
fDevice->SetStreamSource(0, fBuffer, 0, sizeof(plFontVertex));
fDevice->DrawPrimitiveUP( D3DPT_LINELIST, count, (const void *)array, sizeof( plFontVertex ) );
}
//// FlushDraws ///////////////////////////////////////////////////////////////
// Flushes out and finishes any drawing left to be done.
void plDXTextFont::FlushDraws( void )
{
if( !fBuffer )
return;
if( fBufferCursor > 0 )
{
fDevice->SetVertexShader( NULL );
fDevice->SetFVF(kFVF);
fDevice->SetStreamSource( 0, fBuffer, 0, sizeof( plFontVertex ) );
fDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, fBufferCursor / 3 );
fBufferCursor = 0;
}
}
//// SaveStates ///////////////////////////////////////////////////////////////
void plDXTextFont::SaveStates( void )
{
if( !fInitialized )
IInitObjects();
if (fOldStateBlock)
fOldStateBlock->Capture();
if (fTextStateBlock)
fTextStateBlock->Apply();
fDevice->SetTexture( 0, fD3DTexture );
fDevice->SetTransform( D3DTS_TEXTURE0, &d3dIdentityMatrix );
/// Set up the transform matrices so that the vertices can range (0-screenWidth,0-screenHeight)
fDevice->SetTransform( D3DTS_WORLD, &d3dIdentityMatrix );
fDevice->SetTransform( D3DTS_VIEW, &d3dIdentityMatrix );
D3DXMATRIX mat;
mat = d3dIdentityMatrix;
mat(0,0) = 2.0f / (float)fPipe->Width();
mat(1,1) = -2.0f / (float)fPipe->Height();
mat(3,0) = -1.0;
mat(3,1) = 1.0;
fDevice->SetTransform( D3DTS_PROJECTION, &mat );
}
//// RestoreStates ////////////////////////////////////////////////////////////
void plDXTextFont::RestoreStates( void )
{
if (fOldStateBlock)
fOldStateBlock->Apply();
fDevice->SetTexture( 0, nil );
fDevice->SetTransform( D3DTS_TEXTURE0, &d3dIdentityMatrix );
}

View File

@ -0,0 +1,74 @@
/*==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 _plDXTextFont_h
#define _plDXTextFont_h
#include "plTextFont.h"
//#include "hsGDirect3DTnLDevice.h"
//// plDXTextFont Class Definition ///////////////////////////////////////////
struct IDirect3DTexture9;
struct IDirect3DDevice9;
struct IDirect3DStateBlock9;
class plPipeline;
class plDXTextFont : public plTextFont
{
protected:
IDirect3DTexture9 *fD3DTexture;
IDirect3DDevice9 *fDevice;
static IDirect3DVertexBuffer9 *fBuffer;
static UInt32 fBufferCursor;
IDirect3DStateBlock9 *fOldStateBlock;
IDirect3DStateBlock9 *fTextStateBlock;
virtual void ICreateTexture( UInt16 *data );
virtual void IInitStateBlocks( void );
virtual void IDrawPrimitive( UInt32 count, plFontVertex *array );
virtual void IDrawLines( UInt32 count, plFontVertex *array );
public:
plDXTextFont( plPipeline *pipe, IDirect3DDevice9 *device );
~plDXTextFont();
static void CreateShared(IDirect3DDevice9* device);
static void ReleaseShared(IDirect3DDevice9* device);
virtual void FlushDraws( void );
virtual void SaveStates( void );
virtual void RestoreStates( void );
virtual void DestroyObjects( void );
static const DWORD kFVF;
};
#endif // _plDXTextFont_h

View File

@ -0,0 +1,107 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plDXTextureRef.h - Hardware Texture DeviceRef Definition //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 4.25.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plDXTextureRef_h
#define _plDXTextureRef_h
#include "hsMatrix44.h"
#include "hsGeometry3.h"
#include "hsTemplates.h"
#include "plDXDeviceRef.h"
//// Definition ///////////////////////////////////////////////////////////////
class plBitmap;
class plDXTextureRef : public plDXDeviceRef
{
public:
enum Flags
{
kExternData = 0x00000002, // fData points to user data, don't delete
kRenderTarget = 0x00000004, // Created via a render target
kCubicMap = 0x00000008, // Texture is really a cubic map texture
kPerspProjection = 0x00000010, // Perspective projection
kOrthoProjection = 0x00000020, // Orthogonal projection
kProjection = kPerspProjection | kOrthoProjection,
kOffscreenRT = 0x00000040, // Offscreen renderTarget. Never used as an actual texture,
// but handy to still have it as a textureRef
kUVWNormal = 0x00000080 // Use the normal as the UVW src
};
IDirect3DBaseTexture9 *fD3DTexture;
D3DFORMAT fFormatType; // Format of the D3D texture object
UInt32 fMMLvs; // Number of mipmap levels
UInt32 fMaxWidth; // Width of the highest mipmap level
UInt32 fMaxHeight; // Height of the highest mipmap level (no pun intended)
UInt32 fNumPix; // total num texels in all mip levels
UInt32 fDataSize; // size of fData[0..n] in bytes
UInt32* fLevelSizes; // fLevelSize[i] == size in bytes of level i
//UInt32 fCurrLOD; // Current LOD setting for this texture
plBitmap *fOwner;
void* fData; // for reloading
UInt32 GetFlags( void ) { return fFlags; }
void SetFlags( UInt32 flag ) { fFlags = flag; }
plDXTextureRef& Set( D3DFORMAT tp, UInt32 ml, UInt32 mw, UInt32 mh, UInt32 np, UInt32 sz, UInt32 manSize, UInt32* lSz, void* pd, hsBool ed=false, hsBool renderTarget = false );
plDXTextureRef( D3DFORMAT tp, UInt32 ml, UInt32 mw, UInt32 mh, UInt32 np, UInt32 sz, UInt32 manSize, UInt32* lSz, void* pd, hsBool ed=false, hsBool renderTarget = false );
virtual ~plDXTextureRef();
void Link( plDXTextureRef **back ) { plDXDeviceRef::Link( (plDXDeviceRef **)back ); }
plDXTextureRef *GetNext( void ) { return (plDXTextureRef *)fNext; }
void Release( void );
};
class plDXCubeTextureRef : public plDXTextureRef
{
public:
void *fFaceData[ 5 ]; // First face is in the inherited fData
plDXCubeTextureRef( D3DFORMAT tp, UInt32 ml, UInt32 mw, UInt32 mh, UInt32 np, UInt32 sz, UInt32 manSize, UInt32* lSz, void* pd, hsBool ed=false, hsBool renderTarget = false ) :
plDXTextureRef( tp, ml, mw, mh, np, sz, manSize, lSz, pd, ed, renderTarget )
{
}
};
#endif // _plDXTextureRef_h

View File

@ -0,0 +1,152 @@
/*==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==*/
#include "hsConfig.h"
#include "hsWindows.h"
#include <D3d9.h>
#include <D3dx9core.h>
#include "hsTypes.h"
#include "plDXVertexShader.h"
#include "../plSurface/plShader.h"
#include "plGBufferGroup.h"
#include "plDXPipeline.h"
plDXVertexShader::plDXVertexShader(plShader* owner)
: plDXShader(owner), fHandle(nil)
{
}
plDXVertexShader::~plDXVertexShader()
{
Release();
}
void plDXVertexShader::Release()
{
ReleaseObject(fHandle);
fHandle = nil;
fPipe = nil;
ISetError(nil);
}
hsBool plDXVertexShader::VerifyFormat(UInt8 format) const
{
return (fOwner->GetInputFormat() & format) == fOwner->GetInputFormat();
}
IDirect3DVertexShader9 *plDXVertexShader::GetShader(plDXPipeline* pipe)
{
HRESULT hr = S_OK;
if ( !fHandle )
{
if( FAILED(hr = ICreate(pipe)) )
return nil;
}
if( FAILED(hr = ISetConstants(pipe)) )
return nil;
return fHandle;
}
HRESULT plDXVertexShader::ICreate(plDXPipeline* pipe)
{
fHandle = nil; // in case something goes wrong.
fPipe = nil;
ISetError(nil);
#ifdef HS_DEBUGGING
DWORD flags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
#else // HS_DEBUGGING
DWORD flags = 0;
#endif // HS_DEBUGGING
// We could store the compiled buffer and skip the assembly step
// if we need to recreate the shader (e.g. on device lost).
// But whatever.
DWORD* shaderCodes = nil;
HRESULT hr = S_OK;
if( plShaderTable::LoadFromFile() || !fOwner->GetDecl()->GetCodes() )
{
if( fOwner->GetDecl()->GetFileName() )
{
LPD3DXBUFFER compiledShader = nil;
LPD3DXBUFFER compilationErrors = nil;
hr = D3DXAssembleShaderFromFile(
fOwner->GetDecl()->GetFileName(),
NULL, NULL, flags,
&compiledShader,
&compilationErrors);
if( FAILED(hr) )
{
return IOnError(hr, compilationErrors ? (char*)compilationErrors->GetBufferPointer() : "File not found");
}
shaderCodes = (DWORD*)(compiledShader->GetBufferPointer());
}
}
if( !shaderCodes )
{
shaderCodes = (DWORD*)(fOwner->GetDecl()->GetCodes());
}
if( !shaderCodes )
return IOnError(-1, "No file and no compiled codes");
hr = pipe->GetD3DDevice()->CreateVertexShader(shaderCodes, &fHandle);
if( FAILED(hr) )
return IOnError(hr, "Error on CreateVertexShader");
hsAssert(fHandle, "No error, but no vertex shader handle. Grrrr.");
fPipe = pipe;
return S_OK;
}
HRESULT plDXVertexShader::ISetConstants(plDXPipeline* pipe)
{
hsAssert(fHandle, "Vertex shader called to set constants without initialization");
if( fOwner->GetNumConsts() )
{
HRESULT hr = pipe->GetD3DDevice()->SetVertexShaderConstantF(0,
(float*)fOwner->GetConstBasePtr(),
fOwner->GetNumConsts());
if( FAILED(hr) )
return IOnError(hr, "Failure setting vertex shader constants");
}
return S_OK;
}

View File

@ -0,0 +1,57 @@
/*==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 plDXVertexSahder_inc
#define plDXVertexSahder_inc
#include "plDXShader.h"
#include "hsTemplates.h"
struct IDirect3DDevice9;
class plShader;
class plDXPipeline;
class plDXVertexShader : public plDXShader
{
protected:
IDirect3DVertexShader9* fHandle;
hsTArray<DWORD>& IMakeDecl(hsTArray<DWORD>& decl) const;
virtual HRESULT ICreate(plDXPipeline* pipe); // On error, sets error string.
virtual HRESULT ISetConstants(plDXPipeline* pipe); // On error, sets error string.
public:
plDXVertexShader(plShader* owner);
virtual ~plDXVertexShader();
virtual void Release();
void Link(plDXVertexShader** back) { plDXDeviceRef::Link((plDXDeviceRef**)back); }
hsBool VerifyFormat(UInt8 format) const;
IDirect3DVertexShader9* GetShader(plDXPipeline* pipe);
};
#endif // plDXVertexSahder_inc

View File

@ -0,0 +1,288 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plDebugText and plDebugTextManager Functions //
// //
//////////////////////////////////////////////////////////////////////////////
#include "plPipeline.h"
#include "plDebugText.h"
#include "plTextFont.h"
//////////////////////////////////////////////////////////////////////////////
//// plDebugText Functions ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
plDebugText plDebugText::fInstance;
//// DrawString //////////////////////////////////////////////////////////////
void plDebugText::DrawString( UInt16 x, UInt16 y, const char *string, UInt32 hexColor, UInt8 style )
{
if( IsEnabled() && fManager && string != nil && string[ 0 ] != 0 )
fManager->AddString( x, y, string, hexColor, style, fDrawOnTopMode );
}
//// CalcStringWidth /////////////////////////////////////////////////////////
UInt32 plDebugText::CalcStringWidth( const char *string )
{
if( IsEnabled() && fManager && string )
return fManager->CalcStringWidth( string );
return 0;
}
//// DrawRect ////////////////////////////////////////////////////////////////
// TEMPORARY function to draw a flat-shaded 2D rectangle to the screen. Used
// to create a background for our console; will be obliterated once we figure
// a better way to do so.
void plDebugText::DrawRect( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 hexColor )
{
if( IsEnabled() && fManager )
fManager->DrawRect( left, top, right, bottom, hexColor, fDrawOnTopMode );
}
//// Draw3DBorder ////////////////////////////////////////////////////////////
void plDebugText::Draw3DBorder( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 hexColor1, UInt32 hexColor2 )
{
if( IsEnabled() && fManager )
fManager->Draw3DBorder( left, top, right, bottom, hexColor1, hexColor2, fDrawOnTopMode );
}
//// GetScreenSize ///////////////////////////////////////////////////////////
void plDebugText::GetScreenSize( UInt32 *width, UInt32 *height )
{
if( fManager )
fManager->GetScreenSize( width, height );
}
UInt16 plDebugText::GetFontHeight()
{
if (fManager)
return fManager->GetFontHeight();
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//// plDebugTextManager Functions ////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// plDebugTextNode Constructor /////////////////////////////////////////////
plDebugTextManager::plDebugTextNode::plDebugTextNode( const char *s, UInt32 c, UInt16 x, UInt16 y, UInt8 style )
{
HSMemory::Clear( fText, sizeof( fText ) );
strncpy( fText, s, sizeof( fText ) - 1 );
fColor = c;
fX = x;
fY = y;
fStyle = style;
}
plDebugTextManager::plDebugTextNode::plDebugTextNode( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 c )
{
memset( fText, 0, sizeof( fText ) );
fColor = c;
fX = left;
fY = top;
fRight = right;
fBottom = bottom;
fStyle = 0xff;
}
plDebugTextManager::plDebugTextNode::plDebugTextNode( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 c1, UInt32 c2 )
{
memset( fText, 0, sizeof( fText ) );
fColor = c1;
fDarkColor = c2;
fX = left;
fY = top;
fRight = right;
fBottom = bottom;
fStyle = 0xfe;
}
//// plDebugTextManager destructor ///////////////////////////////////////////
plDebugTextManager::~plDebugTextManager()
{
if( fFont != nil )
delete fFont;
}
//// AddString ///////////////////////////////////////////////////////////////
void plDebugTextManager::AddString( UInt16 x, UInt16 y, const char *s, UInt32 hexColor, UInt8 style, hsBool drawOnTop )
{
if( drawOnTop )
fDrawOnTopList.Append( plDebugTextNode( s, hexColor, x, y, style ) );
else
fList.Append( plDebugTextNode( s, hexColor, x, y, style ) );
}
//// DrawRect ////////////////////////////////////////////////////////////////
// TEMPORARY function to draw a flat-shaded 2D rectangle to the screen. Used
// to create a background for our console; will be obliterated once we figure
// a better way to do so.
void plDebugTextManager::DrawRect( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 hexColor, hsBool drawOnTop )
{
if( drawOnTop )
fDrawOnTopList.Append( plDebugTextNode( left, top, right, bottom, hexColor ) );
else
fList.Append( plDebugTextNode( left, top, right, bottom, hexColor ) );
}
//// Draw3DBorder ////////////////////////////////////////////////////////////
void plDebugTextManager::Draw3DBorder( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 hexColor1, UInt32 hexColor2, hsBool drawOnTop )
{
if( drawOnTop )
fDrawOnTopList.Append( plDebugTextNode( left, top, right, bottom, hexColor1, hexColor2 ) );
else
fList.Append( plDebugTextNode( left, top, right, bottom, hexColor1, hexColor2 ) );
}
//// DrawToDevice ////////////////////////////////////////////////////////////
void plDebugTextManager::DrawToDevice( plPipeline *pipe )
{
int i, j;
hsTArray<plDebugTextNode> *list;
if( fList.GetCount() == 0 && fDrawOnTopList.GetCount() == 0 )
{
return;
}
if( fFont == nil )
{
// Create font first time around
fFont = pipe->MakeTextFont( (char *)plDebugText::Instance().GetFontFace(),
plDebugText::Instance().GetFontSize() );
if( fFont == nil )
{
plDebugText::Instance().DisablePermanently();
return;
}
}
// Get stuff
fSWidth = pipe->Width();
fSHeight = pipe->Height();
// Start other stuff
fFont->SaveStates();
for( j = 0; j < 2; j++ )
{
if( j == 0 )
list = &fList;
else
list = &fDrawOnTopList;
for( i = 0; i < list->GetCount(); i++ )
{
plDebugTextNode& node = (*list)[i];
if( node.fStyle == 0xff )
{
fFont->DrawRect( node.fX, node.fY,
node.fRight, node.fBottom, node.fColor );
}
else if( node.fStyle == 0xfe )
{
fFont->Draw3DBorder( node.fX, node.fY,
node.fRight, node.fBottom, node.fColor, node.fDarkColor );
}
else
{
/// Draw string only if its in bounds (clip to right edge if necessary)
if( node.fX >= 0 && node.fY >= 0 )
{
if( node.fY + fFont->GetFontHeight() < fSHeight )
{
if( node.fX + CalcStringWidth( node.fText ) < fSWidth )
{
fFont->DrawString( node.fText, node.fX, node.fY,
node.fColor, node.fStyle );
}
else
{
fFont->DrawString( node.fText, node.fX, node.fY,
node.fColor, node.fStyle, fSWidth );
}
}
}
}
}
}
// Call this to ensure the font object finishes all its drawing
fFont->FlushDraws();
fFont->RestoreStates();
fList.Reset();
fDrawOnTopList.Reset();
}
//// CalcStringWidth /////////////////////////////////////////////////////////
UInt32 plDebugTextManager::CalcStringWidth( const char *string )
{
if( !plDebugText::Instance().IsEnabled() || fFont == nil )
return 0;
return fFont->CalcStringWidth( string );
}
//// GetScreenSize ///////////////////////////////////////////////////////////
void plDebugTextManager::GetScreenSize( UInt32 *width, UInt32 *height )
{
if( width != nil )
*width = fSWidth;
if( height != nil )
*height = fSHeight;
}
UInt16 plDebugTextManager::GetFontHeight()
{
if (fFont)
return fFont->GetFontHeight();
// Just return a quick default height until we get a real font
return 10;
}

View File

@ -0,0 +1,187 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plDebugText and plDebugTextManager Headers //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plDebugText_h
#define _plDebugText_h
#include "hsTypes.h"
#include "hsColorRGBA.h"
#include "hsTemplates.h"
#include "hsUtils.h"
//// plDebugText Class Definition ////////////////////////////////////////////
class plPipeline;
class plDebugTextManager;
class plDebugText
{
private:
static plDebugText fInstance;
plDebugText()
{
fManager = nil;
#ifdef PLASMA_EXTERNAL_RELEASE
SetFont( "Trebuchet MS Bold", 8 );
#else
SetFont( "Courier New", 8 );
#endif
SetEnable( true );
fLockEnable = false;
fDrawOnTopMode = false;
}
protected:
plDebugTextManager *fManager;
char fFontFace[ 128 ];
UInt16 fFontSize;
hsBool fEnabled, fLockEnable, fDrawOnTopMode;
public:
enum Styles
{
kStyleItalic = 0x01,
kStyleBold = 0x02
};
~plDebugText() { ; }
static plDebugText &Instance( void ) { return fInstance; }
UInt32 CalcStringWidth( const char *string );
void DrawString( UInt16 x, UInt16 y, const char *string, UInt32 hexColor, UInt8 style = 0 );
void DrawString( UInt16 x, UInt16 y, const char *string, hsColorRGBA &color, UInt8 style = 0 )
{
UInt32 hex;
UInt8 r, g, b, a;
r = (UInt8)( color.r * 255.0 );
g = (UInt8)( color.g * 255.0 );
b = (UInt8)( color.b * 255.0 );
a = (UInt8)( color.a * 255.0 );
hex = ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | ( b );
DrawString( x, y, string, hex, style );
}
void DrawString( UInt16 x, UInt16 y, const char *string, UInt8 r = 255, UInt8 g = 255, UInt8 b = 255, UInt8 a = 255, UInt8 style = 0 )
{
DrawString( x, y, string, (UInt32)( ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | ( b ) ), style );
}
void SetDrawOnTopMode( hsBool enable ) { fDrawOnTopMode = enable; }
/// TEMPORARY FUNCTION (until we can find a better way to do this, one way or the other)
void DrawRect( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 hexColor );
/// TEMPORARY FUNCTION (until we can find a better way to do this, one way or the other)
void DrawRect( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt8 r, UInt8 g, UInt8 b, UInt8 a = 255 )
{
DrawRect( left, top, right, bottom, (UInt32)( ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | ( b ) ) );
}
/// EVEN MORE TEMPORARY FUNCTION (until we can find a better way to do this, one way or the other)
void Draw3DBorder( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 hexColor1, UInt32 hexColor2 );
void SetManager( plDebugTextManager *m ) { fManager = m; }
void SetFont( char *face, UInt16 size ) { hsStrncpy( fFontFace, face, sizeof( fFontFace ) ); fFontSize = size; }
const char *GetFontFace( void ) { return fFontFace; }
const UInt16 GetFontSize( void ) { return fFontSize; }
UInt16 GetFontHeight();
void SetEnable( hsBool on ) { fEnabled = on; }
void DisablePermanently( void ) { fEnabled = false; fLockEnable = true; }
const hsBool IsEnabled( void ) { return fEnabled; }
void GetScreenSize( UInt32 *width, UInt32 *height );
};
//// plDebugTextManager Class Definition /////////////////////////////////////
class plTextFont;
class plDebugTextManager
{
protected:
struct plDebugTextNode
{
char fText[ 256 ];
UInt32 fColor, fDarkColor;
UInt16 fX, fY, fRight, fBottom; // Last 2 are for rects only
UInt8 fStyle; // 0xff means rectangle, 0xfe means 3d border
plDebugTextNode() { fText[ 0 ] = 0; fColor = 0; fX = fY = 0; fStyle = 0; }
plDebugTextNode( const char *s, UInt32 c, UInt16 x, UInt16 y, UInt8 style );
plDebugTextNode( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 c );
plDebugTextNode( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 c1, UInt32 c2 );
~plDebugTextNode() {;}
};
hsTArray<plDebugTextNode> fList;
hsTArray<plDebugTextNode> fDrawOnTopList;
plTextFont *fFont;
UInt32 fSWidth, fSHeight;
public:
plDebugTextManager() { plDebugText::Instance().SetManager( this ); fFont = nil; }
~plDebugTextManager();
void AddString( UInt16 x, UInt16 y, const char *s, UInt32 hexColor, UInt8 style, hsBool drawOnTop = false );
UInt32 CalcStringWidth( const char *string );
/// TEMPORARY FUNCTION (until we can find a better way to do this, one way or the other)
void DrawRect( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 hexColor, hsBool drawOnTop = false );
/// EVEN MORE TEMPORARY FUNCTION (until we can find a better way to do this, one way or the other)
void Draw3DBorder( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom, UInt32 hexColor1, UInt32 hexColor2, hsBool drawOnTop = false );
void DrawToDevice( plPipeline *pipe );
void GetScreenSize( UInt32 *width, UInt32 *height );
UInt16 GetFontHeight();
};
#endif //_plDebugText_h

View File

@ -0,0 +1,88 @@
/*==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==*/
#include "hsKeyedObject.h"
struct hsMatrix44;
class hsBounds3Ext;
class hsGMaterial;
class hsTriangle3;
struct hsGSplat3;
class plDrawPrim : public hsRefCnt
{
public:
enum plDPPrimType
{
kTypeNone = 0x0,
kTypeTriList = 0x1,
kTypeSplatList = 0x2
};
protected:
UInt32 fPrimType;
UInt32 fDrawProps;
hsGMaterial* fMaterial;
public:
plDrawPrim() : fMaterial(nil), fDrawProps(0), fPrimType(kTypeNone) {}
virtual ~plDrawPrim();
virtual const hsBounds3Ext& GetLocalBounds() const = 0;
hsGMaterial* GetMaterial() { return fMaterial; }
UInt32 GetPrimType() { return fPrimType; }
UInt32 GetDrawProps() { return fDrawProps; }
};
class plTriListPrim : public plDrawPrim
{
public:
plTriListPrim() { fPrimType |= kTypeTriList; }
virtual ~plTriListPrim();
virtual const hsBounds3Ext& GetLocalBounds() const = 0;
virtual hsTriangle3* GetTriList(int& num) = 0;
};
class plSplatListPrim : public plDrawPrim
{
public:
plSplatListPrim() { fPrimType |= kTypeSplatList; }
virtual const hsBounds3Ext& GetLocalBounds() const = 0;
virtual hsGSplat3* GetSplatList(int& num) = 0;
};

View File

@ -0,0 +1,952 @@
/*==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==*/
#include "hsTypes.h"
#include "plDynamicEnvMap.h"
#include "plPipeline.h"
#include "plPipeDebugFlags.h"
#include "plDrawable.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "hsStream.h"
#include "../plMessage/plRenderRequestMsg.h"
#include "../plMessage/plDynamicEnvMapMsg.h"
#include "../pfCamera/plCameraModifier.h"
#include "../pfCamera/plVirtualCamNeu.h"
#include "../plMessage/plRenderMsg.h"
#include "../plMessage/plAgeLoadedMsg.h"
#include "../plMessage/plLayRefMsg.h"
#include "../pnMessage/plPipeResMakeMsg.h"
#include "../pnMessage/plRefMsg.h"
#include "../plScene/plVisRegion.h"
#include "../plScene/plVisMgr.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plSurface/plLayer.h"
plDynamicEnvMap::plDynamicEnvMap()
: fPos(0,0,0),
fHither(0.3f),
fYon(1000.f),
fFogStart(1000.f),
fRefreshRate(0.f),
fLastRefresh(0.0),
fLastRender(0),
fOutStanding(0),
fIncCharacters(false),
fRootNode(nil)
{
fColor.Set(0,0,0,1.f);
int i;
for( i = 0; i < 6; i++ )
fReqMsgs[i] = TRACKED_NEW plRenderRequestMsg(nil, &fReqs[i]);;
SetPosition(fPos);
}
plDynamicEnvMap::plDynamicEnvMap(UInt16 width, UInt16 height, UInt8 bitDepth, UInt8 zDepth, UInt8 sDepth)
: fPos(0,0,0),
fHither(0.3f),
fYon(0.f), // yon < hither means ignore and use current settings
fFogStart(-1.f), // - fog start means use current settings
fRefreshRate(0.f),
fLastRefresh(0.0),
fLastRender(0),
fOutStanding(0),
fIncCharacters(false),
fRootNode(nil),
plCubicRenderTarget(plRenderTarget::kIsTexture, width, height, bitDepth, zDepth, sDepth)
{
fColor.Set(0,0,0,1.f);
int i;
for( i = 0; i < 6; i++ )
fReqMsgs[i] = TRACKED_NEW plRenderRequestMsg(nil, &fReqs[i]);;
SetPosition(fPos);
}
plDynamicEnvMap::~plDynamicEnvMap()
{
SetDeviceRef(nil);
int i;
for( i = 0; i < 6; i++ )
delete fReqMsgs[i];
}
void plDynamicEnvMap::Init()
{
plgDispatch::Dispatch()->RegisterForExactType(plPipeRTMakeMsg::Index(), GetKey());
plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), GetKey());
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
ISetupRenderRequests();
}
hsPoint3 plDynamicEnvMap::GetPosition() const
{
if (fRootNode)
{
// This is to catch export issues where we've got a root node, but its iface
// hasn't fully been set up yet.
if (fRootNode->GetCoordinateInterface())
return fRootNode->GetLocalToWorld().GetTranslate();
}
return fPos;
}
void plDynamicEnvMap::SetPosition(const hsPoint3& pos)
{
hsAssert(fRootNode == nil, "Trying to override a cube map's root node.");
fPos = pos;
SetCameraMatrix(fPos);
}
void plDynamicEnvMap::IUpdatePosition()
{
hsPoint3 pos = GetPosition();
if (pos != fPos)
SetCameraMatrix(fPos);
}
void plDynamicEnvMap::SetHither(hsScalar f)
{
fHither = f;
}
void plDynamicEnvMap::SetYon(hsScalar f)
{
fYon = f;
}
void plDynamicEnvMap::SetFogStart(hsScalar f)
{
fFogStart = f;
}
void plDynamicEnvMap::SetColor(const hsColorRGBA& col)
{
fColor = col;
}
void plDynamicEnvMap::SetRefreshRate(hsScalar secs)
{
fRefreshRate = secs / 6.f;
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
}
void plDynamicEnvMap::ISetupRenderRequests()
{
UInt32 renderState
= plPipeline::kRenderNormal
| plPipeline::kRenderClearColor
| plPipeline::kRenderClearDepth;
int i;
for( i = 0; i < 6; i++ )
{
fReqs[i].SetRenderState(renderState);
fReqs[i].SetDrawableMask(plDrawable::kNormal);
fReqs[i].SetSubDrawableMask(plDrawable::kSubAllTypes);
fReqs[i].SetHither(fHither);
fReqs[i].SetYon(fYon);
fReqs[i].SetFogStart(fFogStart);
fReqs[i].SetFovX(90.f);
fReqs[i].SetFovY(90.f);
fReqs[i].SetClearColor(fColor);
fReqs[i].SetClearDepth(1.f);
fReqs[i].SetClearDrawable(nil);
fReqs[i].SetRenderTarget(GetFace(i));
fReqs[i].SetCameraTransform(GetWorldToCamera(i), GetCameraToWorld(i));
fReqs[i].SetVisForce(fVisSet);
fReqs[i].RequestAck(GetKey());
}
}
void plDynamicEnvMap::ISubmitRenderRequest(int i)
{
IUpdatePosition();
fReqMsgs[i]->SendAndKeep();
fLastRender = i;
fOutStanding++;
}
void plDynamicEnvMap::ISubmitRenderRequests()
{
IUpdatePosition();
int i;
for( i = 0; i < 6; i++ )
fReqMsgs[i]->SendAndKeep();
fLastRefresh = hsTimer::GetSysSeconds();
fOutStanding += 6;
}
void plDynamicEnvMap::ICheckForRefresh(double t, plPipeline *pipe)
{
if( fLastRefresh <= 0 )
{
ISubmitRenderRequests();
return;
}
if( fRefreshRate <= 0 )
return;
#ifndef PLASMA_EXTERNAL_RELEASE
if (pipe->IsDebugFlagSet(plPipeDbg::kFlagNVPerfHUD) && hsTimer::GetDelSysSeconds() == 0)
{
ISubmitRenderRequests();
return;
}
#endif // PLASMA_EXTERNAL_RELEASE
if( t > fLastRefresh + 6.f * fRefreshRate )
{
ISubmitRenderRequests();
return;
}
while( t > fLastRefresh + fRefreshRate )
{
int nextRender = fLastRender+1;
if( nextRender > 5 )
nextRender = 0;
ISubmitRenderRequest(nextRender);
fLastRefresh += fRefreshRate;
}
}
void plDynamicEnvMap::ReRender()
{
ISetupRenderRequests();
ISubmitRenderRequests();
}
hsBool plDynamicEnvMap::INeedReRender()
{
fOutStanding = 0;
fLastRefresh = 0;
return true;
}
hsBool plDynamicEnvMap::MsgReceive(plMessage* msg)
{
plRenderRequestAck* ack = plRenderRequestAck::ConvertNoRef(msg);
if( ack )
{
fOutStanding--;
return true;
}
plRenderMsg* rendMsg = plRenderMsg::ConvertNoRef(msg);
if( rendMsg )
{
if( fOutStanding )
INeedReRender();
ICheckForRefresh(hsTimer::GetSysSeconds(), rendMsg->Pipeline());
return true;
}
if( plPipeRTMakeMsg::ConvertNoRef(msg) )
{
INeedReRender();
plCubicRenderTarget::MsgReceive(msg);
return true;
}
plAgeLoadedMsg* ageLoaded = plAgeLoadedMsg::ConvertNoRef(msg);
if( ageLoaded && ageLoaded->fLoaded )
return INeedReRender();
if( plInitialAgeStateLoadedMsg::ConvertNoRef(msg) )
return INeedReRender();
plDynamicEnvMapMsg* cmd = plDynamicEnvMapMsg::ConvertNoRef(msg);
if( cmd )
{
if( cmd->fCmd & plDynamicEnvMapMsg::kSetPosition )
SetPosition(cmd->fPos);
if( cmd->fCmd & plDynamicEnvMapMsg::kSetHither )
SetHither(cmd->fHither);
if( cmd->fCmd & plDynamicEnvMapMsg::kSetFogStart )
SetFogStart(cmd->fFogStart);
if( cmd->fCmd & plDynamicEnvMapMsg::kSetYon )
SetYon(cmd->fYon);
if( cmd->fCmd & plDynamicEnvMapMsg::kSetColor )
SetColor(cmd->fColor);
if( cmd->fCmd & plDynamicEnvMapMsg::kSetRefresh )
SetRefreshRate(cmd->fRefresh);
// If we're going to ReRender, make sure we've gotten any
// parameter changes first.
if( cmd->fCmd & plDynamicEnvMapMsg::kReRender )
{
ISetupRenderRequests();
INeedReRender();
}
return true;
}
plGenRefMsg* refMsg = plGenRefMsg::ConvertNoRef(msg);
if( refMsg )
{
if( IOnRefMsg(refMsg) )
return true;
}
return plCubicRenderTarget::MsgReceive(msg);
}
hsBool plDynamicEnvMap::IOnRefMsg(plGenRefMsg* refMsg)
{
switch( refMsg->fType)
{
case kRefVisSet:
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
{
plVisRegion* reg = plVisRegion::ConvertNoRef(refMsg->GetRef());
int idx = fVisRegions.Find(reg);
if( reg && (fVisRegions.kMissingIndex == idx) )
{
fVisRegions.Append(reg);
fVisSet.SetBit(reg->GetIndex());
}
ISetupRenderRequests();
return true;
}
else
{
plVisRegion* reg = plVisRegion::ConvertNoRef(refMsg->GetRef());
int idx = fVisRegions.Find(reg);
if( reg && (fVisRegions.kMissingIndex != idx) )
{
fVisRegions.Remove(idx);
fVisSet.ClearBit(reg->GetIndex());
}
ISetupRenderRequests();
return true;
}
break;
case kRefRootNode:
plSceneObject *so = plSceneObject::ConvertNoRef(refMsg->GetRef());
if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace) )
fRootNode = so;
else
fRootNode = nil;
return true;
}
return false;
}
void plDynamicEnvMap::SetIncludeCharacters(hsBool b)
{
fIncCharacters = b;
if( b )
fVisSet.SetBit(plVisMgr::kCharacter);
else
fVisSet.ClearBit(plVisMgr::kCharacter);
}
void plDynamicEnvMap::AddVisRegion(plVisRegion* reg)
{
plGenRefMsg* msg = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnRequest, 0, kRefVisSet);
hsgResMgr::ResMgr()->AddViaNotify(reg->GetKey(), msg, plRefFlags::kActiveRef);
}
void plDynamicEnvMap::Read(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Read(s, mgr);
UInt32 sz = plCubicRenderTarget::Read(s);
fPos.Read(s);
fHither = s->ReadSwapScalar();
fYon = s->ReadSwapScalar();
fFogStart = s->ReadSwapScalar();
fColor.Read(s);
fRefreshRate = s->ReadSwapScalar();
SetPosition(fPos);
sz += sizeof(fPos) + sizeof(fHither) + sizeof(fYon) + sizeof(fFogStart) + sizeof(fColor) + sizeof(fRefreshRate);
fIncCharacters = s->ReadByte();
SetIncludeCharacters(fIncCharacters);
int nVis = s->ReadSwap32();
int i;
for( i = 0; i < nVis; i++ )
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefVisSet), plRefFlags::kActiveRef);
nVis = s->ReadSwap32();
for( i = 0; i < nVis; i++)
{
char *name = s->ReadSafeString();
plKey key = plKeyFinder::Instance().StupidSearch(nil, nil, plVisRegion::Index(), name);
delete[] name;
if (key)
hsgResMgr::ResMgr()->AddViaNotify(key, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefVisSet), plRefFlags::kActiveRef);
}
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefRootNode), plRefFlags::kActiveRef);
Init();
}
void plDynamicEnvMap::Write(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Write(s, mgr);
UInt32 sz = plCubicRenderTarget::Write(s);
fPos.Write(s);
s->WriteSwapScalar(fHither);
s->WriteSwapScalar(fYon);
s->WriteSwapScalar(fFogStart);
fColor.Write(s);
s->WriteSwapScalar(fRefreshRate);
sz += sizeof(fPos) + sizeof(fHither) + sizeof(fYon) + sizeof(fFogStart) + sizeof(fColor) + sizeof(fRefreshRate);
s->WriteByte(fIncCharacters);
s->WriteSwap32(fVisRegions.GetCount());
int i;
for( i = 0; i < fVisRegions.GetCount(); i++ )
mgr->WriteKey(s, fVisRegions[i]);
s->WriteSwap32(fVisRegionNames.Count());
for( i = 0; i < fVisRegionNames.Count(); i++)
{
s->WriteSafeString(fVisRegionNames[i]);
}
mgr->WriteKey(s, fRootNode);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
UInt8 plDynamicCamMap::fFlags = kReflectionEnabled | kReflectionCapable;
plDynamicCamMap::plDynamicCamMap() :
fHither(0.3f),
fYon(500.f),
fFogStart(1000.f),
fRefreshRate(0.f),
fLastRefresh(0.0),
fOutStanding(0),
fCamera(nil),
fRootNode(nil),
fIncCharacters(false),
fDisableTexture(nil)
{
fColor.Set(0,0,0,1.f);
fReqMsg = TRACKED_NEW plRenderRequestMsg(nil, &fReq);
}
plDynamicCamMap::plDynamicCamMap(UInt16 width, UInt16 height, UInt8 bitDepth, UInt8 zDepth, UInt8 sDepth) :
fHither(0.3f),
fYon(-1.f),
fFogStart(-1.f),
fRefreshRate(0.f),
fLastRefresh(0.0),
fOutStanding(0),
fCamera(nil),
fRootNode(nil),
fIncCharacters(false),
fDisableTexture(nil),
plRenderTarget(plRenderTarget::kIsTexture, width, height, bitDepth, zDepth, sDepth)
{
fColor.Set(0,0,0,1.f);
fReqMsg = TRACKED_NEW plRenderRequestMsg(nil, &fReq);
}
plDynamicCamMap::~plDynamicCamMap()
{
plgDispatch::Dispatch()->UnRegisterForExactType(plPipeRTMakeMsg::Index(), GetKey());
plgDispatch::Dispatch()->UnRegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
plgDispatch::Dispatch()->UnRegisterForExactType(plAgeLoadedMsg::Index(), GetKey());
plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());
SetDeviceRef(nil);
delete fReqMsg;
}
void plDynamicCamMap::Init()
{
plgDispatch::Dispatch()->RegisterForExactType(plPipeRTMakeMsg::Index(), GetKey());
plgDispatch::Dispatch()->RegisterForExactType(plInitialAgeStateLoadedMsg::Index(), GetKey());
plgDispatch::Dispatch()->RegisterForExactType(plAgeLoadedMsg::Index(), GetKey());
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
}
void plDynamicCamMap::SetRefreshRate(hsScalar secs)
{
fRefreshRate = secs;
plgDispatch::Dispatch()->RegisterForExactType(plRenderMsg::Index(), GetKey());
}
void plDynamicCamMap::ISetupRenderRequest(plPipeline *pipe)
{
fReq.SetRenderState(plPipeline::kRenderNormal | plPipeline::kRenderClearColor | plPipeline::kRenderClearDepth);
fReq.SetDrawableMask(plDrawable::kNormal);
fReq.SetSubDrawableMask(plDrawable::kSubAllTypes);
fReq.SetHither(fHither);
fReq.SetYon(fYon);
fReq.SetFogStart(fFogStart);
// For a reflection map, this must match the camera FOV, or else the camera based
// texture coordinates for the reflection texture will be off.
//
// For a fixed camera, you might want to use the height in both params, so that
// you're rendering a square FOV into your square texture. In practice, the artists
// don't mind the visual results when just scaling their UVs, so I'll leave it the
// same for both cases.
fReq.SetFovX(fCamera ? fCamera->GetFOVw() : plVirtualCam1::Instance()->GetFOVw());
fReq.SetFovY(fCamera ? fCamera->GetFOVh() : plVirtualCam1::Instance()->GetFOVh());
fReq.SetClearColor(fColor);
fReq.SetClearDepth(1.f);
fReq.SetClearDrawable(nil);
fReq.SetRenderTarget(this);
fReq.SetVisForce(fVisSet);
fReq.SetIgnoreOccluders(true);
fReq.RequestAck(GetKey());
hsMatrix44 w2c, c2w;
if (fCamera)
{
w2c.MakeCamera(&fCamera->GetTargetPos(), &fCamera->GetTargetPOA(), &hsVector3(0.f, 0.f, 1.f));
w2c.GetInverse(&c2w);
}
else
{
if (!fRootNode)
return;
// Could be optimized, but the matrix construction work here seems cheap relative to the cost
// of rerendering all this stuff to a separate target, so I doubt we'd notice.
hsMatrix44 invert;
invert.MakeScaleMat(&(hsVector3(1.f, 1.f, -1.f)));
w2c = pipe->GetWorldToCamera();
c2w = pipe->GetCameraToWorld();
w2c = w2c * fRootNode->GetLocalToWorld() * invert * fRootNode->GetWorldToLocal();
c2w = fRootNode->GetWorldToLocal() * invert * fRootNode->GetLocalToWorld() * c2w;
}
fReq.SetCameraTransform(w2c, c2w);
}
void plDynamicCamMap::ISubmitRenderRequest(plPipeline *pipe)
{
ISetupRenderRequest(pipe);
fReqMsg->SendAndKeep();
fOutStanding++;
fLastRefresh = hsTimer::GetSysSeconds();
}
void plDynamicCamMap::ICheckForRefresh(double t, plPipeline *pipe)
{
int i;
hsBool useRefl = (fFlags & kReflectionMask) == kReflectionMask;
if (!fCamera)
{
if ((useRefl && fMatLayers[0]->GetTexture() != this) || (!useRefl && fMatLayers[0]->GetTexture() != fDisableTexture))
IPrepTextureLayers();
}
// So no one's using us, eh? Hitting this condition is likely a bug,
// but an assert every frame would be annoying. We'll notice when
// the render target never updates.
if (fTargetNodes.GetCount() == 0)
return;
// If dynamic planar reflections are disabled and we're using our substitute
// texture, don't update. Otherwise, this particular reflection is forced to
// always display.
if (!useRefl && fDisableTexture)
return;
hsBool inView = false;
for (i = 0; i < fTargetNodes.GetCount(); i++)
{
if (pipe->TestVisibleWorld(fTargetNodes[i]))
{
inView = true;
break;
}
}
if (!inView)
return;
if( fLastRefresh <= 0 )
{
ISubmitRenderRequest(pipe);
return;
}
if( fRefreshRate <= 0 )
return;
#ifndef PLASMA_EXTERNAL_RELEASE
if (pipe->IsDebugFlagSet(plPipeDbg::kFlagNVPerfHUD) && hsTimer::GetDelSysSeconds() == 0)
{
ISubmitRenderRequest(pipe);
}
#endif // PLASMA_EXTERNAL_RELEASE
if (t > fLastRefresh + fRefreshRate)
{
ISubmitRenderRequest(pipe);
return;
}
}
hsBool plDynamicCamMap::INeedReRender()
{
fOutStanding = 0;
fLastRefresh = 0;
return true;
}
hsBool plDynamicCamMap::MsgReceive(plMessage* msg)
{
plRenderRequestAck* ack = plRenderRequestAck::ConvertNoRef(msg);
if( ack )
{
fOutStanding--;
return true;
}
plRenderMsg* rendMsg = plRenderMsg::ConvertNoRef(msg);
if( rendMsg )
{
if( fOutStanding )
INeedReRender();
ICheckForRefresh(hsTimer::GetSysSeconds(), rendMsg->Pipeline());
return true;
}
if( plPipeRTMakeMsg::ConvertNoRef(msg) )
{
INeedReRender();
plRenderTarget::MsgReceive(msg);
return true;
}
plAgeLoadedMsg* ageLoaded = plAgeLoadedMsg::ConvertNoRef(msg);
if( ageLoaded && ageLoaded->fLoaded )
return INeedReRender();
if( plInitialAgeStateLoadedMsg::ConvertNoRef(msg) )
return INeedReRender();
plDynamicEnvMapMsg* cmd = plDynamicEnvMapMsg::ConvertNoRef(msg);
if( cmd )
{
if( cmd->fCmd & plDynamicEnvMapMsg::kSetFogStart )
fFogStart = cmd->fFogStart;
if( cmd->fCmd & plDynamicEnvMapMsg::kSetColor )
fColor = cmd->fColor;
if( cmd->fCmd & plDynamicEnvMapMsg::kSetRefresh )
SetRefreshRate(cmd->fRefresh);
return true;
}
plRefMsg* refMsg = plRefMsg::ConvertNoRef(msg);
if( refMsg )
{
if( IOnRefMsg(refMsg) )
return true;
}
return plRenderTarget::MsgReceive(msg);
}
void plDynamicCamMap::IPrepTextureLayers()
{
if (fDisableTexture)
{
int i;
for (i = 0; i < fMatLayers.GetCount(); i++)
{
if ((fFlags & kReflectionMask) == kReflectionMask)
{
fMatLayers[i]->SetUVWSrc(plLayerInterface::kUVWPosition);
fMatLayers[i]->SetMiscFlags(hsGMatState::kMiscCam2Screen | hsGMatState::kMiscPerspProjection);
hsgResMgr::ResMgr()->SendRef(GetKey(), TRACKED_NEW plGenRefMsg(fMatLayers[i]->GetKey(), plRefMsg::kOnRequest, 0, plLayRefMsg::kTexture), plRefFlags::kActiveRef);
}
else
{
fMatLayers[i]->SetUVWSrc(0);
fMatLayers[i]->SetMiscFlags(0);
hsgResMgr::ResMgr()->SendRef(fDisableTexture->GetKey(), TRACKED_NEW plGenRefMsg(fMatLayers[i]->GetKey(), plRefMsg::kOnRequest, 0, plLayRefMsg::kTexture), plRefFlags::kActiveRef);
}
}
}
}
hsBool plDynamicCamMap::IOnRefMsg(plRefMsg* refMsg)
{
plGenRefMsg* genRefMsg = plGenRefMsg::ConvertNoRef(refMsg);
if (genRefMsg)
{
if (genRefMsg->fType == kRefVisSet)
{
plVisRegion* reg = plVisRegion::ConvertNoRef(refMsg->GetRef());
if (reg)
{
int idx = fVisRegions.Find(reg);
if ((refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace)) && fVisRegions.kMissingIndex == idx)
{
fVisRegions.Append(reg);
fVisSet.SetBit(reg->GetIndex());
}
else if (!(refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace)) && fVisRegions.kMissingIndex != idx)
{
fVisRegions.Remove(idx);
fVisSet.ClearBit(reg->GetIndex());
}
return true;
}
}
else if (genRefMsg->fType == kRefCamera)
{
plCameraModifier1 *cam = plCameraModifier1::ConvertNoRef(refMsg->GetRef());
if (cam)
{
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
fCamera = cam;
else
fCamera = nil;
return true;
}
}
else if (genRefMsg->fType == kRefRootNode)
{
plSceneObject *so = plSceneObject::ConvertNoRef(refMsg->GetRef());
if (so)
{
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
fRootNode = so;
else
fRootNode = nil;
return true;
}
}
else if (genRefMsg->fType == kRefTargetNode)
{
plSceneObject *so = plSceneObject::ConvertNoRef(refMsg->GetRef());
if (so)
{
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
{
if (fTargetNodes.Find(so) == fTargetNodes.kMissingIndex)
fTargetNodes.Append(so);
}
else
{
fTargetNodes.RemoveItem(so);
}
return true;
}
}
else if (genRefMsg->fType == kRefDisableTexture)
{
plBitmap *bitmap = plBitmap::ConvertNoRef(refMsg->GetRef());
if (bitmap)
{
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
fDisableTexture = bitmap;
else
fDisableTexture = nil;
return true;
}
}
else if (genRefMsg->fType == kRefMatLayer)
{
plLayer *lay = plLayer::ConvertNoRef(refMsg->GetRef());
if (lay)
{
if (refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest|plRefMsg::kOnReplace))
{
if (fMatLayers.Find(lay) == fMatLayers.kMissingIndex)
fMatLayers.Append(lay);
}
else
{
fMatLayers.RemoveItem(lay);
}
return true;
}
}
}
return false;
}
void plDynamicCamMap::SetIncludeCharacters(hsBool b)
{
fIncCharacters = b;
if( b )
fVisSet.SetBit(plVisMgr::kCharacter);
else
fVisSet.ClearBit(plVisMgr::kCharacter);
}
void plDynamicCamMap::AddVisRegion(plVisRegion* reg)
{
hsgResMgr::ResMgr()->AddViaNotify( reg->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plGenRefMsg::kOnReplace, -1, kRefVisSet ), plRefFlags::kActiveRef );
}
void plDynamicCamMap::SetEnabled(hsBool enable)
{
if (enable)
fFlags |= kReflectionEnabled;
else
fFlags &= ~kReflectionEnabled;
}
void plDynamicCamMap::SetCapable(hsBool capable)
{
if (capable)
fFlags |= kReflectionCapable;
else
fFlags &= ~kReflectionCapable;
}
void plDynamicCamMap::Read(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Read(s, mgr);
plRenderTarget::Read(s);
fHither = s->ReadSwapScalar();
fYon = s->ReadSwapScalar();
fFogStart = s->ReadSwapScalar();
fColor.Read(s);
fRefreshRate = s->ReadSwapScalar();
fIncCharacters = s->ReadBool();
SetIncludeCharacters(fIncCharacters);
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefCamera), plRefFlags::kPassiveRef);
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefRootNode), plRefFlags::kActiveRef);
int numTargs = s->ReadByte();
int i;
for (i = 0; i < numTargs; i++)
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, i, kRefTargetNode), plRefFlags::kPassiveRef);
int nVis = s->ReadSwap32();
for( i = 0; i < nVis; i++ )
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefVisSet), plRefFlags::kActiveRef);
nVis = s->ReadSwap32();
for( i = 0; i < nVis; i++)
{
char *name = s->ReadSafeString();
plKey key = plKeyFinder::Instance().StupidSearch(nil, nil, plVisRegion::Index(), name);
delete[] name;
if (key)
hsgResMgr::ResMgr()->AddViaNotify(key, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, -1, kRefVisSet), plRefFlags::kActiveRef);
}
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefDisableTexture), plRefFlags::kActiveRef);
UInt8 numLayers = s->ReadByte();
for (i = 0; i < numLayers; i++)
{
mgr->ReadKeyNotifyMe(s, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kRefMatLayer), plRefFlags::kPassiveRef);
}
Init();
}
void plDynamicCamMap::Write(hsStream* s, hsResMgr* mgr)
{
hsKeyedObject::Write(s, mgr);
plRenderTarget::Write(s);
s->WriteSwapScalar(fHither);
s->WriteSwapScalar(fYon);
s->WriteSwapScalar(fFogStart);
fColor.Write(s);
s->WriteSwapScalar(fRefreshRate);
s->WriteByte(fIncCharacters);
mgr->WriteKey(s, (fCamera ? fCamera->GetKey() : nil));
mgr->WriteKey(s, (fRootNode ? fRootNode->GetKey() : nil));
s->WriteByte(fTargetNodes.GetCount());
int i;
for (i = 0; i < fTargetNodes.GetCount(); i++)
mgr->WriteKey(s, fTargetNodes[i]);
s->WriteSwap32(fVisRegions.GetCount());
for( i = 0; i < fVisRegions.GetCount(); i++ )
mgr->WriteKey(s, fVisRegions[i]);
s->WriteSwap32(fVisRegionNames.Count());
for( i = 0; i < fVisRegionNames.Count(); i++)
{
s->WriteSafeString(fVisRegionNames[i]);
}
mgr->WriteKey(s, fDisableTexture ? fDisableTexture->GetKey() : nil);
s->WriteByte(fMatLayers.GetCount());
for (i = 0; i < fMatLayers.GetCount(); i++)
{
mgr->WriteKey(s, fMatLayers[i]->GetKey());
}
}

View File

@ -0,0 +1,209 @@
/*==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 plDynamicEnvMap_inc
#define plDynamicEnvMap_inc
#include "plCubicRenderTarget.h"
#include "../plScene/plRenderRequest.h"
#include "hsBitVector.h"
class plRenderRequestMsg;
class hsStream;
class plMessage;
class plVisRegion;
class plGenRefMsg;
class hsResMgr;
class plCameraModifier1;
class plSceneObject;
class plBitmap;
class plLayer;
class plDynamicEnvMap : public plCubicRenderTarget
{
public:
enum {
kRefVisSet,
kRefRootNode,
};
protected:
plRenderRequest fReqs[6];
plRenderRequestMsg* fReqMsgs[6];
plSceneObject* fRootNode;
hsPoint3 fPos;
hsScalar fHither;
hsScalar fYon;
hsScalar fFogStart;
hsColorRGBA fColor;
hsScalar fRefreshRate;
double fLastRefresh;
int fLastRender;
int fOutStanding;
hsBitVector fVisSet;
hsTArray<plVisRegion*> fVisRegions;
hsTArray<char *> fVisRegionNames;
hsBool fIncCharacters;
void IUpdatePosition();
hsBool INeedReRender();
void ISetupRenderRequests();
void ISubmitRenderRequests();
void ISubmitRenderRequest(int i);
void ICheckForRefresh(double t, plPipeline *pipe);
hsBool IOnRefMsg(plGenRefMsg* refMsg);
public:
plDynamicEnvMap();
plDynamicEnvMap(UInt16 width, UInt16 height, UInt8 bitDepth, UInt8 zDepth = -1, UInt8 sDepth = -1);
virtual ~plDynamicEnvMap();
CLASSNAME_REGISTER( plDynamicEnvMap );
GETINTERFACE_ANY( plDynamicEnvMap, plCubicRenderTarget );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
void ReRender();
void Init();
void SetPosition(const hsPoint3& pos);
void SetHither(hsScalar f);
void SetYon(hsScalar f);
void SetFogStart(hsScalar f);
void SetColor(const hsColorRGBA& col);
void SetRefreshRate(hsScalar secs);
hsPoint3 GetPosition() const;
hsScalar GetHither() const { return fHither; }
hsScalar GetYon() const { return fYon; }
hsScalar GetFogStart() const { return fFogStart; }
hsColorRGBA GetColor() const { return fColor; }
hsScalar GetRefreshRate() const { return 6.f * fRefreshRate; }
void AddVisRegion(plVisRegion* reg); // Will just send a ref
void SetIncludeCharacters(hsBool b);
hsBool GetIncludeCharacters() const { return fIncCharacters; }
void SetVisRegionName(char *name){ fVisRegionNames.Push(name); }
};
////////////////////////////////////////////////////////////////////////////
// Yes, it's lame that a lot of this code is nearly the same as
// plDynamicEnvMap, but this derives from plRenderTarget, not plCubicRenderTarget
// and I don't want to touch multiple inheritance.
class plDynamicCamMap : public plRenderTarget
{
public:
enum
{
kRefVisSet,
kRefCamera,
kRefRootNode,
kRefTargetNode,
kRefDisableTexture,
kRefMatLayer,
};
hsScalar fHither;
hsScalar fYon;
hsScalar fFogStart;
hsColorRGBA fColor;
protected:
plRenderRequest fReq;
plRenderRequestMsg* fReqMsg;
hsScalar fRefreshRate;
double fLastRefresh;
int fOutStanding;
hsBitVector fVisSet;
hsTArray<plVisRegion*> fVisRegions;
hsTArray<char *> fVisRegionNames; // this allows us to specify vis-regions in other pages.
hsBool fIncCharacters;
plCameraModifier1* fCamera;
plSceneObject* fRootNode;
hsTArray<plSceneObject*> fTargetNodes;
// Extra info for swapping around textures when reflections are disabled.
plBitmap* fDisableTexture;
hsTArray<plLayer*> fMatLayers;
static UInt8 fFlags;
enum
{
kReflectionCapable = 0x01,
kReflectionEnabled = 0x02,
kReflectionMask = kReflectionCapable | kReflectionEnabled,
};
hsBool INeedReRender();
void ISetupRenderRequest(plPipeline *pipe);
void ISubmitRenderRequest(plPipeline *pipe);
void ICheckForRefresh(double t, plPipeline *pipe);
void IPrepTextureLayers();
hsBool IOnRefMsg(plRefMsg* refMsg);
public:
plDynamicCamMap();
plDynamicCamMap(UInt16 width, UInt16 height, UInt8 bitDepth, UInt8 zDepth = -1, UInt8 sDepth = -1);
virtual ~plDynamicCamMap();
CLASSNAME_REGISTER( plDynamicCamMap );
GETINTERFACE_ANY( plDynamicCamMap, plRenderTarget );
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual hsBool MsgReceive(plMessage* msg);
void ReRender();
void Init();
void SetIncludeCharacters(hsBool b);
void SetRefreshRate(hsScalar secs);
void AddVisRegion(plVisRegion* reg);
void SetVisRegionName(char *name){ fVisRegionNames.Push(name); }
static hsBool GetEnabled() { return (fFlags & kReflectionEnabled) != 0; }
static void SetEnabled(hsBool enable);
static hsBool GetCapable() { return (fFlags & kReflectionCapable) != 0; }
static void SetCapable(hsBool capable);
};
#endif // plDynamicEnvMap_inc

View File

@ -0,0 +1,197 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plFogEnvironment.cpp - Functions for the fog volume class //
// //
//////////////////////////////////////////////////////////////////////////////
#include "plFogEnvironment.h"
#include "plTweak.h"
//// Constructors & Destructor ///////////////////////////////////////////////
plFogEnvironment::plFogEnvironment()
{
fType = kNoFog;
}
plFogEnvironment::plFogEnvironment( hsScalar start, hsScalar end, hsScalar density, hsColorRGBA &color )
{
Set( start, end, density, &color );
}
plFogEnvironment::plFogEnvironment( FogType type, hsScalar end, hsScalar density, hsColorRGBA &color )
{
SetExp( type, end, density, &color );
}
plFogEnvironment::~plFogEnvironment()
{
}
//// Set /////////////////////////////////////////////////////////////////////
void plFogEnvironment::Set( hsScalar start, hsScalar end, hsScalar density, const hsColorRGBA *color )
{
if( density <= 0.f )
{
fType = kNoFog;
fStart = 0.f;
fEnd = 0.f;
fDensity = 0.f;
}
else
{
fType = kLinearFog;
fStart = start;
fEnd = end;
fDensity = density;
}
if( color != nil )
fColor = *color;
}
void plFogEnvironment::SetExp( FogType type, hsScalar end, hsScalar density, const hsColorRGBA *color )
{
hsAssert( type == kExpFog || type == kExp2Fog, "Invalid fog type passed to plFogEnvironment" );
if( density <= 0.f )
{
fType = kNoFog;
fStart = 0.f;
fEnd = 0.f;
fDensity = 0.f;
}
else
{
fType = type;
fStart = 0.0f;
fEnd = end;
fDensity = density;
}
if( color != nil )
fColor = *color;
}
//// GetParameters ///////////////////////////////////////////////////////////
// Gets the parameters. Sets start to 0 if the type is not linear (can be
// nil).
void plFogEnvironment::GetParameters( hsScalar *start, hsScalar *end, hsScalar *density, hsColorRGBA *color )
{
hsAssert( fType != kLinearFog || start != nil, "Trying to get non-linear paramters on linear fog!" );
hsAssert( end != nil && density != nil && color != nil, "Bad pointer to plFogEnvironment::GetParameters()" );
if( fType == kLinearFog )
*start = fStart;
else if( start != nil )
*start = 0.0f;
*end = fEnd;
*density = fDensity;
*color = fColor;
}
//// GetPipelineParams ///////////////////////////////////////////////////////
// Gets linear pipeline (DX8) specific parameters. Basically massages our
// interface values into values that DX8 can use. In this case, we simply
// scale our end value out by the density. The whole formula is:
// pipelineEnd = ( end - start ) / density + start
void plFogEnvironment::GetPipelineParams( hsScalar *start, hsScalar *end, hsColorRGBA *color )
{
// hsAssert( fType == kLinearFog, "Getting linear pipeline params on non-linear fog!" );
*color = fColor;
switch(fType)
{
case kLinearFog:
*start = fStart;
*end = (fEnd - fStart) / fDensity + fStart;
break;
case kExpFog:
{
plConst(float) kKnee(0.0f);
*start = fEnd * kKnee;
*end = (fEnd - *start) / fDensity + *start;
}
break;
default:
case kExp2Fog:
{
plConst(float) kKnee(0.3f);
*start = fEnd * kKnee;
*end = (fEnd - *start) / fDensity + *start;
}
break;
}
}
//// GetPipelineParams ///////////////////////////////////////////////////////
// Gets exp/exp^2 pipeline (DX8) specific parameters. Basically massages our
// interface values into values that DX8 can use. In this case, we're going
// to modulate the density by the end value so that it actually ends at the
// right spot.
void plFogEnvironment::GetPipelineParams( hsScalar *density, hsColorRGBA *color )
{
const float ln256 = logf( 256.f );
const float sqrtLn256 = sqrtf( ln256 );
hsAssert( fType == kExpFog || fType == kExp2Fog, "Getting non-linear pipeline params on linear fog!" );
*density = ( ( fType == kExpFog ) ? ln256: sqrtLn256 ) * fDensity / fEnd;
*color = fColor;
}
//// Read ////////////////////////////////////////////////////////////////////
void plFogEnvironment::Read( hsStream *s, hsResMgr *mgr )
{
hsKeyedObject::Read( s, mgr );
fType = s->ReadByte();
fStart = s->ReadSwapFloat();
fEnd = s->ReadSwapFloat();
fDensity = s->ReadSwapFloat();
fColor.Read( s );
}
//// Write ///////////////////////////////////////////////////////////////////
void plFogEnvironment::Write( hsStream *s, hsResMgr *mgr )
{
hsKeyedObject::Write( s, mgr );
s->WriteByte( fType );
s->WriteSwapFloat( fStart );
s->WriteSwapFloat( fEnd );
s->WriteSwapFloat( fDensity );
fColor.Write( s );
}

View File

@ -0,0 +1,104 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plFogEnvironment.h - Header file for the fog environment class //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plFogEnvironment_h
#define _plFogEnvironment_h
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsTypes.h"
#include "hsColorRGBA.h"
#include "hsTemplates.h"
#include "hsUtils.h"
//// plFogEnvironment Class Definition ////////////////////////////////////////////
// Defines a fog environment. Bite me.
class plFogEnvironment : public hsKeyedObject
{
protected:
UInt8 fType;
hsScalar fStart; // Used for linear fog only
hsScalar fEnd, fDensity; // Always used!
hsColorRGBA fColor;
public:
CLASSNAME_REGISTER( plFogEnvironment );
GETINTERFACE_ANY( plFogEnvironment, hsKeyedObject );
enum FogType
{
kLinearFog = 0,
kExpFog,
kExp2Fog,
kNoFog
};
plFogEnvironment();
plFogEnvironment( hsScalar start, hsScalar end, hsScalar density, hsColorRGBA &color );
plFogEnvironment( FogType type, hsScalar end, hsScalar density, hsColorRGBA &color );
~plFogEnvironment();
// Sets the parameters for linear fog
void Set( hsScalar start, hsScalar end, hsScalar density, const hsColorRGBA *color = nil );
// Sets the parameters for exp or exp^2 fog
void SetExp( FogType type, hsScalar end, hsScalar density, const hsColorRGBA *color = nil );
// Sets the color
void SetColor( hsColorRGBA &color ) { fColor = color; }
// Clear the environment to no fog
void Clear( void ) { fType = kNoFog; }
// Gets the type
UInt8 GetType( void ) { return fType; }
// Gets the color
hsColorRGBA &GetColor( void ) { return fColor; }
// Gets the parameters. Sets start to 0 if the type is not linear (can be nil)
void GetParameters( hsScalar *start, hsScalar *end, hsScalar *density, hsColorRGBA *color );
// Gets linear pipeline (DX) specific parameters.
void GetPipelineParams( hsScalar *start, hsScalar *end, hsColorRGBA *color );
// Gets exp or exp^2 pipeline (DX) specific parameters.
void GetPipelineParams( hsScalar *density, hsColorRGBA *color );
virtual void Read(hsStream *s, hsResMgr *mgr);
virtual void Write(hsStream *s, hsResMgr *mgr);
};
#endif //_plFogEnvironment_h

View File

@ -0,0 +1,292 @@
/*==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

View File

@ -0,0 +1,73 @@
/*==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 plPipeDebugFlags_inc
#define plPipeDebugFlags_inc
namespace plPipeDbg
{
// Debug flags
enum DebugFlags
{
kFlagReload,
kFlagShowAllBounds,
kFlagNoMultitexture,
kFlagNoLightmaps,
kFlagNoRuntimeLights,
kFlagOcclusionSnap,
kFlagNoAlphaBlending,
kFlagNoDecals,
kFlagDontSortFaces,
kFlagDisableSpecular,
kFlagOverlayWire,
kFlagShowNormals,
kFlagColorizeMipmaps,
kFlagSingleMat,
kFlagSkipVisDist,
kFlagNoPlates,
kFlagNoShadows,
kFlagNoUpperLayers,
kFlagNoProjLights,
kFlagNoSkinning,
kFlagBumpUV,
kFlagBumpW,
kFlagNoBump,
kFlagNoRender,
kFlagNoAnisotropy,
kFlagAllBright,
kFlagNoApplyProjLights,
kFlagOnlyApplyProjLights,
kFlagShowShadowBounds,
kFlagNoAuxSpans,
kFlagNoShadowApply,
kFlagNoPreShade,
kFlagNVPerfHUD,
kFlagNoFog,
};
}
#endif // plPipeDebugFlags_inc

View File

@ -0,0 +1,66 @@
/*==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 plPipelineCreatable_inc
#define plPipelineCreatable_inc
#include "../pnFactory/plCreator.h"
#include <d3d9.h>
#include "plDXPipeline.h"
REGISTER_NONCREATABLE( plDXPipeline );
#include "hsFogControl.h"
REGISTER_NONCREATABLE( hsFogControl );
#include "plFogEnvironment.h"
REGISTER_CREATABLE( plFogEnvironment );
#include "plRenderTarget.h"
REGISTER_CREATABLE( plRenderTarget );
#include "plCubicRenderTarget.h"
REGISTER_CREATABLE( plCubicRenderTarget );
#include "plCubicRenderTargetModifier.h"
REGISTER_CREATABLE( plCubicRenderTargetModifier );
#include "plTransitionMgr.h"
REGISTER_CREATABLE( plTransitionMgr );
#include "plDynamicEnvMap.h"
REGISTER_CREATABLE( plDynamicEnvMap );
REGISTER_CREATABLE( plDynamicCamMap );
#endif // plPipelineCreatable_inc

View File

@ -0,0 +1,75 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plPipelineCreate Class Header //
// Cyan, Inc. //
// //
// Here's a fun static class. All it does is contain wrapper functions for //
// returning pointers to new pipelines of various types. This way, someone //
// else, say, plClient, can create a new plDXPipeline without having to //
// include every DX header in the known universe. Its messy and there's //
// probably a better way to do it with the resource manager, but neither //
// Chris nor Matt can tell me what it is, so there. :P //
// //
// Note: complile-time trick is that the actual functions for these are //
// in the pipeline sources themselves. Makes more sense, esp. since we //
// then avoid any possible header conflict between the pipelines, should //
// one ever exist. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 3.8.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plPipelineCreate_h
#define _plPipelineCreate_h
//// plPipelineCreate Class Definition ////////////////////////////////////////
class plPipeline;
class plPipelineCreate
{
protected:
static plPipeline *ICreateDXPipeline( hsWinRef hWnd, const hsG3DDeviceModeRecord *devMode );
public:
static plPipeline *CreatePipeline( hsWinRef hWnd, const hsG3DDeviceModeRecord *devMode )
{
// Just this for now. Later we'll key off of the devMode
return ICreateDXPipeline( hWnd, devMode );
}
};
#endif // _plPipelineCreate_h

View File

@ -0,0 +1,236 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plPlates - Header file for the plates and plPlateManager //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plPlates_h
#define _plPlates_h
#include "hsTypes.h"
#include "hsStlUtils.h"
#include "hsColorRGBA.h"
#include "hsTemplates.h"
#include "hsUtils.h"
#include "hsMatrix44.h"
//// plPlate Class Definition ////////////////////////////////////////////////
// plPlate is the actual plate object that represents one plate on the
// screen. It has a transform matrix (which includes position, scale and
// rotation), a material, a depth value and a color that is applied to all
// four corners. All plates are parallelograms.
class plPlateManager;
class hsGMaterial;
class plMipmap;
class plBitmap;
class plPlate
{
friend class plPlateManager;
protected:
hsMatrix44 fXformMatrix;
hsGMaterial *fMaterial;
plMipmap *fMipmap;
hsScalar fDepth, fOpacity;
UInt32 fFlags;
char fTitle[ 64 ];
plPlate *fNext;
plPlate **fPrevPtr;
plPlate **fOwningHandle;
static UInt32 fMagicUniqueKeyInt;
plPlate( plPlate** owningHandle );
virtual ~plPlate();
void ILink( plPlate **back );
void IUnlink( void )
{
hsAssert( fPrevPtr, "Plate not in list" );
if( fNext )
fNext->fPrevPtr = fPrevPtr;
*fPrevPtr = fNext;
fNext = nil;
fPrevPtr = nil;
}
void ISetResourceAlphas(UInt32 colorKey);
public:
enum
{
kFlagVisible = 0x00000001,
kFlagLocalMaterial = 0x00000002,
kFlagIsAGraph = 0x00000004
};
/// Basic properties
void SetTransform( hsMatrix44 &matrix, hsBool reSort = true );
void SetMaterial( hsGMaterial *material );
void SetTexture(plBitmap *texture); // Creates a new single layer material to use the texture.
void SetTitle( const char *title ) { if( title != nil ) strncpy( fTitle, title, sizeof( fTitle ) ); else fTitle[ 0 ] = 0; }
hsGMaterial *GetMaterial( void ) { return fMaterial; }
hsMatrix44 &GetTransform( void ) { return fXformMatrix; }
const char *GetTitle( void ) { return fTitle; }
UInt32 GetFlags( void ) { return fFlags; }
void SetVisible( hsBool vis ) { if( vis ) fFlags |= kFlagVisible; else fFlags &= ~kFlagVisible; }
hsBool IsVisible( void );
void SetOpacity( hsScalar opacity = 1.f );
plPlate *GetNext( void ) { return fNext; }
/// Helper functions
void SetDepth( hsScalar depth) { fDepth = depth; }
void SetPosition( hsScalar x, hsScalar y, hsScalar z = -1.0f );
void SetSize( hsScalar width, hsScalar height, bool adjustByAspectRatio = false );
plMipmap *CreateMaterial( UInt32 width, UInt32 height, hsBool withAlpha, plMipmap* texture = NULL );
void CreateFromResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void ReloadFromResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void CreateFromJPEGResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
void ReloadFromJPEGResource( const char *resName, UInt32 colorKey = 0x00ff00ff );
};
//// plGraphPlate Class Definition ///////////////////////////////////////////
// A derivation of plPlate that maintains a procedural texture which displays
// a scrolling graph of data.
class plGraphPlate : public plPlate
{
protected:
UInt32 fBGHexColor, fAxesHexColor, fGraphHexColor;
std::vector<UInt32> fDataHexColors;
UInt32 fMin, fMax, fLabelMin, fLabelMax;
std::vector<Int32> fLastValues;
std::vector<std::string> fLabelText;
UInt32 IMakePow2( UInt32 value );
void IDrawNumber( UInt32 number, UInt32 *dataPtr, UInt32 stride, UInt32 color );
void IDrawDigit( char digit, UInt32 *dataPtr, UInt32 stride, UInt32 color );
public:
plGraphPlate( plPlate **owningHandle );
virtual ~plGraphPlate();
void SetDataRange( UInt32 min, UInt32 max, UInt32 width );
void SetDataLabels( UInt32 min, UInt32 max );
void SetLabelText( char *text1, char *text2 = nil, char *text3 = nil, char *text4 = nil );
void SetLabelText( const std::vector<std::string> & text );
void ClearData( void );
void AddData( Int32 value, Int32 value2 = -1, Int32 value3 = -1, Int32 value4 = -1 );
void AddData( std::vector<Int32> values );
void SetColors( UInt32 bgHexColor = 0x80000000, UInt32 axesHexColor = 0xffffffff, UInt32 dataHexColor = 0xff00ff00, UInt32 graphHexColor = 0x80ff0000 );
void SetDataColors( UInt32 hexColor1 = 0xff00ff00, UInt32 hexColor2 = 0xff0000ff, UInt32 hexColor3 = 0xffffff00, UInt32 hexColor4 = 0xffff00ff );
void SetDataColors( const std::vector<UInt32> & hexColors );
const char *GetLabelText( int i ) { return fLabelText[ i ].c_str(); }
const UInt32 GetDataColor( int i ) { return fDataHexColors[ i ]; }
const UInt32 GetNumLabels() { return fLabelText.size(); }
const UInt32 GetNumColors() { return fDataHexColors.size(); }
};
//// plPlateManager Class Definition /////////////////////////////////////////
// This class handles all the plates--it keeps track of all the plates,
// creates and destroys them, and draws them when the pipeline tells it to.
class plPipeline;
class plPlateManager
{
friend class plPlate;
private:
static plPlateManager *fInstance;
protected:
plPlate *fPlates;
plPipeline *fOwner;
hsBool fCreatedSucessfully;
plPlateManager( plPipeline *pipe )
{
fInstance = this;
fPlates = nil;
fOwner = pipe;
fCreatedSucessfully = true;
}
virtual void IDrawToDevice( plPipeline *pipe ) = 0;
void IResortPlate( plPlate *plate, bool fromCurrent );
public:
virtual ~plPlateManager();
static plPlateManager &Instance( void ) { return *fInstance; }
static bool InstanceValid( void ) { return fInstance != nil; }
void CreatePlate( plPlate **handle );
void CreatePlate( plPlate **handle, hsScalar width, hsScalar height );
void CreatePlate( plPlate **handle, hsScalar x, hsScalar y, hsScalar width, hsScalar height );
void CreateGraphPlate( plGraphPlate **handle );
void DestroyPlate( plPlate *plate );
void SetPlateScreenPos( plPlate *plate, UInt32 x, UInt32 y );
void SetPlatePixelSize( plPlate *plate, UInt32 pWidth, UInt32 pHeight );
UInt32 GetPipeWidth( void );
UInt32 GetPipeHeight( void );
void DrawToDevice( plPipeline *pipe );
hsBool IsValid( void ) { return fCreatedSucessfully; }
};
// Sets the hInstance that we load our resources from. A SceneViewer hack.
void SetHInstance(void *instance);
#endif //_plPlates_h

View File

@ -0,0 +1,189 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plRenderTarget.cpp - RenderTarget functions //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 7.19.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plRenderTarget.h"
#include "plCubicRenderTarget.h"
#include "hsStream.h"
#include "hsGDeviceRef.h"
#include "plPipeline.h"
#include "plgDispatch.h"
#include "../pnMessage/plPipeResMakeMsg.h"
///////////////////////////////////////////////////////////////////////////////
//// plRenderTarget Functions /////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void plRenderTarget::SetKey(plKey k)
{
hsKeyedObject::SetKey(k);
if( k )
{
if( !fParent )
plgDispatch::Dispatch()->RegisterForExactType( plPipeRTMakeMsg::Index(), GetKey() );
}
}
hsBool plRenderTarget::MsgReceive(plMessage* msg)
{
plPipeRTMakeMsg* make = plPipeRTMakeMsg::ConvertNoRef(msg);
if( make )
{
if( !GetDeviceRef() || GetDeviceRef()->IsDirty() )
{
make->Pipeline()->MakeRenderTargetRef(this);
}
return true;
}
return plBitmap::MsgReceive(msg);
}
UInt32 plRenderTarget::Read( hsStream *s )
{
UInt32 total = plBitmap::Read( s );
fWidth = s->ReadSwap16();
fHeight = s->ReadSwap16();
fProportionalViewport = s->ReadBool();
if( fProportionalViewport )
{
fViewport.fProportional.fLeft = s->ReadSwapScalar();
fViewport.fProportional.fTop = s->ReadSwapScalar();
fViewport.fProportional.fRight = s->ReadSwapScalar();
fViewport.fProportional.fBottom = s->ReadSwapScalar();
}
else
{
fViewport.fAbsolute.fLeft = s->ReadSwap16();
fViewport.fAbsolute.fTop = s->ReadSwap16();
fViewport.fAbsolute.fRight = s->ReadSwap16();
fViewport.fAbsolute.fBottom = s->ReadSwap16();
}
fZDepth = s->ReadByte();
fStencilDepth = s->ReadByte();
return total + 2 * 2 + 2 + 4 * ( fProportionalViewport ? sizeof( hsScalar ) : sizeof( UInt16 ) ) + sizeof( hsBool );
}
UInt32 plRenderTarget::Write( hsStream *s )
{
UInt32 total = plBitmap::Write( s );
s->WriteSwap16( fWidth );
s->WriteSwap16( fHeight );
s->WriteBool( fProportionalViewport );
if( fProportionalViewport )
{
s->WriteSwapScalar( fViewport.fProportional.fLeft );
s->WriteSwapScalar( fViewport.fProportional.fTop );
s->WriteSwapScalar( fViewport.fProportional.fRight );
s->WriteSwapScalar( fViewport.fProportional.fBottom );
}
else
{
s->WriteSwap16( fViewport.fAbsolute.fLeft );
s->WriteSwap16( fViewport.fAbsolute.fTop );
s->WriteSwap16( fViewport.fAbsolute.fRight );
s->WriteSwap16( fViewport.fAbsolute.fBottom );
}
s->WriteByte( fZDepth );
s->WriteByte( fStencilDepth );
return total + 2 * 2 + 2 + 4 * ( fProportionalViewport ? sizeof( hsScalar ) : sizeof( UInt16 ) ) + sizeof( hsBool );
}
///////////////////////////////////////////////////////////////////////////////
//// plCubicRenderTarget Functions ////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
UInt32 plCubicRenderTarget::Read( hsStream *s )
{
int i;
UInt32 total = plRenderTarget::Read( s );
for( i = 0; i < 6; i++ )
{
if( fFaces[ i ] == nil )
fFaces[ i ] = TRACKED_NEW plRenderTarget();
fFaces[ i ]->fParent = this;
total += fFaces[ i ]->Read( s );
}
return total;
}
UInt32 plCubicRenderTarget::Write( hsStream *s )
{
int i;
UInt32 total = plRenderTarget::Write( s );
for( i = 0; i < 6; i++ )
{
total += fFaces[ i ]->Write( s );
}
return total;
}
UInt32 plCubicRenderTarget::GetTotalSize( void ) const
{
UInt32 size = 0, i;
for( i = 0; i < 6; i++ )
{
if( fFaces[ i ] != nil )
size += fFaces[ i ]->GetTotalSize();
}
return size;
}
//// SetCameraMatrix //////////////////////////////////////////////////////////
void plCubicRenderTarget::SetCameraMatrix(const hsPoint3& pos)
{
hsMatrix44::MakeEnvMapMatrices(pos, fWorldToCameras, fCameraToWorlds);
}

View File

@ -0,0 +1,189 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plRenderTarget.h - Header file for the plRenderTarget class //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 5.21.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plRenderTarget_h
#define _plRenderTarget_h
#include "plPipeResReq.h"
#include "../plGImage/plBitmap.h"
#define ASSERT_ABSOLUTE hsAssert( !fProportionalViewport, "Cannot perform this on a proportional RenderTarget" );
#define ASSERT_PROPORTIONAL hsAssert( fProportionalViewport, "Cannot perform this on an absolute RenderTarget" );
//// Class Definition /////////////////////////////////////////////////////////
class hsGDeviceRef;
class plCubicRenderTarget;
class plRenderTarget : public plBitmap
{
friend plCubicRenderTarget;
protected:
UInt16 fWidth, fHeight;
union
{
struct
{
UInt16 fLeft, fTop, fRight, fBottom;
} fAbsolute;
struct
{
hsScalar fLeft, fTop, fRight, fBottom;
} fProportional;
} fViewport;
hsBool fApplyTexQuality;
hsBool fProportionalViewport;
UInt8 fZDepth, fStencilDepth;
plCubicRenderTarget *fParent;
virtual void SetKey(plKey k);
virtual UInt32 Read( hsStream *s );
virtual UInt32 Write( hsStream *s );
public:
CLASSNAME_REGISTER( plRenderTarget );
GETINTERFACE_ANY( plRenderTarget, plBitmap );
plRenderTarget()
{
fWidth = 0;
fHeight = 0;
fPixelSize = 0;
fZDepth = 0;
fStencilDepth = 0;
fApplyTexQuality = false;
fProportionalViewport = true;
SetViewport( 0, 0, 1.f, 1.f );
fFlags = 0;
fParent = nil;
plPipeResReq::Request();
}
plRenderTarget( UInt16 flags, UInt16 width, UInt16 height, UInt8 bitDepth, UInt8 zDepth = 0xff, UInt8 stencilDepth = 0xff )
{
fWidth = width;
fHeight = height;
fPixelSize = bitDepth;
fZDepth = ( zDepth != 0xff ) ? zDepth : (bitDepth > 16 ? 24 : 16);
fStencilDepth = ( stencilDepth != 0xff ) ? stencilDepth : 0;
fFlags = flags;
fParent = nil;
hsAssert( fFlags & (kIsTexture|kIsOffscreen), "Cannot perform this on an on-screen RenderTarget" );
fApplyTexQuality = false;
fProportionalViewport = false;
SetViewport( 0, 0, width, height );
plPipeResReq::Request();
}
// Render-to-Screen constructor
plRenderTarget( UInt16 flags, hsScalar left, hsScalar top, hsScalar right, hsScalar bottom, UInt8 bitDepth, UInt8 zDepth = 0xff, UInt8 stencilDepth = 0xff )
{
fWidth = 0; // Can't really set these, at least not yet
fHeight = 0;
fPixelSize = bitDepth;
fZDepth = ( zDepth != 0xff ) ? zDepth : 16;
fStencilDepth = ( stencilDepth != 0xff ) ? stencilDepth : 0;
fFlags = flags;
fParent = nil;
hsAssert( !( fFlags & (kIsTexture|kIsOffscreen) ), "Cannot perform this on an offscreen RenderTarget" );
fApplyTexQuality = false;
fProportionalViewport = true;
SetViewport( left, top, right, bottom );
plPipeResReq::Request();
}
virtual ~plRenderTarget() {}
virtual void SetViewport( UInt16 left, UInt16 top, UInt16 right, UInt16 bottom )
{
ASSERT_ABSOLUTE;
fViewport.fAbsolute.fLeft = left;
fViewport.fAbsolute.fTop = top;
fViewport.fAbsolute.fRight = right;
fViewport.fAbsolute.fBottom = bottom;
}
virtual void SetViewport( hsScalar left, hsScalar top, hsScalar right, hsScalar bottom )
{
ASSERT_PROPORTIONAL;
fViewport.fProportional.fLeft = left;
fViewport.fProportional.fTop = top;
fViewport.fProportional.fRight = right;
fViewport.fProportional.fBottom = bottom;
}
UInt16 GetWidth( void ) { return fWidth; }
UInt16 GetHeight( void ) { return fHeight; }
UInt8 GetZDepth( void ) { return fZDepth; }
UInt8 GetStencilDepth( void ) { return fStencilDepth; }
UInt16 GetVPLeft( void ) { ASSERT_ABSOLUTE; return fViewport.fAbsolute.fLeft; }
UInt16 GetVPTop( void ) { ASSERT_ABSOLUTE; return fViewport.fAbsolute.fTop; }
UInt16 GetVPRight( void ) { ASSERT_ABSOLUTE; return fViewport.fAbsolute.fRight; }
UInt16 GetVPBottom( void ) { ASSERT_ABSOLUTE; return fViewport.fAbsolute.fBottom; }
hsScalar GetVPLeftProp( void ) { ASSERT_PROPORTIONAL; return fViewport.fProportional.fLeft; }
hsScalar GetVPTopProp( void ) { ASSERT_PROPORTIONAL; return fViewport.fProportional.fTop; }
hsScalar GetVPRightProp( void ) { ASSERT_PROPORTIONAL; return fViewport.fProportional.fRight; }
hsScalar GetVPBottomProp( void ) { ASSERT_PROPORTIONAL; return fViewport.fProportional.fBottom; }
hsBool ViewIsProportional( void ) const { return fProportionalViewport; }
plCubicRenderTarget *GetParent( void ) const { return fParent; }
virtual UInt32 GetTotalSize( void ) const { return fWidth * fHeight * ( fPixelSize >> 3 ); }
virtual hsBool MsgReceive(plMessage* msg);
virtual void SetVisRegionName(char *name){} // override to set vis region names for anyone who cares
};
#endif // _plRenderTarget_h

View File

@ -0,0 +1,112 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plStatusLogDrawer class //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "plStatusLogDrawer.h"
#include "plPipeline.h"
#include "plDebugText.h"
#include "../plStatusLog/plStatusLog.h"
//// Draw ////////////////////////////////////////////////////////////////////
void plStatusLogDrawer::IDrawLogNames(plStatusLog* curLog, plStatusLog* firstLog)
{
plDebugText& drawText = plDebugText::Instance();
UInt32 width = 0, numLogs = 0;
plStatusLog* iLog = firstLog;
while (iLog)
{
width = hsMaximum(drawText.CalcStringWidth(iLog->GetFileName()) + 4, width);
iLog = iLog->fNext;
numLogs++;
}
UInt32 height = drawText.GetFontHeight() + 2;
drawText.DrawRect(0, 0, (UInt16)width, (UInt16)(height*numLogs), 0, 0, 0);
UInt32 yPos = 0;
iLog = firstLog;
while (iLog)
{
if (iLog == curLog)
drawText.DrawString(2, (UInt16)yPos, iLog->GetFileName(), 0, 255, 0);
else
drawText.DrawString(2, (UInt16)yPos, iLog->GetFileName());
iLog = iLog->fNext;
yPos += height;
}
}
void plStatusLogDrawer::Draw(plStatusLog* curLog, plStatusLog* firstLog)
{
int i, x, y, width, height, lineHt;
plDebugText &drawText = plDebugText::Instance();
/// Calc position on screen
lineHt = drawText.GetFontHeight() + 2;
height = lineHt * ( IGetMaxNumLines( curLog ) + 2 ) + 8;
if( IGetFlags( curLog ) & plStatusLog::kAlignToTop )
{
width = fPipeline->Width() - 8;
x = 4;
y = 4;
}
else
{
width = fPipeline->Width() >> 1;
x = width - 10;
y = ( fPipeline->Height() - height ) >> 1;
}
/// Draw!
if( IGetFlags( curLog ) & plStatusLog::kFilledBackground )
drawText.DrawRect( x, y, x + width, y + height, 0, 0, 0, 127 );
drawText.DrawString( x + 2, y + ( lineHt >> 1 ), IGetFilename( curLog ), 127, 127, 255, 255, plDebugText::kStyleBold );
drawText.DrawRect( x + 2, y + ( lineHt << 1 ) + 1,
x + width - 8, y + ( lineHt << 1 ) + 2, 127, 127, 255, 255 );
y += lineHt * 2;
for( i = 0; i < IGetMaxNumLines( curLog ); i++ )
{
if( IGetLines( curLog )[ i ] != nil )
drawText.DrawString( x + 4, y, IGetLines( curLog )[ i ], IGetColors( curLog )[ i ] );
y += lineHt;
}
if (firstLog)
IDrawLogNames(curLog, firstLog);
}

View File

@ -0,0 +1,58 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plStatusLogDrawer class //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plStatusLogDrawer_h
#define _plStatusLogDrawer_h
#include "../plStatusLog/plStatusLog.h"
//// plStatusLogDrawer Class Definition ////////////////////////////////////////////
class plPipeline;
class plStatusLogDrawer : public plStatusLogDrawerStub
{
protected:
plPipeline *fPipeline;
void IDrawLogNames(plStatusLog* curLog, plStatusLog* firstLog);
public:
plStatusLogDrawer( plPipeline *pipe ) : fPipeline( pipe ) {}
virtual ~plStatusLogDrawer() {}
virtual void Draw(plStatusLog* curLog, plStatusLog* firstLog);
};
#endif //_plStatusLogDrawer_h

View File

@ -0,0 +1,87 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plStencil.h - Header for various stencil settings and enums //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 5.17.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plStencil_h
#define _plStencil_h
#include "hsTypes.h"
//// Stencil Caps /////////////////////////////////////////////////////////////
class plStencilCaps
{
public:
enum Depths
{
kDepth1Bit = 0x01,
kDepth4Bits = 0x02,
kDepth8Bits = 0x04
};
enum CompareFuncs
{
kCmpNever = 0,
kCmpLessThan,
kCmpEqual,
kCmpLessThanOrEqual,
kCmpGreaterThan,
kCmpNotEqual,
kCmpGreaterThanOrEqual,
kCmpAlways
};
enum Ops
{
kOpKeep = 0x01,
kOpSetToZero = 0x02,
kOpReplace = 0x04,
kOpIncClamp = 0x08,
kOpDecClamp = 0x10,
kOpInvert = 0x20,
kOpIncWrap = 0x40,
kOpDecWrap = 0x80
};
hsBool fIsSupported;
UInt8 fSupportedDepths;
UInt8 fSupportedOps;
};
#endif // _plStencil_h

View File

@ -0,0 +1,431 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plTextFont Class Functions //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 2.19.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsWindows.h"
#include "HeadSpin.h"
#include "plTextFont.h"
#include "plDebugText.h"
#define DisplayableChar(c) (c >= 0 && c <= 128)
//// Constructor & Destructor /////////////////////////////////////////////////
plTextFont::plTextFont( plPipeline *pipe )
{
fMaxNumIndices = 1024;
fInitialized = false;
fPipe = pipe;
}
plTextFont::~plTextFont()
{
IUnlink();
}
//// IInitFontTexture /////////////////////////////////////////////////////////
UInt16 *plTextFont::IInitFontTexture( void )
{
int nHeight, x, y, c;
char myChar[ 2 ] = "x";
UInt16 *tBits;
DWORD *bitmapBits;
BITMAPINFO bmi;
HDC hDC;
HBITMAP hBitmap;
HFONT hFont;
SIZE size;
BYTE bAlpha;
// Figure out our texture size
if( fSize > 40 )
fTextureWidth = fTextureHeight = 1024;
else if( fSize > 20 )
fTextureWidth = fTextureHeight = 512;
else
fTextureWidth = fTextureHeight = 256;
// Create a new DC and bitmap that we can draw characters to
memset( &bmi.bmiHeader, 0, sizeof( BITMAPINFOHEADER ) );
bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
bmi.bmiHeader.biWidth = fTextureWidth;
bmi.bmiHeader.biHeight = -(int)fTextureHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;
hDC = CreateCompatibleDC( nil );
hBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, (void **)&bitmapBits, nil, 0 );
SetMapMode( hDC, MM_TEXT );
nHeight = -MulDiv( fSize, GetDeviceCaps( hDC, LOGPIXELSY ), 72 );
fFontHeight = -nHeight;
hFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, fFace );
hsAssert( hFont != nil, "Cannot create Windows font" );
SelectObject( hDC, hBitmap );
SelectObject( hDC, hFont );
// Set text colors
SetTextColor( hDC, RGB( 255, 255, 255 ) );
SetBkColor( hDC, 0 );
SetTextAlign( hDC, TA_TOP );
// Loop through characters, drawing them one at a time
RECT r;
r.left = r.top = 0;
r.right = r.bottom = 10;
FillRect( hDC, &r, (HBRUSH)GetStockObject( GRAY_BRUSH ) );
// (Make first character a black dot, for filling rectangles)
SetPixel( hDC, 0, 0, RGB( 255, 255, 255 ) );
for( c = 32, x = 1, y = 0; c < 127; c++ )
{
myChar[ 0 ] = c;
GetTextExtentPoint32( hDC, myChar, 1, &size );
if( (UInt32)( x + size.cx + 1 ) > fTextureWidth )
{
x = 0;
y += size.cy + 1;
}
ExtTextOut( hDC, x, y, ETO_OPAQUE, nil, myChar, 1, nil );
fCharInfo[ c ].fW = (UInt16)size.cx;
fCharInfo[ c ].fH = (UInt16)size.cy;
fCharInfo[ c ].fUVs[ 0 ].fX = (float)x / (float)fTextureWidth;
fCharInfo[ c ].fUVs[ 0 ].fY = (float)y / (float)fTextureHeight;
fCharInfo[ c ].fUVs[ 1 ].fX = (float)( x + size.cx ) / (float)fTextureWidth;
fCharInfo[ c ].fUVs[ 1 ].fY = (float)( y + size.cy ) / (float)fTextureHeight;
fCharInfo[ c ].fUVs[ 0 ].fZ = fCharInfo[ c ].fUVs[ 1 ].fZ = 0;
x += size.cx + 1;
}
fCharInfo[ 32 ].fUVs[ 1 ].fX = fCharInfo[ 32 ].fUVs[ 0 ].fX;
// Special case the tab key
fCharInfo[ '\t' ].fUVs[ 1 ].fX = fCharInfo[ '\t' ].fUVs[ 0 ].fX = fCharInfo[ 32 ].fUVs[ 0 ].fX;
fCharInfo[ '\t' ].fUVs[ 1 ].fY = fCharInfo[ '\t' ].fUVs[ 0 ].fY = 0;
fCharInfo[ '\t' ].fUVs[ 0 ].fZ = fCharInfo[ '\t' ].fUVs[ 1 ].fZ = 0;
fCharInfo[ '\t' ].fW = fCharInfo[ 32 ].fW * 4;
fCharInfo[ '\t' ].fH = fCharInfo[ 32 ].fH;
/// Now create the data block
UInt16 *data = TRACKED_NEW UInt16[ fTextureWidth * fTextureHeight ];
tBits = data;
for( y = 0; y < fTextureHeight; y++ )
{
for( x = 0; x < fTextureWidth; x++ )
{
bAlpha = (BYTE)( ( bitmapBits[ fTextureWidth * y + x ] & 0xff ) >> 4 );
if( bitmapBits[ fTextureWidth * y + x ] )
*tBits = 0xffff;
else
*tBits = 0;
tBits++;
}
}
// Cleanup and return
DeleteObject( hBitmap );
DeleteDC( hDC );
DeleteObject( hFont );
return data;
}
//// Create ///////////////////////////////////////////////////////////////////
void plTextFont::Create( char *face, UInt16 size )
{
// Init normal stuff
strncpy( fFace, face, sizeof( fFace ) );
fSize = size;
}
//// IInitObjects /////////////////////////////////////////////////////////////
void plTextFont::IInitObjects( void )
{
UInt16 *data;
// Create texture
data = IInitFontTexture();
hsAssert( data != nil, "Cannot create font texture" );
ICreateTexture( data );
delete [] data;
// Create state blocks
IInitStateBlocks();
fInitialized = true;
}
//// DrawString ///////////////////////////////////////////////////////////////
void plTextFont::DrawString( const char *string, int sX, int sY, UInt32 hexColor,
UInt8 style, UInt32 rightEdge )
{
static hsTArray<plFontVertex> verts;
int i, j, width, height, count, thisCount, italOffset;
float x = (float)sX;
char c, *strPtr;
if( !fInitialized )
IInitObjects();
/// Set up to draw
italOffset = ( style & plDebugText::kStyleItalic ) ? fSize / 2: 0;
count = strlen( string );
strPtr = (char *)string;
while( count > 0 )
{
thisCount = ( count > 64 ) ? 64 : count;
count -= thisCount;
// Create an array for our vertices
verts.SetCountAndZero( thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ) );
// Fill them all up now
for( i = 0; i < thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ); i++ )
{
verts[ i ].fColor = hexColor;
verts[ i ].fPoint.fZ = 0;
}
for( i = 0, j = 0; i < thisCount; i++, j += 6 )
{
c = strPtr[ i ];
// make sure its a character we will display
if ( DisplayableChar(c) )
{
width = fCharInfo[ c ].fW + 1;
height = fCharInfo[ c ].fH + 1;
if( rightEdge > 0 && x + width + italOffset >= rightEdge )
{
count = 0;
thisCount = i;
break;
}
verts[ j ].fPoint.fX = x + italOffset;
verts[ j ].fPoint.fY = (float)sY;
verts[ j ].fUV = fCharInfo[ c ].fUVs[ 0 ];
verts[ j + 1 ].fPoint.fX = x + width + italOffset;
verts[ j + 1 ].fPoint.fY = (float)sY;
verts[ j + 1 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
verts[ j + 1 ].fUV.fX = fCharInfo[ c ].fUVs[ 1 ].fX;
verts[ j + 2 ].fPoint.fX = x;
verts[ j + 2 ].fPoint.fY = (float)sY + height;
verts[ j + 2 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
verts[ j + 2 ].fUV.fY = fCharInfo[ c ].fUVs[ 1 ].fY;
verts[ j + 3 ].fPoint.fX = x;
verts[ j + 3 ].fPoint.fY = (float)sY + height;
verts[ j + 3 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
verts[ j + 3 ].fUV.fY = fCharInfo[ c ].fUVs[ 1 ].fY;
verts[ j + 4 ].fPoint.fX = x + width + italOffset;
verts[ j + 4 ].fPoint.fY = (float)sY;
verts[ j + 4 ].fUV = fCharInfo[ c ].fUVs[ 0 ];
verts[ j + 4 ].fUV.fX = fCharInfo[ c ].fUVs[ 1 ].fX;
verts[ j + 5 ].fPoint.fX = x + width;
verts[ j + 5 ].fPoint.fY = (float)sY + height;
verts[ j + 5 ].fUV = fCharInfo[ c ].fUVs[ 1 ];
x += width + 1;
}
}
if( thisCount == 0 )
break;
if( style & plDebugText::kStyleBold )
{
for( i = 0; i < thisCount * 6; i++, j++ )
{
verts[ j ] = verts[ i ];
verts[ j ].fPoint.fX = verts[ j ].fPoint.fX + 1.0f;
}
}
/// TEMPORARY DEBUG ONLY: see if we can catch this stupid random draw bug
#if 0
for( i = 0; i < thisCount * ( ( style & plDebugText::kStyleBold ) ? 12 : 6 ); i += 3 )
{
for( j = 0; j < 3; j++ )
{
hsAssert( verts[ i + j ].fPoint.fX >= 0, "Text point out of range" );
hsAssert( verts[ i + j ].fPoint.fY >= 0, "Text point out of range" );
hsAssert( verts[ i + j ].fPoint.fX < 1024, "Text point out of range" );
hsAssert( verts[ i + j ].fPoint.fY < 768, "Text point out of range" );
}
int lt = ( verts[ i ].fPoint.fX < verts[ i + 1 ].fPoint.fX ? verts[ i ].fPoint.fX : verts[ i + 1 ].fPoint.fX );
lt = ( verts[ i + 2 ].fPoint.fX < lt ? verts[ i + 2 ].fPoint.fX : lt );
int tp = ( verts[ i ].fPoint.fY < verts[ i + 1 ].fPoint.fY ? verts[ i ].fPoint.fY : verts[ i + 1 ].fPoint.fY );
tp = ( verts[ i + 2 ].fPoint.fY < tp ? verts[ i + 2 ].fPoint.fY : tp );
int rt = ( verts[ i ].fPoint.fX > verts[ i + 1 ].fPoint.fX ? verts[ i ].fPoint.fX : verts[ i + 1 ].fPoint.fX );
rt = ( verts[ i + 2 ].fPoint.fX > rt ? verts[ i + 2 ].fPoint.fX : rt );
int bt = ( verts[ i ].fPoint.fY > verts[ i + 1 ].fPoint.fY ? verts[ i ].fPoint.fY : verts[ i + 1 ].fPoint.fY );
bt = ( verts[ i + 2 ].fPoint.fY > bt ? verts[ i + 2 ].fPoint.fY : bt );
hsAssert( rt - lt < 32, "Text character too big" );
hsAssert( bt - tp < 32, "Text character too big" );
}
#endif
/// TEMPORARY DEBUG ONLY: see if we can catch this stupid random draw bug
/// Draw a set of tris now
IDrawPrimitive( thisCount * ( ( style & plDebugText::kStyleBold ) ? 4 : 2 ), verts.AcquireArray() );
strPtr += thisCount;
}
/// All done!
}
//// CalcStringWidth //////////////////////////////////////////////////////////
UInt32 plTextFont::CalcStringWidth( const char *string )
{
int i, width = 0;
if( !fInitialized )
IInitObjects();
for( i = 0; i < strlen( string ); i++ )
{
// make sure its a character we will display
if ( DisplayableChar(string[i]) )
width += fCharInfo[ string[ i ] ].fW + 2;
}
return width;
}
//// DrawRect /////////////////////////////////////////////////////////////////
// TEMPORARY function to draw a flat-shaded 2D rectangle to the screen. Used
// to create a background for our console; will be obliterated once we figure
// a better way to do so.
void plTextFont::DrawRect( int left, int top, int right, int bottom, UInt32 hexColor )
{
static hsTArray<plFontVertex> verts;
int i;
if( !fInitialized )
IInitObjects();
/// Draw!
verts.SetCountAndZero( 6 );
for( i = 0; i < 6; i++ )
{
verts[ i ].fColor = hexColor;
verts[ i ].fPoint.fZ = 0;
verts[ i ].fUV.fX = verts[ i ].fUV.fY = 0;
}
verts[ 0 ].fPoint.fX = verts[ 2 ].fPoint.fX = verts[ 3 ].fPoint.fX = (float)left;
verts[ 1 ].fPoint.fX = verts[ 4 ].fPoint.fX = verts[ 5 ].fPoint.fX = (float)right;
verts[ 0 ].fPoint.fY = verts[ 1 ].fPoint.fY = verts[ 4 ].fPoint.fY = (float)top;
verts[ 2 ].fPoint.fY = verts[ 3 ].fPoint.fY = verts[ 5 ].fPoint.fY = (float)bottom;
// omg I had this at 6...just slap the dunce cap on me...-mcn
IDrawPrimitive( 2, verts.AcquireArray() );
/// All done!
}
//// Draw3DBorder /////////////////////////////////////////////////////////////
// Draws a 3d border, upper-left with the first color, lower-right with the
// second. I just LOOOOVE temporary functions :)
// Note: this way sucks. Live with it.
void plTextFont::Draw3DBorder( int left, int top, int right, int bottom, UInt32 hexColor1, UInt32 hexColor2 )
{
static hsTArray<plFontVertex> verts;
int i;
if( !fInitialized )
IInitObjects();
/// Draw!
verts.SetCountAndZero( 8 );
for( i = 0; i < 8; i++ )
{
verts[ i ].fColor = hexColor1;
verts[ i ].fPoint.fZ = 0;
verts[ i ].fUV.fX = verts[ i ].fUV.fY = 0;
}
verts[ 1 ].fPoint.fX = verts[ 2 ].fPoint.fX = verts[ 3 ].fPoint.fX = verts[ 4 ].fPoint.fX = (float)left;
verts[ 0 ].fPoint.fX = verts[ 5 ].fPoint.fX = verts[ 6 ].fPoint.fX = verts[ 7 ].fPoint.fX = (float)right;
verts[ 0 ].fPoint.fY = verts[ 1 ].fPoint.fY = verts[ 2 ].fPoint.fY = verts[ 7 ].fPoint.fY = (float)top;
verts[ 3 ].fPoint.fY = verts[ 4 ].fPoint.fY = verts[ 5 ].fPoint.fY = verts[ 6 ].fPoint.fY = (float)bottom;
for( i = 4; i < 8; i++ )
verts[ i ].fColor = hexColor2;
IDrawLines( 4, verts.AcquireArray() );
/// All done!
}

View File

@ -0,0 +1,141 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plTextFont Class Header //
// Generic 3D text font handler //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 2.19.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plTextFont_h
#define _plTextFont_h
#include "hsTemplates.h"
#include "hsGeometry3.h"
//// plTextFont Class Definition //////////////////////////////////////////////
class plPipeline;
class plTextFont
{
protected:
struct plDXCharInfo
{
UInt16 fW, fH;
hsPoint3 fUVs[ 2 ];
};
struct plFontVertex
{
hsPoint3 fPoint;
UInt32 fColor;
hsPoint3 fUV;
plFontVertex& operator=(const int zero)
{
fPoint.Set(0,0,0);
fColor = 0;
fUV.Set(0,0,0);
return *this;
}
};
UInt32 fMaxNumIndices;
UInt32 fTextureWidth, fTextureHeight;
char fFace[ 128 ];
UInt16 fSize;
hsBool fInitialized;
UInt16 fFontHeight;
plPipeline *fPipe;
plTextFont *fNext;
plTextFont **fPrevPtr;
plDXCharInfo fCharInfo[ 128 ];
virtual void IInitObjects( void );
virtual void ICreateTexture( UInt16 *data ) = 0;
virtual void IInitStateBlocks( void ) = 0;
virtual void IDrawPrimitive( UInt32 count, plFontVertex *array ) = 0;
virtual void IDrawLines( UInt32 count, plFontVertex *array ) = 0;
UInt16 *IInitFontTexture( void );
void IUnlink( void )
{
hsAssert( fPrevPtr, "Font not in list" );
if( fNext )
fNext->fPrevPtr = fPrevPtr;
*fPrevPtr = fNext;
fNext = nil;
fPrevPtr = nil;
}
public:
plTextFont( plPipeline *pipe );
virtual ~plTextFont();
void Create( char *face, UInt16 size );
void DrawString( const char *string, int x, int y, UInt32 hexColor, UInt8 style, UInt32 rightEdge = 0 );
void DrawRect( int left, int top, int right, int bottom, UInt32 hexColor );
void Draw3DBorder( int left, int top, int right, int bottom, UInt32 hexColor1, UInt32 hexColor2 );
UInt32 CalcStringWidth( const char *string );
UInt32 GetFontSize( void ) { return fSize; }
UInt16 GetFontHeight() { return fFontHeight; }
virtual void DestroyObjects( void ) = 0;
virtual void SaveStates( void ) = 0;
virtual void RestoreStates( void ) = 0;
virtual void FlushDraws( void ) = 0;
void Link( plTextFont **back )
{
fNext = *back;
if( *back )
(*back)->fPrevPtr = &fNext;
fPrevPtr = back;
*back = this;
}
};
#endif // _plTextFont_h

View File

@ -0,0 +1,594 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plTextGenerator Class Functions //
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 12.13.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "hsWindows.h"
#include "hsTypes.h"
#include "hsMatrix44.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "plTextGenerator.h"
#include "../plGImage/plMipmap.h"
#include "../plPipeline/hsGDeviceRef.h"
#include "../pnMessage/plRefMsg.h"
#include "plgDispatch.h"
#include "hsResMgr.h"
// Because tempKeys haven't been fixed yet (mf says to blame Eric Ellis), reffing
// objects when we have a tempKey (or they have a tempKey) just don't work. In
// fact, it will do nasty things like crashing on shutdown. Until then, we simply
// won't do the refs. Note that this is BAD, but given the only time we currently
// use these objects are very limited, controlled cases that *should* be okay
// for now, we should be reasonably safe. For now.
//#define MCN_DO_REFS
//// Constructor & Destructor /////////////////////////////////////////////////
plTextGenerator::plTextGenerator()
{
fHost = nil;
}
plTextGenerator::plTextGenerator( plMipmap *host, UInt16 width, UInt16 height )
{
fHost = nil;
Attach( host, width, height );
}
plTextGenerator::~plTextGenerator()
{
// This also won't work until tempKeys work, since the mipmap will be gone by
// this time, in which case, calling Detach() crashes
#ifdef MCN_DO_REFS
Detach();
#endif
}
//// Attach ///////////////////////////////////////////////////////////////////
// Grab onto a plMipmap, suck the texture out of it and replace it with our
// own.
void plTextGenerator::Attach( plMipmap *host, UInt16 width, UInt16 height )
{
UInt16 textWidth, textHeight;
hsAssert( fHost == nil, "Attempting to attach an already attached plTextGenerator" );
fHost = host;
/// Suck the old texture data out
fHost->Reset();
/// Make some new
// Note that we need POW-2 textures, so we go for the next one up that will
// fit what we need
for( textWidth = 1; textWidth < width; textWidth <<= 1 );
for( textHeight = 1; textHeight < height; textHeight <<= 1 );
fWidth = width;
fHeight = height;
fHost->fImage = (void *)IAllocateOSSurface( textWidth, textHeight );
fHost->SetConfig( plMipmap::kARGB32Config );
fHost->fWidth = textWidth;
fHost->fHeight = textHeight;
fHost->fPixelSize = 32;
fHost->fRowBytes = textWidth * 4;
fHost->fNumLevels = 1;
fHost->fFlags |= plMipmap::kUserOwnsBitmap | plMipmap::kDontThrowAwayImage;
fHost->fCompressionType = plMipmap::kUncompressed;
fHost->fUncompressedInfo.fType = plMipmap::UncompressedInfo::kRGB8888;
fHost->IBuildLevelSizes();
fHost->fTotalSize = fHost->GetLevelSize( 0 );
// Destroy the old texture ref, since it's probably completely nutsoid at this point.
// This should force the pipeline to recreate one more suitable for our use
fHost->SetDeviceRef( nil );
// Some init color
hsColorRGBA color;
color.Set( 0.f, 0.f, 0.f, 1.f );
ClearToColor( color );
FlushToHost();
#ifdef MCN_DO_REFS
/// Of course, brilliantly enough, if we did an attach on the constructor, we don't have a key
/// yet, so we better give ourselves one before we can call AddViaNotify()
if( GetKey() == nil )
{
char str[ 256 ];
sprintf( str, "plTextGen:%s", fHost->GetKeyName() );
hsgResMgr::ResMgr()->NewKey( str, this, plLocation::kGlobalFixedLoc );
}
/// Send ourselves a passive ref of the mipmap, so we get notified if and when it goes away
hsgResMgr::ResMgr()->AddViaNotify( fHost->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, 0, 0 ), plRefFlags::kActiveRef );
#endif
/// All done!
}
//// IAllocateOSSurface ///////////////////////////////////////////////////////
// OS-specific. Allocates a rectangular bitmap of the given dimensions that
// the OS can draw text into. Returns a pointer to the pixels.
UInt32 *plTextGenerator::IAllocateOSSurface( UInt16 width, UInt16 height )
{
#if HS_BUILD_FOR_WIN32
BITMAPINFO bmi;
// Create a new DC and bitmap that we can draw characters to
memset( &bmi.bmiHeader, 0, sizeof( BITMAPINFOHEADER ) );
bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -(int)height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 32;
fWinRGBDC = CreateCompatibleDC( nil );
fWinRGBBitmap = CreateDIBSection( fWinRGBDC, &bmi, DIB_RGB_COLORS, (void **)&fWinRGBBits, nil, 0 );
SetMapMode( fWinRGBDC, MM_TEXT );
SetBkMode( fWinRGBDC, TRANSPARENT );
SetTextAlign( fWinRGBDC, TA_TOP | TA_LEFT );
SelectObject( fWinRGBDC, fWinRGBBitmap );
// Now create a second DC/bitmap combo, this one for writing alpha values to
memset( &bmi.bmiHeader, 0, sizeof( BITMAPINFOHEADER ) );
bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -(int)height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biBitCount = 8;
fWinAlphaDC = CreateCompatibleDC( nil );
fWinAlphaBitmap = CreateDIBSection( fWinAlphaDC, &bmi, DIB_RGB_COLORS, (void **)&fWinAlphaBits, nil, 0 );
SetMapMode( fWinAlphaDC, MM_TEXT );
SetBkMode( fWinAlphaDC, TRANSPARENT );
SetTextAlign( fWinAlphaDC, TA_TOP | TA_LEFT );
SelectObject( fWinAlphaDC, fWinAlphaBitmap );
return (UInt32 *)fWinRGBBits;
#endif
}
//// Detach ///////////////////////////////////////////////////////////////////
// Release the mipmap unto itself.
void plTextGenerator::Detach( void )
{
if( fHost == nil )
return;
// hsAssert( fHost != nil, "Attempting to detach unattached host" );
SetFont( nil, 0 );
IDestroyOSSurface();
fHost->Reset();
fHost->fFlags &= ~( plMipmap::kUserOwnsBitmap | plMipmap::kDontThrowAwayImage );
// Destroy the old texture ref, since we're no longer using it
fHost->SetDeviceRef( nil );
plMipmap *oldHost = fHost;
fHost = nil;
#ifdef MCN_DO_REFS
// Now send ourselves a unref msg, just in case we were called directly (if this was done by
// message, we'll get called a few times, but that's ok, we're set up to handle that, and it
// won't happen 'cept on destruction so the speed penalty shouldn't be a problem)
GetKey()->Release( oldHost->GetKey() );
#endif
}
//// IDestroyOSSurface ////////////////////////////////////////////////////////
// Opposite of allocate. DUH!
void plTextGenerator::IDestroyOSSurface( void )
{
#if HS_BUILD_FOR_WIN32
fHost->fImage = nil; // DeleteObject() will get rid of it for us
DeleteObject( fWinRGBBitmap );
DeleteDC( fWinRGBDC );
DeleteObject( fWinAlphaBitmap );
DeleteDC( fWinAlphaDC );
#endif
}
//// ClearToColor /////////////////////////////////////////////////////////////
void plTextGenerator::ClearToColor( hsColorRGBA &color )
{
int i;
UInt32 *data = (UInt32 *)fHost->fImage;
UInt32 hexColor = color.ToARGB32();
#if HS_BUILD_FOR_WIN32
GdiFlush();
#endif
for( i = 0; i < fHost->fWidth * fHost->fHeight; i++ )
data[ i ] = hexColor;
// Fill our alpha bitmap as well, since we use that too
#if HS_BUILD_FOR_WIN32
memset( fWinAlphaBits, (UInt8)( color.a * 255.f ), fHost->fWidth * fHost->fHeight );
#endif
}
//// SetFont //////////////////////////////////////////////////////////////////
// OS-specific. Load the given font for drawing the text with.
void plTextGenerator::SetFont( const char *face, UInt16 size, hsBool antiAliasRGB )
{
#if HS_BUILD_FOR_WIN32
if( fWinFont != nil )
{
DeleteObject( fWinFont );
fWinFont = nil;
}
if( fWinAlphaFont != nil )
{
DeleteObject( fWinAlphaFont );
fWinAlphaFont = nil;
}
if( face != nil )
{
int nHeight = -MulDiv( size, GetDeviceCaps( fWinRGBDC, LOGPIXELSY ), 72 );
fWinFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, antiAliasRGB ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, VARIABLE_PITCH, face );
hsAssert( fWinFont != nil, "Cannot create Windows font for plTextGenerator" );
// The font for the alpha channel is identical except that it's antialiased, whereas the RGB version isn't.
fWinAlphaFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, (!antiAliasRGB) ? ANTIALIASED_QUALITY : DEFAULT_QUALITY, VARIABLE_PITCH, face );
hsAssert( fWinAlphaFont != nil, "Cannot create Windows font for plTextGenerator" );
SelectObject( fWinRGBDC, fWinFont );
SelectObject( fWinAlphaDC, fWinAlphaFont );
}
#endif
}
//// SetTextColor /////////////////////////////////////////////////////////////
// blockRGB basically forces the RGB channel to write in blocks instead of
// actual characters. This isn't useful unless you're relying on the alpha
// channel to do the text (opaque text and transparent background), in which
// case you want plenty of block color in your RGB channel because it'll get
// alpha-ed out by the alpha channel.
void plTextGenerator::SetTextColor( hsColorRGBA &color, hsBool blockRGB )
{
#if HS_BUILD_FOR_WIN32
int r = (int)(color.r * 255.f);
int g = (int)(color.g * 255.f);
int b = (int)(color.b * 255.f);
int a = (int)(color.a * 255.f);
if( blockRGB )
{
::SetBkColor( fWinRGBDC, RGB( r, g, b ) );
::SetBkMode( fWinRGBDC, OPAQUE );
}
else
::SetBkMode( fWinRGBDC, TRANSPARENT );
::SetTextColor( fWinRGBDC, RGB( r, g, b ) );
::SetTextColor( fWinAlphaDC, RGB( a, a, a ) );
#endif
}
//// DrawString ///////////////////////////////////////////////////////////////
void plTextGenerator::DrawString( UInt16 x, UInt16 y, const char *text )
{
wchar_t *wText = hsStringToWString(text);
DrawString(x,y,wText);
delete [] wText;
}
void plTextGenerator::DrawString( UInt16 x, UInt16 y, const wchar_t *text )
{
#if HS_BUILD_FOR_WIN32
::TextOutW( fWinRGBDC, x, y, text, wcslen( text ) );
::TextOutW( fWinAlphaDC, x, y, text, wcslen( text ) );
#endif
}
//// DrawClippedString ////////////////////////////////////////////////////////
void plTextGenerator::DrawClippedString( Int16 x, Int16 y, const char *text, UInt16 width, UInt16 height )
{
wchar_t *wText = hsStringToWString(text);
DrawClippedString(x,y,wText,width,height);
delete [] wText;
}
void plTextGenerator::DrawClippedString( Int16 x, Int16 y, const wchar_t *text, UInt16 width, UInt16 height )
{
#if HS_BUILD_FOR_WIN32
RECT r;
::SetRect( &r, x, y, x + width, y + height );
::ExtTextOutW( fWinRGBDC, x, y, ETO_CLIPPED, &r, text, wcslen( text ), nil );
::ExtTextOutW( fWinAlphaDC, x, y, ETO_CLIPPED, &r, text, wcslen( text ), nil );
#endif
}
//// DrawClippedString ////////////////////////////////////////////////////////
void plTextGenerator::DrawClippedString( Int16 x, Int16 y, const char *text, UInt16 clipX, UInt16 clipY, UInt16 width, UInt16 height )
{
wchar_t *wText = hsStringToWString(text);
DrawClippedString(x,y,wText,clipX,clipY,width,height);
delete [] wText;
}
void plTextGenerator::DrawClippedString( Int16 x, Int16 y, const wchar_t *text, UInt16 clipX, UInt16 clipY, UInt16 width, UInt16 height )
{
#if HS_BUILD_FOR_WIN32
RECT r;
::SetRect( &r, clipX, clipY, clipX + width, clipY + height );
::ExtTextOutW( fWinRGBDC, x, y, ETO_CLIPPED, &r, text, wcslen( text ), nil );
::ExtTextOutW( fWinAlphaDC, x, y, ETO_CLIPPED, &r, text, wcslen( text ), nil );
#endif
}
//// DrawWrappedString ////////////////////////////////////////////////////////
void plTextGenerator::DrawWrappedString( UInt16 x, UInt16 y, const char *text, UInt16 width, UInt16 height )
{
wchar_t *wText = hsStringToWString(text);
DrawWrappedString(x,y,wText,width,height);
delete [] wText;
}
void plTextGenerator::DrawWrappedString( UInt16 x, UInt16 y, const wchar_t *text, UInt16 width, UInt16 height )
{
#if HS_BUILD_FOR_WIN32
RECT r;
::SetRect( &r, x, y, x + width, y + height );
// HBRUSH brush = ::CreateSolidBrush( RGB( 255, 255, 255 ) );
// ::FillRect( fWinRGBDC, &r, brush );
// ::DeleteObject( brush );
::DrawTextW( fWinRGBDC, text, wcslen( text ), &r,
DT_TOP | DT_LEFT | DT_NOPREFIX | DT_WORDBREAK );
::DrawTextW( fWinAlphaDC, text, wcslen( text ), &r,
DT_TOP | DT_LEFT | DT_NOPREFIX | DT_WORDBREAK );
#endif
}
//// CalcStringWidth //////////////////////////////////////////////////////////
UInt16 plTextGenerator::CalcStringWidth( const char *text, UInt16 *height )
{
wchar_t *wText = hsStringToWString(text);
UInt16 retVal = CalcStringWidth(wText,height);
delete [] wText;
return retVal;
}
UInt16 plTextGenerator::CalcStringWidth( const wchar_t *text, UInt16 *height )
{
#if HS_BUILD_FOR_WIN32
SIZE size;
::GetTextExtentPoint32W( fWinRGBDC, text, wcslen( text ), &size );
if( height != nil )
*height = (UInt16)size.cy;
return (UInt16)size.cx;
#endif
}
//// CalcWrappedStringSize ////////////////////////////////////////////////////
void plTextGenerator::CalcWrappedStringSize( const char *text, UInt16 *width, UInt16 *height )
{
wchar_t *wText = hsStringToWString(text);
CalcWrappedStringSize(wText,width,height);
delete [] wText;
}
void plTextGenerator::CalcWrappedStringSize( const wchar_t *text, UInt16 *width, UInt16 *height )
{
#if HS_BUILD_FOR_WIN32
RECT r;
::SetRect( &r, 0, 0, *width, 0 );
::DrawTextW( fWinRGBDC, text, wcslen( text ), &r, DT_TOP | DT_LEFT | DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT );
*width = (UInt16)(r.right);
if( height != nil )
*height = (UInt16)r.bottom;
#endif
}
//// FillRect /////////////////////////////////////////////////////////////////
void plTextGenerator::FillRect( UInt16 x, UInt16 y, UInt16 width, UInt16 height, hsColorRGBA &color )
{
#if HS_BUILD_FOR_WIN32
RECT rc;
::SetRect( &rc, x, y, x + width, y + height );
int r = (int)(color.r * 255.f);
int g = (int)(color.g * 255.f);
int b = (int)(color.b * 255.f);
int a = (int)(color.a * 255.f);
HBRUSH brush = ::CreateSolidBrush( RGB( r, g, b ) );
::FillRect( fWinRGBDC, &rc, brush );
::DeleteObject( brush );
brush = ::CreateSolidBrush( RGB( a, a, a ) );
::FillRect( fWinAlphaDC, &rc, brush );
::DeleteObject( brush );
#endif
}
//// FrameRect ////////////////////////////////////////////////////////////////
void plTextGenerator::FrameRect( UInt16 x, UInt16 y, UInt16 width, UInt16 height, hsColorRGBA &color )
{
#if HS_BUILD_FOR_WIN32
RECT rc;
::SetRect( &rc, x, y, x + width, y + height );
int r = (int)(color.r * 255.f);
int g = (int)(color.g * 255.f);
int b = (int)(color.b * 255.f);
int a = (int)(color.a * 255.f);
HBRUSH brush = ::CreateSolidBrush( RGB( r, g, b ) );
::FrameRect( fWinRGBDC, &rc, brush );
::DeleteObject( brush );
brush = ::CreateSolidBrush( RGB( a, a, a ) );
::FrameRect( fWinAlphaDC, &rc, brush );
::DeleteObject( brush );
#endif
}
//// FlushToHost //////////////////////////////////////////////////////////////
void plTextGenerator::FlushToHost( void )
{
#if HS_BUILD_FOR_WIN32
// Flush the GDI first, to make sure it's done
GdiFlush();
// Now copy our alpha channel over. I hate the GDI
UInt32 i = fHost->fWidth * fHost->fHeight;
UInt32 *dest = fWinRGBBits;
UInt8 *src = fWinAlphaBits;
/* while( i-- )
{
*dest &= 0x00ffffff;
*dest |= ( *src ) << 24;
// *dest |= ( *dest << 16 ) & 0xff000000;
dest++;
src++;
}
*/
do
{
i--;
dest[ i ] &= 0x00ffffff;
dest[ i ] |= src[ i ] << 24;
} while( i );
#endif
// Dirty the mipmap's deviceRef, if there is one
if( fHost->GetDeviceRef() != nil )
fHost->GetDeviceRef()->SetDirty( true );
}
//// GetTextWidth/Height //////////////////////////////////////////////////////
UInt16 plTextGenerator::GetTextWidth( void )
{
return ( fHost != nil ) ? (UInt16)(fHost->fWidth) : 0;
}
UInt16 plTextGenerator::GetTextHeight( void )
{
return ( fHost != nil ) ? (UInt16)(fHost->fHeight) : 0;
}
//// GetLayerTransform ////////////////////////////////////////////////////////
// Since the textGen can actually create a texture bigger than you were expecting,
// you want to be able to apply a layer texture transform that will compensate. This
// function will give you that transform. Just feed it into plLayer->SetTransform().
hsMatrix44 plTextGenerator::GetLayerTransform( void )
{
hsMatrix44 xform;
hsVector3 scale;
scale.Set( (float)GetWidth() / (float)GetTextWidth(),
(float)GetHeight() / (float)GetTextHeight(), 1.f );
xform.MakeScaleMat( &scale );
return xform;
}
//// MsgReceive ///////////////////////////////////////////////////////////////
hsBool plTextGenerator::MsgReceive( plMessage *msg )
{
#ifdef MCN_DO_REFS
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg );
if( refMsg != nil )
{
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest ) )
{
// Don't do anything--already did an attach
}
else if( refMsg->GetContext() & ( plRefMsg::kOnDestroy | plRefMsg::kOnRemove ) )
{
Detach();
}
return true;
}
#endif
return hsKeyedObject::MsgReceive( msg );
}

View File

@ -0,0 +1,124 @@
/*==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==*/
///////////////////////////////////////////////////////////////////////////////
// //
// plTextGenerator Class Header //
// Helper utility class that "attaches" to a mipmap and fills that mipmap //
// with text.
// Cyan, Inc. //
// //
//// Version History //////////////////////////////////////////////////////////
// //
// 12.13.2001 mcn - Created. //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef _plTextGenerator_h
#define _plTextGenerator_h
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "hsColorRGBA.h"
//// plTextGenerator Class Definition //////////////////////////////////////////////
class plMipmap;
struct hsMatrix44;
class plTextGenerator : public hsKeyedObject
{
protected:
plMipmap *fHost;
UInt16 fWidth, fHeight;
#if HS_BUILD_FOR_WIN32
HDC fWinRGBDC;
HBITMAP fWinRGBBitmap;
HFONT fWinFont;
UInt32 *fWinRGBBits;
HFONT fWinAlphaFont;
HDC fWinAlphaDC;
HBITMAP fWinAlphaBitmap;
UInt8 *fWinAlphaBits;
#endif
UInt32 *IAllocateOSSurface( UInt16 width, UInt16 height );
void IDestroyOSSurface( void );
public:
plTextGenerator();
plTextGenerator( plMipmap *host, UInt16 width, UInt16 height );
virtual ~plTextGenerator();
void Attach( plMipmap *host, UInt16 width, UInt16 height );
void Detach( void );
/// Operations to perform on the text block
void ClearToColor( hsColorRGBA &color );
void SetFont( const char *face, UInt16 size, hsBool antiAliasRGB = true );
void SetTextColor( hsColorRGBA &color, hsBool blockRGB = false );
void DrawString( UInt16 x, UInt16 y, const char *text );
void DrawString( UInt16 x, UInt16 y, const wchar_t *text );
void DrawClippedString( Int16 x, Int16 y, const char *text, UInt16 width, UInt16 height );
void DrawClippedString( Int16 x, Int16 y, const wchar_t *text, UInt16 width, UInt16 height );
void DrawClippedString( Int16 x, Int16 y, const char *text, UInt16 clipX, UInt16 clipY, UInt16 width, UInt16 height );
void DrawClippedString( Int16 x, Int16 y, const wchar_t *text, UInt16 clipX, UInt16 clipY, UInt16 width, UInt16 height );
void DrawWrappedString( UInt16 x, UInt16 y, const char *text, UInt16 width, UInt16 height );
void DrawWrappedString( UInt16 x, UInt16 y, const wchar_t *text, UInt16 width, UInt16 height );
UInt16 CalcStringWidth( const char *text, UInt16 *height = nil );
UInt16 CalcStringWidth( const wchar_t *text, UInt16 *height = nil );
void CalcWrappedStringSize( const char *text, UInt16 *width, UInt16 *height );
void CalcWrappedStringSize( const wchar_t *text, UInt16 *width, UInt16 *height );
void FillRect( UInt16 x, UInt16 y, UInt16 width, UInt16 height, hsColorRGBA &color );
void FrameRect( UInt16 x, UInt16 y, UInt16 width, UInt16 height, hsColorRGBA &color );
void FlushToHost( void );
UInt16 GetTextWidth( void );
UInt16 GetTextHeight( void );
UInt16 GetWidth( void ) { return fWidth; }
UInt16 GetHeight( void ) { return fHeight; }
// Since the textGen can actually create a texture bigger than you were expecting,
// you want to be able to apply a layer texture transform that will compensate. This
// function will give you that transform. Just feed it into plLayer->SetTransform().
hsMatrix44 GetLayerTransform( void );
virtual hsBool MsgReceive( plMessage *msg );
};
#endif // _plTextGenerator_h

View File

@ -0,0 +1,358 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plTransitionMgr - Class to handle fullscreen transitions (fades, etc) //
// //
// Note: eventually, I would like to drive these transitions on material //
// animations (it's just a big screen-covering plate with a material, //
// after all). This would allow the artists to specify their own //
// transitions and do really cool effects. However, that would require //
// somehow loading the materials in, and I'm not sure exactly how to do //
// that.... //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsWindows.h"
#include "hsTypes.h"
#include "plTransitionMgr.h"
#include "plPlates.h"
#include "../plGImage/plMipmap.h"
#include "../plSurface/plLayer.h"
#include "../plSurface/hsGMaterial.h"
#include "../plMessage/plLayRefMsg.h"
#include "../pnMessage/plRefMsg.h"
#include "../plMessage/plTransitionMsg.h"
#include "../pnMessage/plTimeMsg.h"
#include "../pnMessage/plEventCallbackMsg.h"
#include "../plMessage/plLinkToAgeMsg.h"
#include "plgDispatch.h"
#include "hsGDeviceRef.h"
#include "hsResMgr.h"
#include "hsTimer.h"
#include "../plAudio/plAudioSystem.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plNetClient/plLinkEffectsMgr.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plStatusLog/plStatusLog.h"
//// Constructor/Destructor //////////////////////////////////////////////////
plTransitionMgr::plTransitionMgr()
{
fEffectPlate = nil;
fCurrentEffect = kIdle;
fPlaying = false;
}
void plTransitionMgr::Init( void )
{
ICreatePlate();
plgDispatch::Dispatch()->RegisterForExactType( plTransitionMsg::Index(), GetKey() );
plgDispatch::Dispatch()->RegisterForExactType( plLinkEffectBCMsg::Index(), GetKey() );
}
plTransitionMgr::~plTransitionMgr()
{
int i;
for( i = 0; i < fCallbacks.GetCount(); i++ )
hsRefCnt_SafeUnRef( fCallbacks[ i ] );
if( fEffectPlate != nil )
plPlateManager::Instance().DestroyPlate( fEffectPlate );
if( fRegisteredForTime )
plgDispatch::Dispatch()->UnRegisterForExactType( plTimeMsg::Index(), GetKey() );
plgDispatch::Dispatch()->UnRegisterForExactType( plTransitionMsg::Index(), GetKey() );
plgDispatch::Dispatch()->UnRegisterForExactType( plLinkEffectBCMsg::Index(), GetKey() );
}
//// ICreatePlate ////////////////////////////////////////////////////////////
void plTransitionMgr::ICreatePlate( void )
{
int x, y;
fEffectPlate = nil;
// +0.01 to deal with the half-pixel antialiasing stuff
plPlateManager::Instance().CreatePlate( &fEffectPlate, 0, 0, 2.01, 2.01 );
fEffectPlate->SetDepth(2);
// hack for now--create a black layer that we will animate the opacity on
plMipmap *ourMip = fEffectPlate->CreateMaterial( 16, 16, true );
for( y = 0; y < ourMip->GetHeight(); y++ )
{
UInt32 *pixels = ourMip->GetAddr32( 0, y );
for( x = 0; x < ourMip->GetWidth(); x++ )
pixels[ x ] = 0xff000000;
}
fEffectPlate->SetVisible( false );
}
//// IStartFadeOut ///////////////////////////////////////////////////////////
void plTransitionMgr::IStartFadeOut( hsScalar lengthInSecs, UInt8 effect )
{
fCurrentEffect = effect; // default - kFadeOut;
fEffectLength = lengthInSecs;
// Special case for length 0--just jump straight to fadeout
if( lengthInSecs == 0.f )
{
fCurrOpacity = 1.f;
fLastTime = -1.f;
fPlaying = false;
plgAudioSys::SetGlobalFadeVolume( 0.f );
}
else
{
fCurrOpacity = 0;
fOpacDelta = 1.f / lengthInSecs;
fLastTime = -1.f;
fPlaying = true;
// Register for time message
plgDispatch::Dispatch()->RegisterForExactType( plTimeMsg::Index(), GetKey() );
fRegisteredForTime = true;
}
if( fEffectPlate == nil )
ICreatePlate();
fEffectPlate->SetVisible( true );
plLayer *layer = (plLayer *)fEffectPlate->GetMaterial()->GetLayer( 0 );
if( layer != nil )
{
layer->SetOpacity( fCurrOpacity );
}
}
//// IStartFadeIn ////////////////////////////////////////////////////////////
void plTransitionMgr::IStartFadeIn( hsScalar lengthInSecs, UInt8 effect )
{
fCurrentEffect = effect; // default - kFadeIn;
fEffectLength = lengthInSecs;
fCurrOpacity = 1.f;
fOpacDelta = -1.f / lengthInSecs;
fLastTime = -1.f;
fPlaying = true;
// Register for time message
plgDispatch::Dispatch()->RegisterForExactType( plTimeMsg::Index(), GetKey() );
fRegisteredForTime = true;
if( fEffectPlate == nil )
ICreatePlate();
fEffectPlate->SetVisible( true );
plLayer *layer = (plLayer *)fEffectPlate->GetMaterial()->GetLayer( 0 );
if( layer != nil )
{
layer->SetOpacity( fCurrOpacity );
}
}
//// IStop ///////////////////////////////////////////////////////////////////
void plTransitionMgr::IStop( hsBool aboutToStartAgain /*= false*/ )
{
int i;
plgDispatch::Dispatch()->UnRegisterForExactType( plTimeMsg::Index(), GetKey() );
fRegisteredForTime = false;
if( fPlaying )
{
if( !fHoldAtEnd && fEffectPlate != nil && !aboutToStartAgain )
fEffectPlate->SetVisible( false );
// finish the opacity to the end opacity
if( fEffectPlate != nil )
{
plLayer *layer = (plLayer *)fEffectPlate->GetMaterial()->GetLayer( 0 );
if( layer != nil )
{
layer->SetOpacity( (fCurrentEffect == kFadeIn || fCurrentEffect == kTransitionFadeIn) ? 0.f : 1.f );
}
}
if( !aboutToStartAgain )
{
if (!fNoSoundFade)
plgAudioSys::SetGlobalFadeVolume( (fCurrentEffect == kFadeIn || fCurrentEffect == kTransitionFadeIn) ? 1.f : 0.f );
}
for( i = 0; i < fCallbacks.GetCount(); i++ )
{
fCallbacks[ i ]->SetSender( GetKey() );
plgDispatch::MsgSend( fCallbacks[ i ] );
}
fCallbacks.Reset();
fPlaying = false;
}
}
//// MsgReceive //////////////////////////////////////////////////////////////
hsBool plTransitionMgr::MsgReceive( plMessage* msg )
{
int i;
plTimeMsg *time = plTimeMsg::ConvertNoRef( msg );
if( time != nil )
{
if( !fPlaying )
return false;
if (fLastTime < 0)
{
// Semi-hack. We trigger transitions after we've finished loading.
// Problem is the loading all happens in one really long frame, so that
// if we record the time we started, we'll instantly be done next frame,
// even though we triggered just at the "end" of the last frame.
//
// So instead we don't start the clock until we get our first plTimeMsg.
fLastTime = (hsScalar)(time->DSeconds());
return false;
}
fEffectLength -= (hsScalar)( time->DSeconds() - fLastTime );//*/time->DelSeconds();
if( fEffectLength < 0 )
IStop();
else
{
// Grab the layer so we can set the opacity
fCurrOpacity += (hsScalar)(fOpacDelta * ( time->DSeconds() - fLastTime ));//*/time->DelSeconds();
if( fEffectPlate == nil )
ICreatePlate();
plLayer *layer = (plLayer *)fEffectPlate->GetMaterial()->GetLayer( 0 );
if( layer != nil )
{
layer->SetOpacity( fCurrOpacity );
}
// Let the audiosystem handle fading in sounds
if(!fNoSoundFade)
plgAudioSys::SetGlobalFadeVolume( 1.f - fCurrOpacity );
fLastTime = (hsScalar)(time->DSeconds());
}
return false;
}
plTransitionMsg *effect = plTransitionMsg::ConvertNoRef( msg );
if( effect != nil )
{
if( fRegisteredForTime )
IStop( true );
for( i = 0; i < effect->GetNumCallbacks(); i++ )
{
plEventCallbackMsg *pMsg = effect->GetEventCallback( i );
hsRefCnt_SafeRef( pMsg );
fCallbacks.Append( pMsg );
}
fHoldAtEnd = effect->GetHoldState();
fNoSoundFade = false;
switch(effect->GetEffect())
{
case plTransitionMsg::kFadeInNoSound:
fNoSoundFade = true;
case plTransitionMsg::kFadeIn:
IStartFadeIn( effect->GetLengthInSecs(), kTransitionFadeIn );
break;
case plTransitionMsg::kFadeOutNoSound:
fNoSoundFade = true;
case plTransitionMsg::kFadeOut:
IStartFadeOut( effect->GetLengthInSecs(), kTransitionFadeOut );
break;
}
return false;
}
plLinkEffectBCMsg *link = plLinkEffectBCMsg::ConvertNoRef( msg );
if( link != nil )
{
const float kScreenFadeTime = 3.f; // seconds
// Go ahead and auto-trigger based on link FX messages
if( plNetClientApp::GetInstance() != nil && link->fLinkKey == plNetClientApp::GetInstance()->GetLocalPlayerKey() )
{
if( fRegisteredForTime )
IStop( true );
if( link->HasLinkFlag( plLinkEffectBCMsg::kLeavingAge ) )
{
plNetApp::GetInstance()->DebugMsg("Local player linking out, fading screen\n");
fHoldAtEnd = true;
IStartFadeOut( kScreenFadeTime );
}
else
{
plNetApp::GetInstance()->DebugMsg("Local player linking in, fading screen\n");
fHoldAtEnd = false;
IStartFadeIn( kScreenFadeTime );
}
if (link->HasLinkFlag(plLinkEffectBCMsg::kSendCallback))
{
plLinkEffectsMgr *mgr;
if( ( mgr = plLinkEffectsMgr::ConvertNoRef( link->GetSender()->ObjectIsLoaded() ) ) != nil )
{
plEventCallbackMsg *cback = plEventCallbackMsg::ConvertNoRef( mgr->WaitForEffect( link->fLinkKey ) );
// hsRefCnt_SafeRef( cback ); // mgr has given us ownership, his ref is now ours. No need for another. -mf-
fCallbacks.Append( cback );
}
}
}
return true;
}
return hsKeyedObject::MsgReceive( msg );
}

View File

@ -0,0 +1,90 @@
/*==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==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plTransitionMgr - Class to handle fullscreen transitions (fades, etc) //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _plTransitionMgr_h
#define _plTransitionMgr_h
#include "hsTypes.h"
#include "hsTemplates.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "hsUtils.h"
//// Class Definition ////////////////////////////////////////////////////////
class plPlate;
class plEventCallbackMsg;
class plTransitionMgr : public hsKeyedObject
{
protected:
plPlate *fEffectPlate;
enum
{
kIdle,
kFadeOut,
kFadeIn,
kTransitionFadeIn,
kTransitionFadeOut
};
UInt8 fCurrentEffect;
hsBool fRegisteredForTime, fHoldAtEnd, fPlaying, fNoSoundFade;
hsScalar fEffectLength, fCurrOpacity, fOpacDelta;
hsScalar fLastTime;
void IStartFadeIn( hsScalar lengthInSecs, UInt8 effect = kFadeIn );
void IStartFadeOut( hsScalar lengthInSecs, UInt8 effect = kFadeOut );
void ICreatePlate( void );
void IStop( hsBool aboutToStartAgain = false );
hsTArray<plEventCallbackMsg *> fCallbacks;
public:
plTransitionMgr();
virtual ~plTransitionMgr();
CLASSNAME_REGISTER( plTransitionMgr );
GETINTERFACE_ANY( plTransitionMgr, hsKeyedObject );
void Init( void );
virtual hsBool MsgReceive( plMessage* msg );
};
#endif //_plTransitionMgr_h

View File

@ -0,0 +1,447 @@
/*==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==*/
#include "hsTypes.h"
#include "plVertCoder.h"
#include "hsStream.h"
#include "plGBufferGroup.h"
const hsScalar kPosQuantum = 1.f / hsScalar(1 << 10);
const hsScalar kWeightQuantum = 1.f / hsScalar(1 << 15);
const hsScalar kUVWQuantum = 1.f / hsScalar(1 << 16);
UInt32 plVertCoder::fCodedVerts = 0;
UInt32 plVertCoder::fCodedBytes = 0;
UInt32 plVertCoder::fRawBytes = 0;
UInt32 plVertCoder::fSkippedBytes = 0;
static const hsScalar kQuanta[plVertCoder::kNumFloatFields] =
{
kPosQuantum,
kWeightQuantum,
kUVWQuantum,
kUVWQuantum,
kUVWQuantum,
kUVWQuantum,
kUVWQuantum,
kUVWQuantum,
kUVWQuantum,
kUVWQuantum,
};
inline void plVertCoder::ICountFloats(const UInt8* src, UInt16 maxCnt, const hsScalar quant, const UInt32 stride,
hsScalar& lo, hsBool &allSame, UInt16& count)
{
lo = *(hsScalar*)src;
lo = floor(lo / quant + 0.5f) * quant;
allSame = false;
hsScalar hi = lo;
count = 1;
const hsScalar maxRange = hsScalar(UInt16(0xffff)) * quant;
src += stride;
maxCnt--;
while( maxCnt-- )
{
hsScalar val = *(hsScalar*)src;
val = floor(val / quant + 0.5f) * quant;
if( val < lo )
{
if( hi - val > maxRange )
return;
lo = val;
}
else if( val > hi )
{
if( val - lo > maxRange )
return;
hi = val;
}
count++;
src += stride;
}
allSame = (lo == hi);
}
static inline void IWriteFloat(hsStream* s, const UInt8*& src, const hsScalar offset, const hsScalar quantum)
{
float fval = *(float*)src;
fval -= offset;
fval /= quantum;
// hsAssert(fval < hsScalar(UInt16(0xffff)), "Bad offset?");
const UInt16 ival = UInt16(floor(fval + 0.5f));
s->WriteSwap16(ival);
src += 4;
}
static inline void IReadFloat(hsStream* s, UInt8*& dst, const hsScalar offset, const hsScalar quantum)
{
const UInt16 ival = s->ReadSwap16();
float fval = float(ival) * quantum;
fval += offset;
hsScalar* val = (hsScalar*)dst;
*val = fval;
dst += 4;
}
inline void plVertCoder::IEncodeFloat(hsStream* s, const UInt32 vertsLeft, const int field, const int chan, const UInt8*& src, const UInt32 stride)
{
if( !fFloats[field][chan].fCount )
{
ICountFloats(src, (UInt16)vertsLeft, kQuanta[field], stride, fFloats[field][chan].fOffset, fFloats[field][chan].fAllSame, fFloats[field][chan].fCount);
s->WriteSwapScalar(fFloats[field][chan].fOffset);
s->WriteBool(fFloats[field][chan].fAllSame);
s->WriteSwap16(fFloats[field][chan].fCount);
}
if (!fFloats[field][chan].fAllSame)
IWriteFloat(s, src, fFloats[field][chan].fOffset, kQuanta[field]);
else
src += 4;
fFloats[field][chan].fCount--;
}
inline void plVertCoder::IDecodeFloat(hsStream* s, const int field, const int chan, UInt8*& dst, const UInt32 stride)
{
if( !fFloats[field][chan].fCount )
{
fFloats[field][chan].fOffset = s->ReadSwapScalar();
fFloats[field][chan].fAllSame = s->ReadBool();
fFloats[field][chan].fCount = s->ReadSwap16();
}
if (!fFloats[field][chan].fAllSame)
IReadFloat(s, dst, fFloats[field][chan].fOffset, kQuanta[field]);
else
{
*((hsScalar*)dst) = fFloats[field][chan].fOffset;
dst += 4;
}
fFloats[field][chan].fCount--;
}
static inline int INumWeights(const UInt8 format)
{
return (format & plGBufferGroup::kSkinWeightMask) >> 4;
}
static const hsScalar kNormalScale(Int16(0x7fff));
static const hsScalar kInvNormalScale(1.f / kNormalScale);
inline void plVertCoder::IEncodeNormal(hsStream* s, const UInt8*& src, const UInt32 stride)
{
hsScalar x = *(hsScalar*)src;
s->WriteByte((UInt8)((x / 2.f + .5f) * 255.9f));
src += 4;
x = *(hsScalar*)src;
s->WriteByte((UInt8)((x / 2.f + .5f) * 255.9f));
src += 4;
x = *(hsScalar*)src;
s->WriteByte((UInt8)((x / 2.f + .5f) * 255.9f));
src += 4;
}
inline void plVertCoder::IDecodeNormal(hsStream* s, UInt8*& dst, const UInt32 stride)
{
UInt8 ix = s->ReadByte();
hsScalar* x = (hsScalar*)dst;
*x = (ix / 255.9f - .5f) * 2.f;
dst += 4;
ix = s->ReadByte();
x = (hsScalar*)dst;
*x = (ix / 255.9f - .5f) * 2.f;
dst += 4;
ix = s->ReadByte();
x = (hsScalar*)dst;
*x = (ix / 255.9f - .5f) * 2.f;
dst += 4;
}
inline void plVertCoder::ICountBytes(const UInt32 vertsLeft, const UInt8* src, const UInt32 stride, UInt16& len, UInt8& same)
{
// We want to run length encode this. So we're looking here for either
// the number of consecutive bytes of the same value,
// or the number of consective bytes of different values.
// The latter is so we don't wind up getting larger when there aren't any
// runs of the same value (count=1 and val=c1, count=1 and val=c2, etc.).
// The break-even point is a run of 3, so we'll look for a minimum run of 4.
if( vertsLeft < 4 )
{
len = (UInt16)vertsLeft;
same = false;
return;
}
// First, count how many values are the same as the first one
int i;
for( i = 0; i < vertsLeft; i++ )
{
if( src[i * stride] != src[0] )
break;
}
if( i >= 4 )
{
// Found a good run.
len = i;
same = true;
return;
}
// Okay, we're in a section of varying values. How far to the next
// section of sameness?
same = false;
for( ; i < vertsLeft-4; i++ )
{
if( (src[i*stride] == src[(i+1)*stride])
&&(src[i*stride] == src[(i+2)*stride])
&&(src[i*stride] == src[(i+3)*stride]) )
break;
}
if( i < vertsLeft-4 )
{
len = i;
return;
}
len = (UInt16)vertsLeft;
return;
}
static const UInt16 kSameMask(0x8000);
inline void plVertCoder::IEncodeByte(hsStream* s, const int chan, const UInt32 vertsLeft, const UInt8*& src, const UInt32 stride)
{
if( !fColors[chan].fCount )
{
ICountBytes(vertsLeft, src, stride, fColors[chan].fCount, fColors[chan].fSame);
UInt16 cnt = fColors[chan].fCount;
if( fColors[chan].fSame )
cnt |= kSameMask;
s->WriteSwap16(cnt);
if( fColors[chan].fSame )
s->WriteByte(*src);
}
if( !fColors[chan].fSame )
s->WriteByte(*src);
src++;
fColors[chan].fCount--;
}
inline void plVertCoder::IDecodeByte(hsStream* s, const int chan, UInt8*& dst, const UInt32 stride)
{
if( !fColors[chan].fCount )
{
UInt16 cnt = s->ReadSwap16();
if( cnt & kSameMask )
{
fColors[chan].fSame = true;
fColors[chan].fVal = s->ReadByte();
cnt &= ~kSameMask;
}
else
{
fColors[chan].fSame = false;
}
fColors[chan].fCount = cnt;
}
if( !fColors[chan].fSame )
*dst = s->ReadByte();
else
*dst = fColors[chan].fVal;
dst++;
fColors[chan].fCount--;
}
inline void plVertCoder::IEncodeColor(hsStream* s, const UInt32 vertsLeft, const UInt8*& src, const UInt32 stride)
{
IEncodeByte(s, 0, vertsLeft, src, stride);
IEncodeByte(s, 1, vertsLeft, src, stride);
IEncodeByte(s, 2, vertsLeft, src, stride);
IEncodeByte(s, 3, vertsLeft, src, stride);
}
inline void plVertCoder::IDecodeColor(hsStream* s, UInt8*& dst, const UInt32 stride)
{
IDecodeByte(s, 0, dst, stride);
IDecodeByte(s, 1, dst, stride);
IDecodeByte(s, 2, dst, stride);
IDecodeByte(s, 3, dst, stride);
}
inline void plVertCoder::IEncode(hsStream* s, const UInt32 vertsLeft, const UInt8*& src, const UInt32 stride, const UInt8 format)
{
IEncodeFloat(s, vertsLeft, kPosition, 0, src, stride);
IEncodeFloat(s, vertsLeft, kPosition, 1, src, stride);
IEncodeFloat(s, vertsLeft, kPosition, 2, src, stride);
// Weights and indices?
const int numWeights = INumWeights(format);
if( numWeights )
{
int j;
for( j = 0; j < numWeights; j++ )
IEncodeFloat(s, vertsLeft, kWeight, j, src, stride);
if( format & plGBufferGroup::kSkinIndices )
{
const UInt32 idx = *(UInt32*)src;
s->WriteSwap32(idx);
src += 4;
}
}
IEncodeNormal(s, src, stride);
IEncodeColor(s, vertsLeft, src, stride);
// COLOR2
src += 4;
const int numUVWs = format & plGBufferGroup::kUVCountMask;
int i;
for( i = 0; i < numUVWs; i++ )
{
IEncodeFloat(s, vertsLeft, kUVW + i, 0, src, stride);
IEncodeFloat(s, vertsLeft, kUVW + i, 1, src, stride);
IEncodeFloat(s, vertsLeft, kUVW + i, 2, src, stride);
}
}
inline void plVertCoder::IDecode(hsStream* s, UInt8*& dst, const UInt32 stride, const UInt8 format)
{
IDecodeFloat(s, kPosition, 0, dst, stride);
IDecodeFloat(s, kPosition, 1, dst, stride);
IDecodeFloat(s, kPosition, 2, dst, stride);
// Weights and indices?
const int numWeights = INumWeights(format);
if( numWeights )
{
int j;
for( j = 0; j < numWeights; j++ )
IDecodeFloat(s, kWeight, j, dst, stride);
if( format & plGBufferGroup::kSkinIndices )
{
UInt32* idx = (UInt32*)dst;
*idx = s->ReadSwap32();
dst += 4;
}
}
IDecodeNormal(s, dst, stride);
IDecodeColor(s, dst, stride);
// COLOR2
UInt32* trash = (UInt32*)dst;
*trash = 0;
dst += 4;
const int numUVWs = format & plGBufferGroup::kUVCountMask;
int i;
for( i = 0; i < numUVWs; i++ )
{
IDecodeFloat(s, kUVW + i, 0, dst, stride);
IDecodeFloat(s, kUVW + i, 1, dst, stride);
IDecodeFloat(s, kUVW + i, 2, dst, stride);
}
}
void plVertCoder::Read(hsStream* s, UInt8* dst, const UInt8 format, const UInt32 stride, const UInt16 numVerts)
{
Clear();
int i = numVerts;
for( i = 0; i < numVerts; i++ )
IDecode(s, dst, stride, format);
}
void plVertCoder::Write(hsStream* s, const UInt8* src, const UInt8 format, const UInt32 stride, const UInt16 numVerts)
{
Clear();
UInt32 streamStart = s->GetPosition();
int numLeft = numVerts;
while( numLeft )
{
IEncode(s, numLeft, src, stride, format);
numLeft--;
}
fCodedVerts += numVerts;
fCodedBytes += (s->GetPosition() - streamStart);
fRawBytes += numVerts * stride;
}
plVertCoder::plVertCoder()
{
Clear();
}
plVertCoder::~plVertCoder()
{
}
void plVertCoder::Clear()
{
memset(this, 0, sizeof(*this));
}

View File

@ -0,0 +1,106 @@
/*==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 plVertCoder_inc
#define plVertCoder_inc
class hsStream;
class plVertCoder
{
public:
enum {
kPosition,
kWeight,
kUVW,
kNumFloatFields = kUVW + 8
};
protected:
class FloatCode
{
public:
hsScalar fOffset;
hsBool fAllSame;
UInt16 fCount;
};
FloatCode fFloats[kNumFloatFields][3];
class ByteCode
{
public:
UInt16 fCount;
UInt8 fVal;
UInt8 fSame;
};
ByteCode fColors[4];
static UInt32 fCodedVerts;
static UInt32 fCodedBytes;
static UInt32 fRawBytes;
static UInt32 fSkippedBytes;
inline void ICountFloats(const UInt8* src, UInt16 maxCnt, const hsScalar quant, const UInt32 stride, hsScalar& lo, hsBool& allSame, UInt16& count);
inline void IEncodeFloat(hsStream* s, const UInt32 vertsLeft, const int field, const int chan, const UInt8*& src, const UInt32 stride);
inline void IDecodeFloat(hsStream* s, const int field, const int chan, UInt8*& dst, const UInt32 stride);
inline void IEncodeNormal(hsStream* s, const UInt8*& src, const UInt32 stride);
inline void IDecodeNormal(hsStream* s, UInt8*& dst, const UInt32 stride);
inline void ICountBytes(const UInt32 vertsLeft, const UInt8* src, const UInt32 stride, UInt16& len, UInt8& same);
inline void IEncodeByte(hsStream* s, const int chan, const UInt32 vertsLeft, const UInt8*& src, const UInt32 stride);
inline void IDecodeByte(hsStream* s, const int chan, UInt8*& dst, const UInt32 stride);
inline void IEncodeColor(hsStream* s, const UInt32 vertsLeft, const UInt8*& src, const UInt32 stride);
inline void IDecodeColor(hsStream* s, UInt8*& dst, const UInt32 stride);
inline void IEncode(hsStream* s, const UInt32 vertsLeft, const UInt8*& src, const UInt32 stride, const UInt8 format);
inline void IDecode(hsStream* s, UInt8*& dst, const UInt32 stride, const UInt8 format);
public:
plVertCoder();
~plVertCoder();
void Clear();
void Read(hsStream* s, UInt8* dst, const UInt8 format, const UInt32 stride, const UInt16 numVerts);
void Write(hsStream* s, const UInt8* src, const UInt8 format, const UInt32 stride, const UInt16 numVerts);
static void ClearAverage() { fCodedVerts = 0; fCodedBytes = 0; fRawBytes = 0; fSkippedBytes = 0; }
static UInt32 CodedBytes() { return fCodedBytes; }
static UInt32 RawBytes() { return fRawBytes; }
static UInt32 CodedVerts() { return fCodedVerts; }
static float AverageCodedVertSize() { return fCodedVerts ? float(fCodedBytes) / float(fCodedVerts) : 0; }
static float AverageRawVertSize() { return fCodedVerts ? float(fRawBytes) / float(fCodedVerts) : 0; }
static UInt32 SkippedBytes() { return fSkippedBytes; }
static void AddSkippedBytes(UInt32 f) { fSkippedBytes += f; }
};
#endif // plVertCoder_inc