#include "pch.h"
float Plane::Distance(const HVector& vec) const
{
return
vec.X() * m_hvec.X()
+ vec.Y() * m_hvec.Y()
+ vec.Z() * m_hvec.Z()
+ vec.W() * m_hvec.W();
}
float Plane::Intersect(const HVector& v0, const HVector& v1) const
{
HVector vd = v1 - v0;
float a = m_hvec * v0;
float b = m_hvec * vd;
float alpha = -a / b;
return bound(alpha, 0.0f, 1.0f);
}
class StateChangeBase {};
typedef TBitMask<StateChangeBase, DWORD> StateChange;
class StateChangeMatrix : public StateChange { public: StateChangeMatrix () : StateChange(0x000001) {} };
class StateChangePerspectiveMatrix : public StateChange { public: StateChangePerspectiveMatrix () : StateChange(0x000002) {} };
class StateChangeMaterial : public StateChange { public: StateChangeMaterial () : StateChange(0x000004) {} };
class StateChangeTexture : public StateChange { public: StateChangeTexture () : StateChange(0x000008) {} };
class StateChangeShadeMode : public StateChange { public: StateChangeShadeMode () : StateChange(0x000010) {} };
class StateChangeBlendMode : public StateChange { public: StateChangeBlendMode () : StateChange(0x000020) {} };
class StateChangeZTest : public StateChange { public: StateChangeZTest () : StateChange(0x000040) {} };
class StateChangeZWrite : public StateChange { public: StateChangeZWrite () : StateChange(0x000080) {} };
class StateChangeLinearFilter : public StateChange { public: StateChangeLinearFilter () : StateChange(0x000100) {} };
class StateChangePerspectiveCorrection : public StateChange { public: StateChangePerspectiveCorrection() : StateChange(0x000200) {} };
class StateChangeDither : public StateChange { public: StateChangeDither () : StateChange(0x000400) {} };
class StateChangeWrapMode : public StateChange { public: StateChangeWrapMode () : StateChange(0x000800) {} };
class StateChangeCullMode : public StateChange { public: StateChangeCullMode () : StateChange(0x001000) {} };
class StateChangeClipRect : public StateChange { public: StateChangeClipRect () : StateChange(0x002000) {} };
class StateChangeClipPlanes : public StateChange { public: StateChangeClipPlanes () : StateChange(0x004000) {} };
class StateChangeColor : public StateChange { public: StateChangeColor () : StateChange(0x008000) {} };
class StateChangeAmbientLevel : public StateChange { public: StateChangeAmbientLevel () : StateChange(0x010000) {} };
class StateChangeLineWidth : public StateChange { public: StateChangeLineWidth () : StateChange(0x020000) {} };
class StateChangeColorKey : public StateChange { public: StateChangeColorKey () : StateChange(0x040000) {} };
class StateChangeDeformation : public StateChange { public: StateChangeDeformation () : StateChange(0x080000) {} };
class StateChangeAll : public StateChange { public: StateChangeAll () : StateChange(0xffffff) {} };
const StateChange stCommon =
StateChangeMatrix()
| StateChangeMaterial()
| StateChangeTexture();
const StateChange stUncommon = StateChangeAll().Clear(stCommon);
class State : public IObjectSingle {
public:
TRef<State> m_pnext;
TRef<Material> m_pmaterial;
TRef<Surface> m_psurfaceTexture;
TRef<Deformation> m_pdeform;
Matrix m_mat;
Matrix m_matPerspective;
Rect m_rectClip;
int m_countClipPlanes;
bool m_bZTest;
bool m_bZWrite;
bool m_bDither;
bool m_bColorKey;
bool m_bLinearFilter;
bool m_bPerspectiveCorrection;
ShadeMode m_shadeMode;
BlendMode m_blendMode;
WrapMode m_wrapMode;
CullMode m_cullMode;
Color m_color;
float m_ambientLevel;
float m_lineWidth;
StateChange m_maskChanges;
StateChange m_maskOverride;
State()
{
}
State(State* pstate) :
m_pnext(pstate),
m_maskChanges(),
m_maskOverride()
{
}
};
class ContextImpl : public PrivateContext {
private:
class WhiteSurfaceSite : public SurfaceSite {
public:
void UpdateSurface(Surface* psurface)
{
psurface->FillSurface(Color::White());
}
};
TRef<IDevice3D> m_pdevice3D;
TRef<State> m_pstate;
TRef<State> m_pstateDevice;
PrivateSurface* m_psurface;
Vertex* m_pvertexBuffer;
int m_countVertexBuffer;
MeshIndex* m_pindexBuffer;
int m_countIndexBuffer;
bool m_bRendering;
bool m_bIn3DLayer;
bool m_bInScene;
bool m_bRenderingCallbacks;
float m_focus;
float m_near;
float m_far;
float m_aspect;
float m_rxscale;
float m_ryscale;
float m_yscale;
float m_lod;
class Decal {
public:
Vector m_position;
Color m_color;
float m_scale;
float m_angle;
Vector m_forward;
Vector m_right;
bool GetVertices(VertexL* pvertex) const
{
Vector v0;
Vector v1;
Vector v2;
Vector v3;
if (m_forward.IsZero()) {
float c = cos(m_angle) * m_scale;
float s = sin(m_angle) * m_scale;
float dx = c - s;
float dy = c + s;
float x = m_position.X();
float y = m_position.Y();
float z = m_position.Z();
v0 = Vector(x - dy, y + dx, z);
v1 = Vector(x - dx, y - dy, z);
v2 = Vector(x + dy, y - dx, z);
v3 = Vector(x + dx, y + dy, z);
} else {
v0 = m_position - m_forward - m_right;
v1 = m_position + m_forward - m_right;
v2 = m_position + m_forward + m_right;
v3 = m_position - m_forward + m_right;
}
float r = m_color.R();
float g = m_color.G();
float b = m_color.B();
float a = m_color.A();
pvertex[0] = VertexL(v0.X(), v0.Y(), v0.Z(), r, g, b, a, 0, 1);
pvertex[1] = VertexL(v1.X(), v1.Y(), v1.Z(), r, g, b, a, 0, 0);
pvertex[2] = VertexL(v2.X(), v2.Y(), v2.Z(), r, g, b, a, 1, 0);
pvertex[3] = VertexL(v3.X(), v3.Y(), v3.Z(), r, g, b, a, 1, 1);
return true;
}
};
class DecalSet {
public:
TRef<Surface> m_psurface;
TVector<Decal> m_vdecal;
};
TVector<DecalSet> m_vdecalSet;
TVector<DecalSet> m_vdecalSetOpaque;
class GeoCallbackData {
public:
TRef<IGeoCallback> m_pgeoCallback;
Matrix m_mat;
float m_distance;
};
class CompareDistance {
public:
bool operator () (const GeoCallbackData& value1, const GeoCallbackData& value2)
{
return value1.m_distance < value2.m_distance;
}
};
typedef TList<GeoCallbackData, DefaultNoEquals, CompareDistance> GeoCallbackDataList;
GeoCallbackDataList m_listGeoCallbacks;
GeoCallbackDataList m_listGeoCallbacksSorted;
#ifdef EnablePerformanceCounters
int m_countDrawString;
int m_countDrawStringChars;
#endif
public:
ContextImpl(PrivateSurface* psurface) :
#ifdef EnablePerformanceCounters
m_countDrawString(0),
m_countDrawStringChars(0),
#endif
m_pvertexBuffer(NULL),
m_countVertexBuffer(0),
m_pindexBuffer(NULL),
m_countIndexBuffer(0),
m_psurface(psurface),
m_bRendering(false),
m_bIn3DLayer(false),
m_bInScene(false),
m_bRenderingCallbacks(false)
{
if (psurface->GetSurfaceType().Test(SurfaceType3D())) {
TRef<Engine> pengine = psurface->GetEngine();
TRef<Rasterizer> prasterizer;
bool bAlwaysUseD3D = (pengine->GetPrimaryPixelFormat()->PixelBits() == 32);
if (
bAlwaysUseD3D
|| (
pengine->GetUsing3DAcceleration()
&& psurface->GetSurfaceType().Test(SurfaceTypeVideo())
)
) {
prasterizer = CreateD3DRasterizer(m_psurface);
} else {
prasterizer = CreateSoftwareRasterizer(m_psurface);
}
if (prasterizer == NULL) {
return;
}
m_pdevice3D = CreateDevice3D(prasterizer);
}
m_pstateDevice = new State();
m_pstateDevice->m_mat.SetIdentity();
m_pstateDevice->m_matPerspective.SetIdentity();
m_pstateDevice->m_pmaterial = NULL;
m_pstateDevice->m_bZTest = false;
m_pstateDevice->m_bZWrite = false;
m_pstateDevice->m_bPerspectiveCorrection = false;
m_pstateDevice->m_bDither = true;
m_pstateDevice->m_bColorKey = true;
m_pstateDevice->m_bLinearFilter = true;
m_pstateDevice->m_shadeMode = ShadeModeGouraud;
m_pstateDevice->m_blendMode = BlendModeSource;
m_pstateDevice->m_wrapMode = WrapModeNone;
m_pstateDevice->m_cullMode = CullModeCCW;
m_pstateDevice->m_maskChanges = StateChangeAll();
m_pstateDevice->m_maskOverride = StateChange();
m_pstateDevice->m_countClipPlanes = 0;
m_pstateDevice->m_rectClip =
Rect(
Point(0, 0),
Point::Cast(m_psurface->GetSize())
);
m_pstateDevice->m_color = Color::White();
m_pstateDevice->m_lineWidth = 1;
}
bool IsValid()
{
return m_pdevice3D != NULL && m_pdevice3D->IsValid();
}
~ContextImpl()
{
if (m_pvertexBuffer) {
free(m_pvertexBuffer);
}
if (m_pindexBuffer) {
free(m_pindexBuffer);
}
}
bool Has3DAcceleration()
{
return m_pdevice3D->Has3DAcceleration();
}
void BeginRendering()
{
ZAssert(!m_bRendering);
ZAssert(!m_bInScene);
ZAssert(!m_bIn3DLayer);
m_bRendering = true;
PushState();
}
void EndRendering()
{
ZAssert(m_bRendering);
PopState();
if (m_bIn3DLayer) {
End3DLayer();
}
EndScene();
m_bRendering = false;
}
PrivateSurface* GetSurface()
{
return m_psurface;
}
bool GetClipping()
{
return m_pdevice3D->GetClipping();
}
void SetClipping(bool bClip)
{
m_pdevice3D->SetClipping(bClip);
}
bool IsCulled(
const Vector& vecOrigin,
float radius,
bool& bNotClipped
) {
Vector vecEye = TransformLocalToEye(vecOrigin);
float x = vecEye.X();
float y = vecEye.Y();
float z = vecEye.Z();
float back = z - m_far;
float front = m_near - z;
float rx;
float ry;
float left;
float right;
float bottom;
float top;
if (m_focus == 0) {
rx = radius;
ry = radius;
left = x - 1;
right = -x - 1;
bottom = y - 1;
top = -y - 1;
} else {
rx = radius * m_rxscale;
ry = radius * m_ryscale;
left = m_focus * x - z;
right = -m_focus * x - z;
bottom = m_yscale * y - z;
top = -m_yscale * y - z;
}
if (
left < -rx
|| right < -rx
|| bottom < -ry
|| top < -ry
|| back < -radius
|| front < -radius
) {
bNotClipped = false;
return true;
}
if (
left > rx
&& right > rx
&& bottom > ry
&& top > ry
&& back > radius
&& front > radius
) {
bNotClipped = true;
return false;
}
bNotClipped = false;
return false;
}
void DrawImage(
Surface* psurface,
const Rect& rectSource,
bool bCentered,
const Point& point
) {
ZAssert(!m_bIn3DLayer);
ZAssert(m_pstateDevice->m_matPerspective.GetType() < TransformRotate);
DD2D();
Point pointImage;
if (TransformLocalToImage(Vector(point.X(), point.Y(), 0), pointImage)) {
WinPoint pointScreen = TransformImageToSurface(pointImage);
if (bCentered) {
pointScreen.SetX(pointScreen.X() - (int)(rectSource.XSize() / 2.0f));
pointScreen.SetY(pointScreen.Y() - (int)(rectSource.YSize() / 2.0f));
} else {
pointScreen.SetY(pointScreen.Y() - (int)rectSource.YSize());
}
m_psurface->BitBlt(
pointScreen,
psurface,
WinRect::Cast(rectSource)
);
};
}
void DrawImage(
Surface* psurface,
bool bCentered,
const Point& point
) {
DrawImage(
psurface,
WinRect(
WinPoint(0, 0),
psurface->GetSize()
),
bCentered,
point
);
}
void DrawImage3D(
Surface* psurface,
const Rect& rectSource,
const Color& color,
bool bCentered,
const Point& point
) {
ZAssert(m_bRendering);
if (!m_bInScene) {
Texture2D();
}
Point sizeSource(Point::Cast(psurface->GetSize()));
float xOffset = point.X() - (bCentered ? rectSource.XSize() / 2 : 0);
float yOffset = point.Y() - (bCentered ? rectSource.YSize() / 2 : 0);
float xmin = xOffset;
float xmax = xOffset + rectSource.XSize();
float ymin = yOffset;
float ymax = yOffset + rectSource.YSize();
float xt;
float yt;
xt = 1.0f / sizeSource.X();
yt = 1.0f / sizeSource.Y();
float xtmin = xt * rectSource.XMin();
float xtmax = xt * rectSource.XMax();
float ytmin = yt * (sizeSource.Y() - rectSource.YMin());
float ytmax = yt * (sizeSource.Y() - rectSource.YMax());
static MeshIndex indices[6] = { 0, 2, 1, 0, 3, 2 };
UpdateState();
#ifdef DEBUGOFF if (psurface->GetPixelFormat()->PixelBits() != m_psurface->GetPixelFormat()->PixelBits())
debugf ("DrawImage3D ppf mismatch for %s - will convert\n",(const char *)psurface->GetName());
#endif
m_pdevice3D->SetTexture(psurface->GetConvertedSurface(m_psurface->GetPixelFormat()));
m_pdevice3D->SetLinearFilter(false); switch (GetShadeMode()) {
case ShadeModeCopy:
{
Vertex vertices[4] = {
Vertex(xmin, ymax, 0, 0, 0, 1, xtmin, ytmax),
Vertex(xmin, ymin, 0, 0, 0, 1, xtmin, ytmin),
Vertex(xmax, ymin, 0, 0, 0, 1, xtmax, ytmin),
Vertex(xmax, ymax, 0, 0, 0, 1, xtmax, ytmax)
};
m_pdevice3D->DrawTriangles(vertices, 4, indices, 6);
}
break;
case ShadeModeFlat:
case ShadeModeGouraud:
{
float r = color.R();
float g = color.G();
float b = color.B();
float a = color.A();
VertexL vertices[4] = {
VertexL(xmin, ymax, 0, r, g, b, a, xtmin, ytmax),
VertexL(xmin, ymin, 0, r, g, b, a, xtmin, ytmin),
VertexL(xmax, ymin, 0, r, g, b, a, xtmax, ytmin),
VertexL(xmax, ymax, 0, r, g, b, a, xtmax, ytmax)
};
m_pdevice3D->SetShadeMode(ShadeModeFlat);
m_pdevice3D->DrawTriangles(vertices, 4, indices, 6);
m_pdevice3D->SetShadeMode(m_pstateDevice->m_shadeMode);
}
break;
default:
ZError("Invalid shade mode");
break;
}
m_pdevice3D->SetTexture(m_pstateDevice->m_psurfaceTexture);
m_pdevice3D->SetLinearFilter(m_pstateDevice->m_bLinearFilter); }
void DrawImage3D(
Surface* psurface,
const Color& color,
bool bCentered,
const Point& point
) {
DrawImage3D(
psurface,
Rect(
Point(0, 0),
Point::Cast(psurface->GetSize())
),
color,
bCentered,
point
);
}
void DrawString(
IEngineFont* pfont,
const Color& color,
const Point& point,
const ZString& str
) {
#ifdef EnablePerformanceCounters
m_countDrawString++;
m_countDrawStringChars += str.GetLength();
#endif
DD2D();
Point pointImage;
if (TransformLocalToImage(Vector(point.X(), point.Y(), 0), pointImage)) {
WinPoint pointScreen = TransformImageToSurface(pointImage);
WinPoint size = pfont->GetTextExtent(str);
pointScreen.SetY(pointScreen.Y() - size.Y());
m_psurface->DrawString(pfont, color, pointScreen, str);
};
}
void DrawRectangle(const Rect& rect, const Color& color)
{
Texture2D();
static MeshIndex indices[8] = { 0, 1, 1, 2, 2, 3, 3, 0 };
float xmin = rect.XMin();
float xmax = rect.XMax();
float ymin = rect.YMin();
float ymax = rect.YMax();
float r = color.R();
float g = color.G();
float b = color.B();
float a = color.A();
VertexL vertices[4] = {
VertexL(xmin, ymax, 0, r, g, b, a, 0, 0),
VertexL(xmin, ymin, 0, r, g, b, a, 0, 0),
VertexL(xmax, ymin, 0, r, g, b, a, 0, 0),
VertexL(xmax, ymax, 0, r, g, b, a, 0, 0)
};
m_pdevice3D->DrawLines(vertices, 4, indices, 8);
}
void FillRect(const Rect& rect, const Color& color)
{
Texture2D();
static MeshIndex indices[6] = { 0, 2, 1, 0, 3, 2 };
float xmin = rect.XMin();
float xmax = rect.XMax();
float ymin = rect.YMin();
float ymax = rect.YMax();
float r = color.R();
float g = color.G();
float b = color.B();
float a = color.A();
VertexL vertices[4] = {
VertexL(xmin, ymax, 0, r, g, b, a, 0, 1),
VertexL(xmin, ymin, 0, r, g, b, a, 0, 0),
VertexL(xmax, ymin, 0, r, g, b, a, 1, 0),
VertexL(xmax, ymax, 0, r, g, b, a, 1, 1)
};
UpdateState();
m_pdevice3D->SetShadeMode(ShadeModeFlat);
m_pdevice3D->SetColorKey(false); m_pdevice3D->DrawTriangles(vertices, 4, indices, 6);
m_pdevice3D->SetShadeMode(m_pstateDevice->m_shadeMode);
m_pdevice3D->SetColorKey(m_pstateDevice->m_bColorKey); }
void FillInfinite(const Color& color)
{
DD2D();
m_psurface->FillSurface(color);
}
void Begin3DLayer(Camera* pcamera, bool bZBuffer)
{
ZEnter("Context::Begin3DLayer");
ZAssert(m_bRendering);
ZAssert(!m_bIn3DLayer);
PushState();
pcamera->Update();
SetPerspectiveMatrix(pcamera->GetPerspectiveMatrix());
m_bIn3DLayer = true;
SetTransform(pcamera->GetModelMatrix());
BeginScene();
WinPoint point = m_psurface->GetSize();
m_focus = pcamera->GetFocus();
m_near = pcamera->GetNear();
m_far = pcamera->GetFar();
m_aspect = float(point.Y()) / float(point.X());
m_yscale = m_focus / m_aspect;
m_rxscale = sqrt(m_focus * m_focus + 1.0f);
m_ryscale = sqrt(m_yscale * m_yscale + 1.0f);
SetClipping(true);
m_lod = FLT_MAX;
if (bZBuffer) {
ZTrace("Clearing ZBuffer");
UpdateState();
m_pdevice3D->ClearZBuffer();
SetZWrite(true, false);
SetZTest(true, false);
} else {
SetZWrite(false, false);
SetZTest(false, false);
}
PushState();
}
void RenderCallbackGeos(GeoCallbackDataList& list)
{
GeoCallbackDataList::Iterator iter(list);
while (!iter.End()) {
GeoCallbackData& data = iter.Value();
PushState();
SetTransform(data.m_mat);
data.m_pgeoCallback->RenderCallback(this);
PopState();
iter.Next();
}
list.SetEmpty();
}
void End3DLayer()
{
ZExit("Context::Begin3DLayer");
ZAssert(m_bRendering);
ZAssert(m_bIn3DLayer);
ZAssert(m_bInScene);
PopState();
m_bRenderingCallbacks = true;
RenderCallbackGeos(m_listGeoCallbacksSorted);
RenderCallbackGeos(m_listGeoCallbacks);
m_bRenderingCallbacks = false;
DrawCachedDecals();
PopState();
m_bIn3DLayer = false;
}
void BeginScene()
{
if (!m_bInScene) {
m_pdevice3D->BeginScene();
m_bInScene = true;
}
}
void EndScene()
{
if (m_bInScene) {
m_pdevice3D->EndScene();
m_bInScene = false;
}
}
void SetLOD(float lod)
{
m_lod = lod;
}
float GetLOD()
{
return m_lod;
}
const Color& GetGlobalColor() const { return m_pstateDevice->m_color ; }
bool GetZTest() const { return m_pstateDevice->m_bZTest ; }
bool GetZWrite() const { return m_pstateDevice->m_bZWrite ; }
bool GetPerspectiveCorrection() const { return m_pstateDevice->m_bPerspectiveCorrection; }
bool GetDither() const { return m_pstateDevice->m_bDither ; }
bool GetColorKey() const { return m_pstateDevice->m_bColorKey ; }
bool GetLinearFilter() const { return m_pstateDevice->m_bLinearFilter ; }
ShadeMode GetShadeMode() const { return m_pstateDevice->m_shadeMode ; }
BlendMode GetBlendMode() const { return m_pstateDevice->m_blendMode ; }
WrapMode GetWrapMode() const { return m_pstateDevice->m_wrapMode ; }
CullMode GetCullMode() const { return m_pstateDevice->m_cullMode ; }
Surface* GetTexture() const { return m_pstateDevice->m_psurfaceTexture ; }
Material* GetMaterial() const { return m_pstateDevice->m_pmaterial ; }
Deformation* GetDeformation() const { return m_pstateDevice->m_pdeform ; }
template<class ValueType>
void DoSetState(
const ValueType& value,
ValueType& valueDevice,
ValueType& valueState,
bool bOverride,
const StateChange& st
) {
if (!m_pstateDevice->m_maskOverride.Test(st)) {
if (value != valueDevice) {
if (!m_pstate->m_maskChanges.Test(st)) {
valueState = valueDevice;
m_pstate->m_maskChanges.Set(st);
}
valueDevice = value;
m_pstateDevice->m_maskChanges.Set(st);
}
if (bOverride) {
m_pstate->m_maskOverride.Set(st);
m_pstateDevice->m_maskOverride.Set(st);
}
}
}
void SetGlobalColor(const Color& color, bool bOverride)
{
DoSetState(
color,
m_pstateDevice->m_color,
m_pstate->m_color,
bOverride,
StateChangeColor()
);
}
void SetLinearFilter(bool b, bool bOverride)
{
DoSetState(
b,
m_pstateDevice->m_bLinearFilter,
m_pstate->m_bLinearFilter,
bOverride,
StateChangeLinearFilter()
);
}
void SetPerspectiveCorrection(bool b, bool bOverride)
{
DoSetState(
b,
m_pstateDevice->m_bPerspectiveCorrection,
m_pstate->m_bPerspectiveCorrection,
bOverride,
StateChangePerspectiveCorrection()
);
}
void SetDither(bool b, bool bOverride)
{
DoSetState(
b,
m_pstateDevice->m_bDither,
m_pstate->m_bDither,
bOverride,
StateChangeDither()
);
}
void SetColorKey(bool b, bool bOverride)
{
DoSetState(
b,
m_pstateDevice->m_bColorKey,
m_pstate->m_bColorKey,
bOverride,
StateChangeColorKey()
);
}
void SetZTest(bool b, bool bOverride)
{
DoSetState(
b,
m_pstateDevice->m_bZTest,
m_pstate->m_bZTest,
bOverride,
StateChangeZTest()
);
}
void SetZWrite(bool b, bool bOverride)
{
DoSetState(
b,
m_pstateDevice->m_bZWrite,
m_pstate->m_bZWrite,
bOverride,
StateChangeZWrite()
);
}
void SetShadeMode(ShadeMode shadeMode, bool bOverride)
{
DoSetState(
shadeMode,
m_pstateDevice->m_shadeMode,
m_pstate->m_shadeMode,
bOverride,
StateChangeShadeMode()
);
}
void SetBlendMode(BlendMode blendMode, bool bOverride)
{
DoSetState(
blendMode,
m_pstateDevice->m_blendMode,
m_pstate->m_blendMode,
bOverride,
StateChangeBlendMode()
);
}
void SetWrapMode(WrapMode wrapMode, bool bOverride)
{
DoSetState(
wrapMode,
m_pstateDevice->m_wrapMode,
m_pstate->m_wrapMode,
bOverride,
StateChangeWrapMode()
);
}
void SetCullMode(CullMode cullMode, bool bOverride)
{
DoSetState(
cullMode,
m_pstateDevice->m_cullMode,
m_pstate->m_cullMode,
bOverride,
StateChangeCullMode()
);
}
void SetMaterial(Material* pmaterial, bool bOverride)
{
DoSetState(
TRef<Material>(pmaterial),
m_pstateDevice->m_pmaterial,
m_pstate->m_pmaterial,
bOverride,
StateChangeMaterial()
);
}
void SetTexture(Surface* psurface, bool bOverride)
{
DoSetState(
TRef<Surface>(psurface),
m_pstateDevice->m_psurfaceTexture,
m_pstate->m_psurfaceTexture,
bOverride,
StateChangeTexture()
);
}
void SetDeformation(Deformation* pdeform, bool bOverride)
{
DoSetState(
TRef<Deformation>(pdeform),
m_pstateDevice->m_pdeform,
m_pstate->m_pdeform,
bOverride,
StateChangeDeformation()
);
}
void SetLineWidth(float width, bool bOverride = false)
{
DoSetState(
width,
m_pstateDevice->m_lineWidth,
m_pstate->m_lineWidth,
bOverride,
StateChangeLineWidth()
);
}
void UpdateState()
{
const StateChange& maskChanges = m_pstateDevice->m_maskChanges;
if (maskChanges.Test(stCommon)) {
if (maskChanges.Test(StateChangeMatrix())) {
m_pdevice3D->SetMatrix(m_pstateDevice->m_mat);
}
if (maskChanges.Test(StateChangeMaterial())) {
m_pdevice3D->SetMaterial(m_pstateDevice->m_pmaterial);
}
if (maskChanges.Test(StateChangeTexture())) {
m_pdevice3D->SetTexture(m_pstateDevice->m_psurfaceTexture);
}
}
if (maskChanges.Test(stUncommon)) {
if (maskChanges.Test(StateChangeDeformation())) {
m_pdevice3D->SetDeformation(m_pstateDevice->m_pdeform);
}
if (maskChanges.Test(StateChangePerspectiveMatrix())) {
m_pdevice3D->SetPerspectiveMatrix(m_pstateDevice->m_matPerspective);
}
if (maskChanges.Test(StateChangeColor())) {
m_pdevice3D->SetGlobalColor(m_pstateDevice->m_color);
}
if (maskChanges.Test(StateChangeClipRect())) {
m_pdevice3D->SetClipRect(m_pstateDevice->m_rectClip);
}
if (maskChanges.Test(StateChangeShadeMode())) {
m_pdevice3D->SetShadeMode(m_pstateDevice->m_shadeMode);
}
if (maskChanges.Test(StateChangeBlendMode())) {
m_pdevice3D->SetBlendMode(m_pstateDevice->m_blendMode);
}
if (maskChanges.Test(StateChangeWrapMode())) {
m_pdevice3D->SetWrapMode(m_pstateDevice->m_wrapMode);
}
if (maskChanges.Test(StateChangeCullMode())) {
m_pdevice3D->SetCullMode(m_pstateDevice->m_cullMode);
}
if (maskChanges.Test(StateChangeZTest())) {
m_pdevice3D->SetZTest(m_pstateDevice->m_bZTest);
}
if (maskChanges.Test(StateChangeZWrite())) {
m_pdevice3D->SetZWrite(m_pstateDevice->m_bZWrite);
}
if (maskChanges.Test(StateChangeLinearFilter())) {
m_pdevice3D->SetLinearFilter(m_pstateDevice->m_bLinearFilter);
}
if (maskChanges.Test(StateChangePerspectiveCorrection())) {
m_pdevice3D->SetPerspectiveCorrection(m_pstateDevice->m_bPerspectiveCorrection);
}
if (maskChanges.Test(StateChangeDither())) {
m_pdevice3D->SetDither(m_pstateDevice->m_bDither);
}
if (maskChanges.Test(StateChangeColorKey())) {
m_pdevice3D->SetColorKey(m_pstateDevice->m_bColorKey);
}
if (maskChanges.Test(StateChangeLineWidth())) {
m_pdevice3D->SetLineWidth(m_pstateDevice->m_lineWidth);
}
}
m_pstateDevice->m_maskChanges.Clear(StateChangeAll());
}
void PushState()
{
m_pstate = new State(m_pstate);
}
void PopState()
{
const StateChange& maskChanges = m_pstate->m_maskChanges;
if (maskChanges.Test(stCommon)) {
if (maskChanges.Test(StateChangeMatrix())) {
m_pstateDevice->m_mat = m_pstate->m_mat;
}
if (maskChanges.Test(StateChangeMaterial())) {
m_pstateDevice->m_pmaterial = m_pstate->m_pmaterial;
}
if (maskChanges.Test(StateChangeTexture())) {
m_pstateDevice->m_psurfaceTexture = m_pstate->m_psurfaceTexture;
}
}
if (maskChanges.Test(stUncommon)) {
if (maskChanges.Test(StateChangeDeformation())) {
m_pstateDevice->m_pdeform = m_pstate->m_pdeform;
}
if (maskChanges.Test(StateChangeClipPlanes())) {
while (m_pstateDevice->m_countClipPlanes > m_pstate->m_countClipPlanes) {
m_pdevice3D->RemoveClipPlane(0);
m_pstateDevice->m_countClipPlanes--;
}
}
if (maskChanges.Test(StateChangeColor())) {
m_pstateDevice->m_color = m_pstate->m_color;
}
if (maskChanges.Test(StateChangeClipRect())) {
m_pstateDevice->m_rectClip = m_pstate->m_rectClip;
}
if (maskChanges.Test(StateChangePerspectiveMatrix())) {
m_pstateDevice->m_matPerspective = m_pstate->m_matPerspective;
}
if (maskChanges.Test(StateChangeShadeMode())) {
m_pstateDevice->m_shadeMode = m_pstate->m_shadeMode;
}
if (maskChanges.Test(StateChangeBlendMode())) {
m_pstateDevice->m_blendMode = m_pstate->m_blendMode;
}
if (maskChanges.Test(StateChangeWrapMode())) {
m_pstateDevice->m_wrapMode = m_pstate->m_wrapMode;
}
if (maskChanges.Test(StateChangeCullMode())) {
m_pstateDevice->m_cullMode = m_pstate->m_cullMode;
}
if (maskChanges.Test(StateChangeZTest())) {
m_pstateDevice->m_bZTest = m_pstate->m_bZTest;
}
if (maskChanges.Test(StateChangeZWrite())) {
m_pstateDevice->m_bZWrite = m_pstate->m_bZWrite;
}
if (maskChanges.Test(StateChangeLinearFilter())) {
m_pstateDevice->m_bLinearFilter = m_pstate->m_bLinearFilter;
}
if (maskChanges.Test(StateChangePerspectiveCorrection())) {
m_pstateDevice->m_bPerspectiveCorrection = m_pstate->m_bPerspectiveCorrection;
}
if (maskChanges.Test(StateChangeDither())) {
m_pstateDevice->m_bDither = m_pstate->m_bDither;
}
if (maskChanges.Test(StateChangeColorKey())) {
m_pstateDevice->m_bColorKey = m_pstate->m_bColorKey;
}
if (maskChanges.Test(StateChangeLineWidth())) {
m_pstateDevice->m_lineWidth = m_pstate->m_lineWidth;
}
}
m_pstateDevice->m_maskChanges.Set(m_pstate->m_maskChanges);
m_pstateDevice->m_maskOverride.Clear(m_pstate->m_maskOverride);
m_pstate = m_pstate->m_pnext;
}
Point Transform2D(const Point& point)
{
Point pointImage;
ZVerify(TransformLocalToImage(Vector(point.X(), point.Y(), 0), pointImage));
return pointImage;
}
WinRect GetSurfaceClipRect()
{
return
WinRect(
int(m_pstateDevice->m_rectClip.XMin()),
m_psurface->GetSize().Y() - int(m_pstateDevice->m_rectClip.YMax()),
int(m_pstateDevice->m_rectClip.XMax()),
m_psurface->GetSize().Y() - int(m_pstateDevice->m_rectClip.YMin())
);
}
void Clip(const Rect& rect)
{
ZAssert(!m_bIn3DLayer);
if (!m_pstate->m_maskChanges.Test(StateChangeClipRect())) {
m_pstate->m_rectClip = m_pstateDevice->m_rectClip;
m_pstate->m_maskChanges.Set(StateChangeClipRect());
}
m_pstateDevice->m_rectClip.Intersect(
Rect(
Transform2D(rect.Min()),
Transform2D(rect.Max())
)
);
m_pstateDevice->m_maskChanges.Set(StateChangeClipRect());
}
void AddClipPlane(const Plane& plane)
{
if (!m_pstate->m_maskChanges.Test(StateChangeClipPlanes())) {
m_pstate->m_countClipPlanes = m_pstateDevice->m_countClipPlanes;
m_pstate->m_maskChanges.Set(StateChangeClipPlanes());
}
UpdateState();
m_pdevice3D->AddClipPlane(plane);
m_pstateDevice->m_countClipPlanes++;
}
void PreMatrixChanged()
{
ZAssert(m_bIn3DLayer);
if (!m_pstate->m_maskChanges.Test(StateChangeMatrix())) {
m_pstate->m_mat = m_pstateDevice->m_mat;
m_pstate->m_maskChanges.Set(StateChangeMatrix());
}
m_pstateDevice->m_maskChanges.Set(StateChangeMatrix());
}
void SetTransform(const Matrix& mat)
{
PreMatrixChanged();
m_pstateDevice->m_mat = mat;
}
void Multiply(const Matrix& mat)
{
PreMatrixChanged();
m_pstateDevice->m_mat.PreMultiply(mat);
}
void Rotate(const Vector& vec, float angle)
{
PreMatrixChanged();
m_pstateDevice->m_mat.PreRotate(vec, angle);
}
void Translate(const Vector& vec)
{
PreMatrixChanged();
m_pstateDevice->m_mat.PreTranslate(vec);
}
void Scale(const Vector& vec)
{
PreMatrixChanged();
m_pstateDevice->m_mat.PreScale(vec);
}
void Scale3(float scale)
{
PreMatrixChanged();
m_pstateDevice->m_mat.PreScale(scale);
}
void PrePerspectiveMatrixChanged()
{
ZAssert(!m_bIn3DLayer);
if (!m_pstate->m_maskChanges.Test(StateChangePerspectiveMatrix())) {
m_pstate->m_matPerspective = m_pstateDevice->m_matPerspective;
m_pstate->m_maskChanges.Set(StateChangePerspectiveMatrix());
}
m_pstateDevice->m_maskChanges.Set(StateChangePerspectiveMatrix());
}
void SetMatrix(const Matrix2& mat)
{
PrePerspectiveMatrixChanged();
m_pstateDevice->m_matPerspective = mat;
}
void Multiply(const Matrix2& mat)
{
PrePerspectiveMatrixChanged();
m_pstateDevice->m_matPerspective.PreMultiply(mat);
}
void Rotate(float angle)
{
PrePerspectiveMatrixChanged();
m_pstateDevice->m_matPerspective.PreRotate(Vector(0, 0, 1), angle);
}
void Translate(const Point& point)
{
PrePerspectiveMatrixChanged();
m_pstateDevice->m_matPerspective.PreTranslate(Vector(point.X(), point.Y(), 0));
}
void Scale(const Point& point)
{
PrePerspectiveMatrixChanged();
m_pstateDevice->m_matPerspective.PreScale(Vector(point.X(), point.Y(), 0));
}
void Scale2(float scale)
{
PrePerspectiveMatrixChanged();
m_pstateDevice->m_matPerspective.PreScale(Vector(scale, scale, 1));
}
void SetPerspectiveMatrix(const Matrix& mat)
{
PrePerspectiveMatrixChanged();
m_pstateDevice->m_matPerspective.PreMultiply(mat);
}
const Matrix& GetLocalToEyeMatrix()
{
return m_pstateDevice->m_mat;
}
const Matrix& GetEyeToLocalMatrix()
{
UpdateState();
return m_pdevice3D->GetInverseModelMatrix();
}
Vector TransformEyeToLocal(const Vector& vec)
{
return GetEyeToLocalMatrix().Transform(vec);
}
Vector TransformLocalToEye(const Vector& vec)
{
return GetLocalToEyeMatrix().Transform(vec);
}
Vector TransformDirectionToEye(const Vector& vec)
{
HVector hvec = m_pstateDevice->m_mat.Transform(HVector(vec.X(), vec.Y(), vec.Z(), 0));
return Vector(hvec.X(), hvec.Y(), hvec.Z());
}
bool TransformEyeToImage(const Vector& vecEye, Point& point)
{
HVector hvecImage = m_pstateDevice->m_matPerspective.Transform(HVector(vecEye));
if (hvecImage.W() < 0) {
return false;
}
float rhw = 1.0f / hvecImage.W();
point =
Point(
rhw * hvecImage.X(),
rhw * hvecImage.Y()
);
return true;
}
bool TransformDirectionToImage(const Vector& vec, Point& point)
{
return TransformEyeToImage(TransformDirectionToEye(vec), point);
}
bool TransformLocalToImage(const Vector& vec, Point& point)
{
return TransformEyeToImage(TransformLocalToEye(vec), point);
}
WinPoint TransformImageToSurface(const Point& point)
{
const WinPoint& size = m_psurface->GetSize();
return
WinPoint(
MakeInt(point.X()),
size.Y() - MakeInt(point.Y())
);
}
float GetImageRadius(const Vector& vec, float radius)
{
Vector vecEye = TransformLocalToEye(vec);
Point point;
if (TransformEyeToImage(vecEye, point)) {
Point pointRadius;
if (TransformEyeToImage(vecEye + Vector(radius, 0, 0), pointRadius)) {
return pointRadius.X() - point.X();
}
}
return radius;
}
void DirectionalLight(const Vector& vec, const Color& color)
{
UpdateState();
m_pdevice3D->DirectionalLight(vec, color);
}
void BidirectionalLight(const Vector& direction, const Color& color, const Color& colorAlt)
{
UpdateState();
m_pdevice3D->BidirectionalLight(direction, color, colorAlt);
}
void SetAmbientLevel(float ambientLevel)
{
m_pdevice3D->SetAmbientLevel(ambientLevel);
}
void DrawCallbackGeo(IGeoCallback* pgeoCallback, bool bSortObject)
{
if (m_bIn3DLayer) {
if (m_bRenderingCallbacks) {
PushState();
pgeoCallback->RenderCallback(this);
PopState();
} else {
if (bSortObject) {
GeoCallbackData dataNew;
dataNew.m_mat = m_pstateDevice->m_mat;
dataNew.m_pgeoCallback = pgeoCallback;
dataNew.m_distance = m_pstateDevice->m_mat.GetTranslate().LengthSquared();
m_listGeoCallbacksSorted.InsertSorted(dataNew);
} else {
m_listGeoCallbacks.PushFront();
GeoCallbackData& data = m_listGeoCallbacks.GetFront();
data.m_mat = m_pstateDevice->m_mat;
data.m_pgeoCallback = pgeoCallback;
}
}
} else {
pgeoCallback->RenderCallback(this);
}
}
void SizeVertexBuffer(int count)
{
if (m_countVertexBuffer < count) {
m_countVertexBuffer = count;
m_pvertexBuffer = (Vertex*)realloc(m_pvertexBuffer, sizeof(Vertex) * count);
}
}
void SizeIndexBuffer(int count)
{
if (m_countIndexBuffer < count) {
m_countIndexBuffer = count;
m_pindexBuffer = (MeshIndex*)realloc(m_pindexBuffer, sizeof(MeshIndex) * count);
}
}
Vertex* GetVertexBuffer(int count)
{
SizeVertexBuffer(count);
return m_pvertexBuffer;
}
MeshIndex* GetIndexBuffer(int count)
{
SizeIndexBuffer(count);
return m_pindexBuffer;
}
VertexL* GetVertexLBuffer(int count)
{
return m_pdevice3D->GetVertexLBuffer(count);
}
VertexScreen* GetVertexScreenBuffer(int count)
{
return m_pdevice3D->GetVertexScreenBuffer(count);
}
void DD2D()
{
ZAssert(m_bRendering);
ZAssert(!m_bIn3DLayer);
EndScene();
UpdateState();
}
void Texture2D()
{
ZAssert(m_bRendering);
ZAssert(!m_bIn3DLayer);
BeginScene();
UpdateState();
}
void Mode3D()
{
ZAssert(m_bRendering);
if (!m_bIn3DLayer) {
Texture2D();
} else {
ZAssert(m_bInScene);
UpdateState();
}
}
void DrawTriangles(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
if (icount != 0) {
Mode3D();
m_pdevice3D->DrawTriangles(pvertex, vcount, pindex, icount);
}
}
void DrawTriangles(const VertexL* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
if (icount != 0) {
Mode3D();
m_pdevice3D->DrawTriangles(pvertex, vcount, pindex, icount);
}
}
void DrawTriangles(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
if (icount != 0) {
Mode3D();
m_pdevice3D->DrawTriangles(pvertex, vcount, pindex, icount);
}
}
void DrawTriangles(const D3DVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
Mode3D();
m_pdevice3D->DrawTriangles(pvertex, vcount, pindex, icount);
}
void DrawLineStrip(const Vertex* pvertex, int vcount)
{
int icount = (vcount - 1) * 2;
MeshIndex* pindex = GetIndexBuffer(icount);
for (int index = 0; index < vcount - 1; index++) {
pindex[index * 2 ] = index;
pindex[index * 2 + 1] = index + 1;
}
DrawLines(pvertex, vcount, pindex, icount);
}
void DrawLineStrip(const VertexL* pvertex, int vcount)
{
int icount = (vcount - 1) * 2;
MeshIndex* pindex = GetIndexBuffer(icount);
for (int index = 0; index < vcount - 1; index++) {
pindex[index * 2 ] = index;
pindex[index * 2 + 1] = index + 1;
}
DrawLines(pvertex, vcount, pindex, icount);
}
void DrawLineStrip(const VertexScreen* pvertex, int vcount)
{
int icount = (vcount - 1) * 2;
MeshIndex* pindex = GetIndexBuffer(icount);
for (int index = 0; index < vcount - 1; index++) {
pindex[index * 2 ] = index;
pindex[index * 2 + 1] = index + 1;
}
DrawLines(pvertex, vcount, pindex, icount);
}
void DrawLineStrip(const D3DVertex* pvertex, int vcount)
{
int icount = (vcount - 1) * 2;
MeshIndex* pindex = GetIndexBuffer(icount);
for (int index = 0; index < vcount - 1; index++) {
pindex[index * 2 ] = index;
pindex[index * 2 + 1] = index + 1;
}
DrawLines(pvertex, vcount, pindex, icount);
}
void DrawLines(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
if (icount != 0) {
Mode3D();
m_pdevice3D->DrawLines(pvertex, vcount, pindex, icount);
}
}
void DrawLines(const VertexL* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
if (icount != 0) {
Mode3D();
m_pdevice3D->DrawLines(pvertex, vcount, pindex, icount);
}
}
void DrawLines(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
if (icount != 0) {
Mode3D();
m_pdevice3D->DrawLines(pvertex, vcount, pindex, icount);
}
}
void DrawLines(const D3DVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
Mode3D();
m_pdevice3D->DrawLines(pvertex, vcount, pindex, icount);
}
void DrawPoints(const Vertex* pvertex, int vcount)
{
if (vcount != 0) {
Mode3D();
m_pdevice3D->DrawPoints(pvertex, vcount);
}
}
void DrawPoints(const VertexL* pvertex, int vcount)
{
if (vcount != 0) {
Mode3D();
m_pdevice3D->DrawPoints(pvertex, vcount);
}
}
void DrawPoints(const VertexScreen* pvertex, int vcount)
{
if (vcount != 0) {
Mode3D();
m_pdevice3D->DrawPoints(pvertex, vcount);
}
}
void DrawPoints(const D3DVertex* pvertex, int vcount)
{
Mode3D();
m_pdevice3D->DrawPoints(pvertex, vcount);
}
void DrawTriangles(const TVector<Vertex>& vertices, const TVector<MeshIndex>& indices)
{
DrawTriangles(&(vertices[0]), vertices.GetCount(), &(indices[0]), indices.GetCount());
}
void DrawTriangles(const TVector<VertexL>& vertices, const TVector<MeshIndex>& indices)
{
DrawTriangles(&(vertices[0]), vertices.GetCount(), &(indices[0]), indices.GetCount());
}
void DrawTriangles(const TVector<D3DVertex>& vertices, const TVector<MeshIndex>& indices)
{
DrawTriangles(&(vertices[0]), vertices.GetCount(), &(indices[0]), indices.GetCount());
}
void DrawLines(const TVector<Vertex>& vertices, const TVector<MeshIndex>& indices)
{
DrawLines(&(vertices[0]), vertices.GetCount(), &(indices[0]), indices.GetCount());
}
void DrawLines(const TVector<VertexL>& vertices, const TVector<MeshIndex>& indices)
{
DrawLines(&(vertices[0]), vertices.GetCount(), &(indices[0]), indices.GetCount());
}
void DrawLines(const TVector<D3DVertex>& vertices, const TVector<MeshIndex>& indices)
{
DrawLines(&(vertices[0]), vertices.GetCount(), &(indices[0]), indices.GetCount());
}
void DrawPoints(const TVector<Vertex>& vertices)
{
DrawPoints(&(vertices[0]), vertices.GetCount());
}
void DrawPoints(const TVector<VertexL>& vertices)
{
DrawPoints(&(vertices[0]), vertices.GetCount());
}
void DrawPoints(const TVector<D3DVertex>& vertices)
{
DrawPoints(&(vertices[0]), vertices.GetCount());
}
Decal& AddDecal(TVector<DecalSet>& vdecalSet, Surface* psurface)
{
int countDecalSets = vdecalSet.GetCount();
int indexSet;
for(indexSet = 0; indexSet < countDecalSets; indexSet++) {
const DecalSet& set = vdecalSet[indexSet];
if (psurface == set.m_psurface) {
break;
}
}
if (indexSet == countDecalSets) {
vdecalSet.PushEnd();
vdecalSet.Get(indexSet).m_psurface = psurface;
}
DecalSet& set = vdecalSet.Get(indexSet);
set.m_vdecal.PushEnd();
return set.m_vdecal.Get(set.m_vdecal.GetCount() - 1);
}
float DrawDecal(
Surface* psurface,
const Color& color,
const Vector& positionLocal,
const Vector& forwardLocal,
const Vector& rightLocal,
float scale,
float angle,
BlendMode blendMode
) {
ZAssert(
blendMode == BlendModeSource
|| blendMode == BlendModeAdd
);
const Matrix& mat = GetLocalToEyeMatrix();
Vector position = mat.Transform(positionLocal);
if (position.Z() < 0) {
Decal& decal =
AddDecal(
blendMode == BlendModeSource
? m_vdecalSetOpaque
: m_vdecalSet,
psurface
);
float sizeScale = 4.0f / (position.Z() * position.Z());
float scaleMat = mat.GetScale();
decal.m_position = position;
decal.m_color = color;
decal.m_angle = angle;
decal.m_scale = scaleMat * scale;
if (forwardLocal.IsZero()) {
decal.m_forward = Vector(0, 0, 0);
return sizeScale * decal.m_scale * decal.m_scale;
} else {
decal.m_forward = scaleMat * mat.TransformDirection(forwardLocal);
if (rightLocal.IsZero()) {
Vector right = decal.m_forward.GetOrthogonalVector();
float lengthForward = forwardLocal.Length();
float lengthRight = decal.m_scale * lengthForward;
decal.m_right = lengthRight * right.Normalize();
return sizeScale * lengthForward * lengthRight;
} else {
decal.m_right = scaleMat * mat.TransformDirection(rightLocal);
return sizeScale * decal.m_right.Length() * decal.m_forward.Length();
}
}
}
return 0;
}
void DrawVDecalSet(TVector<DecalSet>& vdecalSet)
{
int countDecalSets = vdecalSet.GetCount();
for(int indexSet = 0; indexSet < countDecalSets; indexSet++) {
DecalSet& set = vdecalSet.Get(indexSet);
int countDecal = set.m_vdecal.GetCount();
if (countDecal > 0) {
SetTexture(set.m_psurface, false);
VertexL* pvertex = GetVertexLBuffer(countDecal * 4);
MeshIndex* pindex = GetIndexBuffer(countDecal * 6);
int index;
for (index = 0; index < countDecal; index++) {
set.m_vdecal[index].GetVertices(pvertex + index * 4);
pindex[index * 6 + 0] = index * 4 + 0;
pindex[index * 6 + 1] = index * 4 + 2;
pindex[index * 6 + 2] = index * 4 + 1;
pindex[index * 6 + 3] = index * 4 + 0;
pindex[index * 6 + 4] = index * 4 + 3;
pindex[index * 6 + 5] = index * 4 + 2;
}
UpdateState();
m_pdevice3D->DrawTriangles(
&pvertex[0],
index * 4,
&pindex[0],
index * 6
);
set.m_vdecal.SetCount(0);
}
}
}
void DrawCachedDecals()
{
SetCullMode(CullModeNone, false);
SetShadeMode(ShadeModeFlat, false);
SetTransform(Matrix::GetIdentity());
SetBlendMode(BlendModeSource, false);
SetZWrite(true, false);
DrawVDecalSet(m_vdecalSetOpaque);
SetBlendMode(BlendModeAdd, false);
SetZWrite(false, false);
DrawVDecalSet(m_vdecalSet);
}
#ifdef EnablePerformanceCounters
int GetPerformanceCounter(Counter counter)
{
if (counter == CounterDrawStrings)
return m_countDrawString;
else if (counter == CounterDrawStringChars)
return m_countDrawStringChars;
return m_pdevice3D->GetPerformanceCounter(counter);
}
void ResetPerformanceCounters()
{
m_countDrawString = 0;
m_countDrawStringChars = 0;
m_pdevice3D->ResetPerformanceCounters();
}
#endif
};
TRef<PrivateContext> CreateContextImpl(PrivateSurface* psurface)
{
return new ContextImpl(psurface);
}