#include "pch.h"
#pragma optimize("t", on)
const int g_maxCountPlanes = 8;
typedef BYTE Code;
const Code ClipFront = 0x01;
const Code ClipBack = 0x02;
const Code ClipLeft = 0x04;
const Code ClipRight = 0x08;
const Code ClipBottom = 0x10;
const Code ClipTop = 0x20;
const Code ClipPlane = 0x40;
class VertexTL {
public:
HVector m_pos;
Color m_color;
Point m_pointTexture;
MeshIndex m_index;
Code m_code;
VertexTL()
{
}
VertexTL(const VertexTL& v) :
m_pos(v.m_pos),
m_color(v.m_color),
m_pointTexture(v.m_pointTexture),
m_index(v.m_index),
m_code(v.m_code)
{
}
void Interpolate(const VertexTL& vertex0, const VertexTL& vertex1, float alpha)
{
float beta = 1 - alpha;
m_pos = ::Interpolate(vertex0.m_pos, vertex1.m_pos, alpha);
m_color =
Color(
alpha * vertex1.m_color.GetRed() + beta * vertex0.m_color.GetRed() ,
alpha * vertex1.m_color.GetGreen() + beta * vertex0.m_color.GetGreen(),
alpha * vertex1.m_color.GetBlue() + beta * vertex0.m_color.GetBlue() ,
alpha * vertex1.m_color.GetAlpha() + beta * vertex0.m_color.GetAlpha()
);
m_pointTexture = ::Interpolate(vertex0.m_pointTexture, vertex1.m_pointTexture, alpha);
}
void UpdateClipCode()
{
m_code = 0;
if (m_pos.x < -m_pos.w) m_code |= ClipLeft;
if (m_pos.x > m_pos.w) m_code |= ClipRight;
if (m_pos.y < -m_pos.w) m_code |= ClipBottom;
if (m_pos.y > m_pos.w) m_code |= ClipTop;
if (m_pos.z < 0 ) m_code |= ClipFront;
if (m_pos.z > m_pos.w) m_code |= ClipBack;
}
void UpdateClipCode(const Plane& plane, Code code)
{
if (plane.Distance(m_pos) <= 0) {
m_code |= code;
}
}
};
class Device3D : public IDevice3D {
typedef void (Device3D::*PFNClip)(VertexTL* pvertex, int vcount, const MeshIndex* pindex, int icount);
typedef void (Device3D::*PFNDraw)(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount);
typedef void (Device3D::*PFNVertex)(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw);
typedef void (Device3D::*PFNVertexL)(const VertexL* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw);
TRef<Rasterizer> m_prasterizer;
Point m_sizeSurface;
Rect m_rectClip;
Rect m_rectClipScreen;
bool m_bClip;
bool m_bZTest;
bool m_bZWrite;
ShadeMode m_shadeMode;
BlendMode m_blendMode;
PFNVertexL m_pfnTransform;
PFNVertex m_pfnLightVertex;
PFNVertexL m_pfnLightVertexL;
PFNDraw m_pfnDrawLines;
Matrix m_mat;
Matrix m_matPerspective;
Matrix m_matFull;
Matrix m_matInverse;
bool m_bUpdateMatFull;
bool m_bUpdateLighting;
bool m_bUpdatePointers;
bool m_bUpdateInverse;
TRef<Material> m_pmaterial;
TRef<Deformation> m_pdeform;
float m_lineWidth;
float m_brightAmbient;
Vector m_vecLight;
Vector m_vecLightWorld;
Color m_color;
Color m_colorAlt;
Color m_colorGlobal;
bool m_bBidirectional;
float m_scalex;
float m_scaley;
float m_xoffset;
float m_yoffset;
int m_countPlanes;
Plane m_pplane[g_maxCountPlanes];
VertexL* m_pvertexLBuffer;
int m_countVertexLBuffer;
VertexTL* m_pvertexTLBuffer;
int m_countVertexTLBuffer;
VertexScreen* m_pvertexScreenBuffer;
int m_countVertexScreenBuffer;
int m_indexVertexScreenBuffer;
MeshIndex* m_pindexBuffer;
int m_countIndexBuffer;
int m_indexIndexBuffer;
#ifdef EnablePerformanceCounters
int m_countPoints;
int m_countLines;
int m_countTriangles;
int m_countMeshes;
int m_countObjects;
int m_countObjectsRendered;
int m_countMatrixLoads;
#endif
public:
Device3D(Rasterizer* prasterizer) :
m_prasterizer(prasterizer),
m_pvertexLBuffer(NULL),
m_countVertexLBuffer(0),
m_pvertexTLBuffer(NULL),
m_countVertexTLBuffer(0),
m_pvertexScreenBuffer(NULL),
m_countVertexScreenBuffer(0),
m_indexVertexScreenBuffer(0),
m_pindexBuffer(NULL),
m_countIndexBuffer(0),
m_indexIndexBuffer(0),
m_bClip(true),
m_shadeMode(ShadeModeGouraud),
m_bUpdateMatFull(true),
m_bUpdateLighting(true),
m_bUpdatePointers(true),
m_brightAmbient(0.0f),
m_vecLightWorld(1, 0, 0),
m_color(Color::White()),
m_colorAlt(Color::White()),
m_colorGlobal(Color::White()),
m_pfnDrawLines(&Device3D::DrawLinesRasterizer),
m_lineWidth(0.5f)
{
m_sizeSurface = prasterizer->GetSurfaceSize();
m_mat.SetIdentity();
m_matPerspective.SetIdentity();
m_countPlanes = 6;
m_pplane[0] = Plane(HVector( 0, 0, 1, 0));
m_pplane[1] = Plane(HVector( 0, 0, 1, -1));
m_pplane[2] = Plane(HVector( 1, 0, 0, 1));
m_pplane[3] = Plane(HVector(-1, 0, 0, 1));
m_pplane[4] = Plane(HVector( 0, 1, 0, 1));
m_pplane[5] = Plane(HVector( 0,-1, 0, 1));
#ifdef EnablePerformanceCounters
ResetPerformanceCounters();
#endif
}
bool IsValid()
{
return m_prasterizer->IsValid();
}
#ifdef EnablePerformanceCounters
void ResetPerformanceCounters()
{
m_countPoints = 0;
m_countLines = 0;
m_countTriangles = 0;
m_countMeshes = 0;
m_countObjects = 0;
m_countObjectsRendered = 0;
m_countMatrixLoads = 0;
}
int GetPerformanceCounter(Counter counter)
{
switch (counter) {
case CounterPoints : return m_countPoints ;
case CounterLines : return m_countLines ;
case CounterTriangles : return m_countTriangles ;
case CounterMeshes : return m_countMeshes ;
case CounterObjects : return m_countObjects ;
case CounterObjectsRendered : return m_countObjectsRendered;
case CounterMatrixLoads : return m_countMatrixLoads ;
}
ZError("Unknown counter");
return 0;
}
#endif
~Device3D()
{
if (m_pvertexLBuffer) {
free(m_pvertexLBuffer);
}
if (m_pvertexTLBuffer) {
free(m_pvertexTLBuffer);
}
if (m_pvertexScreenBuffer) {
free(m_pvertexScreenBuffer);
}
if (m_pindexBuffer) {
free(m_pindexBuffer);
}
}
bool Has3DAcceleration()
{
return m_prasterizer->Has3DAcceleration();
}
void BeginScene()
{
m_prasterizer->BeginScene();
}
void EndScene()
{
m_prasterizer->EndScene();
}
void ClearZBuffer()
{
m_prasterizer->ClearZBuffer();
}
void SetClipRect(const Rect& rectClip)
{
m_rectClip = rectClip;
m_rectClipScreen =
Rect(
rectClip.XMin(),
m_sizeSurface.Y() - rectClip.YMax(),
rectClip.XMax(),
m_sizeSurface.Y() - rectClip.YMin()
);
m_bUpdateMatFull = true;
m_prasterizer->SetClipRect(m_rectClipScreen);
}
void DirectionalLight(const Vector& vec, const Color& color)
{
m_vecLightWorld = m_mat.TransformDirection(vec);
m_bBidirectional = false;
}
void BidirectionalLight(const Vector& vec, const Color& color, const Color& colorAlt)
{
m_vecLightWorld = m_mat.TransformDirection(vec);
m_color = color;
m_colorAlt = colorAlt;
m_bBidirectional = true;
}
void SetAmbientLevel(float level)
{
m_brightAmbient = level;
}
void SetGlobalColor(const Color& color)
{
m_colorGlobal = color;
}
const Matrix& GetFullMatrix()
{
if (m_bUpdateMatFull) {
m_bUpdateMatFull = false;
m_matFull = m_mat;
m_matFull.Multiply(m_matPerspective);
if (m_bClip) {
Point pointCenter = m_rectClip.Center();
float scalex = 0.5f * m_rectClip.XSize();
float scaley = 0.5f * m_rectClip.YSize();
m_matFull.Translate(
Vector(
-pointCenter.X(),
-pointCenter.Y(),
0
)
);
m_matFull.Scale(
Vector(
1 / scalex,
1 / scaley,
1.0f
)
);
m_xoffset = pointCenter.X(); m_yoffset = m_sizeSurface.Y() - pointCenter.Y(); m_scalex = 0.5f * m_rectClip.XSize();
m_scaley = -0.5f * m_rectClip.YSize();
} else {
m_matFull.Translate(Vector(0, -m_sizeSurface.Y(), 0));
m_matFull.Scale(Vector(1, -1, 1));
}
}
return m_matFull;
}
void UpdateLighting()
{
if (m_bUpdateLighting) {
m_bUpdateLighting = false;
m_vecLight = GetInverseModelMatrix().TransformDirection(m_vecLightWorld);
m_vecLight.SetNormalize();
}
}
void UpdatePointers()
{
if (m_bUpdatePointers) {
m_bUpdatePointers = false;
bool bClip = m_bClip || m_countPlanes > 6;
if (m_pdeform != NULL) {
bClip = true;
m_pfnTransform = &Device3D::TransformDeformClip;
} else if (bClip) {
m_pfnTransform = &Device3D::TransformClip;
} else {
m_pfnTransform = &Device3D::TransformNoClip;
}
m_pfnLightVertexL = m_pfnTransform;
switch (m_shadeMode) {
case ShadeModeNone:
case ShadeModeCopy:
if (bClip) {
m_pfnLightVertex = &Device3D::LightVertexCopy;
} else {
m_pfnLightVertex = &Device3D::TransformNoClipNoLight;
}
break;
case ShadeModeGlobalColor:
m_pfnLightVertex = &Device3D::LightVertexGlobalColor;
break;
case ShadeModeFlat:
case ShadeModeGouraud:
if (m_pmaterial) {
m_pfnLightVertex = &Device3D::MaterialLightVertex;
} else if (m_bBidirectional) {
m_pfnLightVertex = &Device3D::BidirectionalLightVertex;
} else {
if (bClip) {
m_pfnLightVertex = &Device3D::LightVertex;
} else {
m_pfnLightVertex = &Device3D::TransformAndLightNoClip;
}
}
break;
default:
ZError("Invalid ShadeMode");
}
if (
(m_lineWidth == 0.5f)
&& (
m_prasterizer->Has3DAcceleration()
|| (
(m_lineWidth == 0.5f)
&& (!m_bZTest)
&& (!m_bZWrite)
&& (m_shadeMode == ShadeModeFlat)
&& (m_blendMode == BlendModeSource)
)
)
) {
m_pfnDrawLines = &Device3D::DrawLinesRasterizer;
} else {
m_pfnDrawLines = &Device3D::DrawLinesWithPolygons;
}
}
}
bool GetClipping()
{
return m_bClip;
}
const Matrix& GetMatrix()
{
return m_mat;
}
const Matrix& GetInverseModelMatrix()
{
if (m_bUpdateInverse) {
m_bUpdateInverse = false;
m_matInverse.SetInverse(m_mat);
}
return m_matInverse;
}
void SetMatrix(const Matrix& mat)
{
m_mat = mat;
m_bUpdateMatFull = true;
m_bUpdateLighting = true;
m_bUpdateInverse = true;
}
void SetPerspectiveMatrix(const Matrix& mat)
{
m_matPerspective = mat;
m_bUpdateMatFull = true;
}
void SetClipping(bool bClip)
{
m_bClip = bClip;
m_bUpdateMatFull = true;
m_bUpdatePointers = true;
}
void RemoveClipPlane(int indexRemove)
{
ZAssert(indexRemove >= 0 && indexRemove + 6 < m_countPlanes);
for(int index = m_countPlanes - indexRemove - 1; index < m_countPlanes - 1; index++) {
m_pplane[index] = m_pplane[index + 1];
}
m_countPlanes--;
}
void AddClipPlane(const Plane& plane)
{
ZAssert(m_countPlanes < g_maxCountPlanes);
const Matrix& mat = GetFullMatrix();
Matrix mati;
mati.SetInverse(mat);
mati.Transpose();
HVector p = plane.GetHVector();
HVector pp = mati.Transform(p);
m_pplane[m_countPlanes] = Plane(pp);
m_countPlanes++;
}
void SetShadeMode(ShadeMode shadeMode)
{
m_shadeMode = shadeMode;
m_bUpdatePointers = true;
m_prasterizer->SetShadeMode(shadeMode);
}
void SetMaterial(Material* pmaterial)
{
m_pmaterial = pmaterial;
m_bUpdatePointers = true;
}
void SetBlendMode(BlendMode blendMode)
{
m_blendMode = blendMode;
m_bUpdatePointers = true;
m_prasterizer->SetBlendMode(blendMode);
}
void SetTexture(Surface* psurfaceTexture)
{
m_prasterizer->SetTexture(psurfaceTexture);
}
void SetWrapMode(WrapMode wrapMode)
{
m_prasterizer->SetWrapMode(wrapMode);
}
void SetCullMode(CullMode cullMode)
{
m_prasterizer->SetCullMode(cullMode);
}
void SetZTest(bool bZTest)
{
m_bZTest = bZTest;
m_bUpdatePointers = true;
m_prasterizer->SetZTest(bZTest);
}
void SetZWrite(bool bZWrite)
{
m_bZWrite = bZWrite;
m_bUpdatePointers = true;
m_prasterizer->SetZWrite(bZWrite);
}
void SetLinearFilter(bool bLinearFilter)
{
m_prasterizer->SetLinearFilter(bLinearFilter);
}
void SetPerspectiveCorrection(bool bPerspectiveCorrection)
{
m_prasterizer->SetPerspectiveCorrection(bPerspectiveCorrection);
}
void SetDither(bool bDither)
{
m_prasterizer->SetDither(bDither);
}
void SetColorKey(bool bColorKey)
{
m_prasterizer->SetColorKey(bColorKey);
}
void SetLineWidth(float width)
{
m_lineWidth = 0.5f * width;
}
void SetDeformation(Deformation* pdeform)
{
m_pdeform = pdeform;
m_bUpdatePointers = true;
}
void SizeVertexLBuffer(int count)
{
if (m_countVertexLBuffer < count) {
m_countVertexLBuffer = count;
m_pvertexLBuffer = (VertexL*)realloc(m_pvertexLBuffer, sizeof(VertexL) * count);
}
}
void SizeVertexTLBuffer(int count)
{
if (m_countVertexTLBuffer < count) {
m_countVertexTLBuffer = count;
m_pvertexTLBuffer = (VertexTL*)realloc(m_pvertexTLBuffer, sizeof(VertexTL) * count);
}
}
void SizeVertexScreenBuffer(int count)
{
if (m_countVertexScreenBuffer < count) {
m_pvertexScreenBuffer = (VertexScreen*)realloc(m_pvertexScreenBuffer, sizeof(VertexScreen) * count);
for (int index = m_countVertexScreenBuffer; index < count; index++) {
m_pvertexScreenBuffer[index].specular = 0;
}
m_countVertexScreenBuffer = count;
}
}
void SizeIndexBuffer(int count)
{
if (m_countIndexBuffer < count) {
m_countIndexBuffer = count;
m_pindexBuffer = (MeshIndex*)realloc(m_pindexBuffer, sizeof(MeshIndex) * count);
}
}
VertexL* GetVertexLBuffer(int count)
{
SizeVertexLBuffer(count);
return m_pvertexLBuffer;
}
VertexScreen* GetVertexScreenBuffer(int count)
{
SizeVertexScreenBuffer(count);
return m_pvertexScreenBuffer;
}
void StoreTriangle(MeshIndex index1, MeshIndex index2, MeshIndex index3)
{
SizeIndexBuffer(m_indexIndexBuffer + 3);
m_pindexBuffer[m_indexIndexBuffer ] = index1;
m_pindexBuffer[m_indexIndexBuffer + 1] = index2;
m_pindexBuffer[m_indexIndexBuffer + 2] = index3;
m_indexIndexBuffer += 3;
}
void StoreLine(MeshIndex index1, MeshIndex index2)
{
SizeIndexBuffer(m_indexIndexBuffer + 2);
m_pindexBuffer[m_indexIndexBuffer ] = index1;
m_pindexBuffer[m_indexIndexBuffer + 1] = index2;
m_indexIndexBuffer += 2;
}
void ClampVertex(VertexScreen& vertex)
{
if (vertex.x < m_rectClipScreen.XMin()) {
vertex.x = m_rectClipScreen.XMin();
} else if (vertex.x > m_rectClipScreen.XMax()) {
vertex.x = m_rectClipScreen.XMax();
}
if (vertex.y < m_rectClipScreen.YMin()) {
vertex.y = m_rectClipScreen.YMin();
} else if (vertex.y > m_rectClipScreen.YMax()) {
vertex.y = m_rectClipScreen.YMax();
}
if (vertex.z < 0) {
vertex.z = 0;
} else if (vertex.z > 1) {
vertex.z = 1;
}
}
MeshIndex ConvertVertex(VertexTL& vertex)
{
SizeVertexScreenBuffer(m_indexVertexScreenBuffer + 1);
vertex.m_index = m_indexVertexScreenBuffer;
VertexScreen* pvertex = m_pvertexScreenBuffer + m_indexVertexScreenBuffer;
float rhw = 1.0f / vertex.m_pos.w;
pvertex->x = m_scalex * rhw * vertex.m_pos.x + m_xoffset;
pvertex->y = m_scaley * rhw * vertex.m_pos.y + m_yoffset;
pvertex->z = rhw * vertex.m_pos.z;
pvertex->qw = rhw;
pvertex->u = vertex.m_pointTexture.X();
pvertex->v = vertex.m_pointTexture.Y();
pvertex->color = MakeD3DCOLOR(vertex.m_color);
pvertex->specular = 0;
ClampVertex(*pvertex);
m_indexVertexScreenBuffer++;
return vertex.m_index;
}
MeshIndex TranslateIndex(VertexTL& vertex)
{
if (vertex.m_index == 0xffff) {
return ConvertVertex(vertex);
}
return vertex.m_index;
}
int TranslateIntersection(
const Plane& plane,
const VertexTL& vertex0,
const VertexTL& vertex1
) {
VertexTL vertex;
CalculateIntersection(plane, vertex0, vertex1, vertex);
return ConvertVertex(vertex);
}
void CalculateIntersection(
const Plane& plane,
const VertexTL& vertex0,
const VertexTL& vertex1,
VertexTL& vertexOut
) {
float alpha = plane.Intersect(vertex0.m_pos, vertex1.m_pos);
vertexOut.Interpolate(vertex0, vertex1, alpha);
vertexOut.m_index = 0xffff;
}
int ClipPolygonToPlane(
const Plane& plane,
Code bit,
VertexTL* pvertexIn,
int vcountIn,
VertexTL* pvertexOut
) {
int vcount = 0;
int vindexPrevious = vcountIn - 1;
Code codePrevious = pvertexIn[vindexPrevious].m_code & bit;
for (int vindex = 0; vindex < vcountIn; vindex++) {
Code code = pvertexIn[vindex].m_code & bit;
if ((code ^ codePrevious) != 0) {
CalculateIntersection(
plane,
pvertexIn[vindexPrevious],
pvertexIn[vindex],
pvertexOut[vcount]
);
pvertexOut[vcount].UpdateClipCode();
if (m_countPlanes > 6) {
Code code = ClipPlane;
for (int index = 6; index < m_countPlanes; index++, code <<= 1) {
pvertexOut[vcount].UpdateClipCode(m_pplane[index], code);
}
}
vcount++;
}
if (code == 0) {
pvertexOut[vcount] = pvertexIn[vindex];
vcount++;
}
ZAssert(vcount <= 8);
codePrevious = code;
vindexPrevious = vindex;
}
return vcount;
}
void ClipPolygonToPlanes(
const Plane* pplane,
int pcount,
Code codeOr,
const VertexTL& vertex0,
const VertexTL& vertex1,
const VertexTL& vertex2
) {
VertexTL pverticesIn[3] =
{
vertex0,
vertex1,
vertex2
};
VertexTL pverticesOut0[8];
VertexTL pverticesOut1[8];
VertexTL* pvertexIn = pverticesIn;
VertexTL* pvertexOut = pverticesOut0;
VertexTL* pvertexOther = pverticesOut1;
int vcount = 3;
Code bit = 1;
int pindex = 0;
while (pindex < pcount) {
if ((codeOr & bit) != 0) {
vcount = ClipPolygonToPlane(pplane[pindex], bit, pvertexIn, vcount, pvertexOut);
pvertexIn = pvertexOut;
pvertexOut = pvertexOther;
pvertexOther = pvertexIn;
}
bit *= 2;
pindex++;
}
MeshIndex aindex[7];
int index;
for(index = 0; index < vcount; index++) {
aindex[index] = TranslateIndex(pvertexIn[index]);
}
for(index = 1; index < vcount - 1; index++) {
StoreTriangle(
aindex[0],
aindex[index],
aindex[index + 1]
);
}
}
void ClipPolygonToPlane(
const Plane& plane,
Code code0,
Code code1,
Code code2,
VertexTL& vertex0,
VertexTL& vertex1,
VertexTL& vertex2
) {
if (code0 != 0) {
if (code1 != 0) {
StoreTriangle(
TranslateIntersection(plane, vertex2, vertex0),
TranslateIntersection(plane, vertex1, vertex2),
TranslateIndex(vertex2)
);
} else if (code2 != 0) {
StoreTriangle(
TranslateIntersection(plane, vertex0, vertex1),
TranslateIndex(vertex1),
TranslateIntersection(plane, vertex2, vertex1)
);
} else {
int index0 = TranslateIntersection(plane, vertex0, vertex1);
int index2 = TranslateIndex(vertex2);
StoreTriangle(
index0,
TranslateIndex(vertex1),
index2
);
StoreTriangle(
index0,
index2,
TranslateIntersection(plane, vertex0, vertex2)
);
}
} else {
if (code1 != 0) {
if (code2 != 0) {
StoreTriangle(
TranslateIndex(vertex0),
TranslateIntersection(plane, vertex0, vertex1),
TranslateIntersection(plane, vertex2, vertex0)
);
} else {
int index0 = TranslateIndex(vertex0);
int index2 = TranslateIntersection(plane, vertex1, vertex2);
StoreTriangle(
index0,
TranslateIntersection(plane, vertex0, vertex1),
index2
);
StoreTriangle(
index0,
index2,
TranslateIndex(vertex2)
);
}
} else {
int index0 = TranslateIndex(vertex0);
int index2 = TranslateIntersection(plane, vertex1, vertex2);
StoreTriangle(
index0,
TranslateIndex(vertex1),
index2
);
StoreTriangle(
index0,
index2,
TranslateIntersection(plane, vertex2, vertex0)
);
}
}
}
void ClipTriangles(VertexTL* pvertex, int vcountIn, const MeshIndex* pindex, int icountIn)
{
for(int index = 0; index < icountIn; index += 3) {
int index0 = pindex[index + 0];
int index1 = pindex[index + 1];
int index2 = pindex[index + 2];
Code code0 = pvertex[index0].m_code;
Code code1 = pvertex[index1].m_code;
Code code2 = pvertex[index2].m_code;
Code codeAnd = code0 & code1 & code2;
if (codeAnd == 0) {
Code codeOr = code0 | code1 | code2;
if (codeOr == 0) {
StoreTriangle(
TranslateIndex(pvertex[index0]),
TranslateIndex(pvertex[index1]),
TranslateIndex(pvertex[index2])
);
} else {
Code bit = 1;
int pindex = 0;
while (
(pindex < m_countPlanes)
&& (codeOr != bit)
) {
pindex++;
bit *= 2;
}
if (pindex < m_countPlanes) {
ClipPolygonToPlane(
m_pplane[pindex],
code0,
code1,
code2,
pvertex[index0],
pvertex[index1],
pvertex[index2]
);
} else {
ClipPolygonToPlanes(
m_pplane,
m_countPlanes,
codeOr,
pvertex[index0],
pvertex[index1],
pvertex[index2]
);
}
}
} else {
int i = 0;
}
}
}
void ClipLineToPlanes(
const Plane* pplane,
int pcount,
Code codeOr,
const VertexTL& vertex0,
const VertexTL& vertex1
) {
float t0 = 0;
float t1 = 1;
int vcount = 3;
Code bit = 1;
int pindex = 0;
while (pindex < pcount) {
if ((codeOr & bit) != 0) {
float t = pplane[pindex].Intersect(vertex0.m_pos, vertex1.m_pos);
if ((vertex0.m_code & bit) != 0) {
if (t > t0) {
t0 = t;
}
} else {
if (t < t1) {
t1 = t;
}
}
}
bit *= 2;
pindex++;
}
if (t0 < t1) {
VertexTL vertexT0; vertexT0.Interpolate(vertex0, vertex1, t0);
VertexTL vertexT1; vertexT1.Interpolate(vertex0, vertex1, t1);
StoreLine(
ConvertVertex(vertexT0),
ConvertVertex(vertexT1)
);
}
}
void ClipLines(VertexTL* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
for (int index = 0; index < icount; index += 2) {
int index0 = pindex[index + 0];
int index1 = pindex[index + 1];
Code code0 = pvertex[index0].m_code;
Code code1 = pvertex[index1].m_code;
Code codeAnd = code0 & code1;
if (codeAnd == 0) {
Code codeOr = code0 | code1;
if (codeOr == 0) {
StoreLine(
TranslateIndex(pvertex[index0]),
TranslateIndex(pvertex[index1])
);
} else {
ClipLineToPlanes(
m_pplane,
m_countPlanes,
codeOr,
pvertex[index0],
pvertex[index1]
);
}
} else {
}
}
}
void ClipPoints(VertexTL* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
for(int index = 0; index < vcount; index++) {
if (pvertex[index].m_code == 0) {
ConvertVertex(pvertex[index]);
}
}
}
void TransformDeformClip(const VertexL* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
SizeVertexTLBuffer(vcount);
Matrix mat = m_mat;
m_mat.SetIdentity();
m_bUpdateMatFull = true;
const Matrix& matFull = GetFullMatrix();
for (int index = 0; index < vcount; index++) {
Vector vecLocal = Vector(pvertex[index].x, pvertex[index].y, pvertex[index].z);
HVector hvec(
m_pdeform->Deform(
mat.Transform(
vecLocal
)
)
);
m_pvertexTLBuffer[index].m_pos = matFull.Transform(hvec);
m_pvertexTLBuffer[index].m_pointTexture = Point(pvertex[index].u, pvertex[index].v);
m_pvertexTLBuffer[index].m_color =
Color(
pvertex[index].r,
pvertex[index].g,
pvertex[index].b,
pvertex[index].a
);
m_pvertexTLBuffer[index].m_index = 0xffff;
m_pvertexTLBuffer[index].UpdateClipCode();
}
if (m_countPlanes > 6) {
for (int index = 0; index < vcount; index++) {
Code code = ClipPlane;
for (int iplane = 6; iplane < m_countPlanes; iplane++, code <<= 1) {
m_pvertexTLBuffer[index].UpdateClipCode(m_pplane[iplane], code);
}
}
}
m_indexVertexScreenBuffer = 0;
m_indexIndexBuffer = 0;
(this->*pfnClip)(m_pvertexTLBuffer, vcount, pindex, icount);
if (m_indexVertexScreenBuffer != 0) {
(this->*pfnDraw)(
m_pvertexScreenBuffer,
m_indexVertexScreenBuffer,
m_pindexBuffer,
m_indexIndexBuffer
);
}
m_mat = mat;
}
void TransformClip(const VertexL* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
SizeVertexTLBuffer(vcount);
const Matrix& mat = GetFullMatrix();
for (int index = 0; index < vcount; index++) {
HVector hvec(
pvertex[index].x,
pvertex[index].y,
pvertex[index].z,
1
);
m_pvertexTLBuffer[index].m_pos = mat.Transform(hvec);
m_pvertexTLBuffer[index].m_pointTexture = Point(pvertex[index].u, pvertex[index].v);
m_pvertexTLBuffer[index].m_color =
Color(
pvertex[index].r,
pvertex[index].g,
pvertex[index].b,
pvertex[index].a
);
m_pvertexTLBuffer[index].m_index = 0xffff;
m_pvertexTLBuffer[index].UpdateClipCode();
}
if (m_countPlanes > 6) {
for (int index = 0; index < vcount; index++) {
Code code = ClipPlane;
for (int iplane = 6; iplane < m_countPlanes; iplane++, code <<= 1) {
m_pvertexTLBuffer[index].UpdateClipCode(m_pplane[iplane], code);
}
}
}
m_indexVertexScreenBuffer = 0;
m_indexIndexBuffer = 0;
(this->*pfnClip)(m_pvertexTLBuffer, vcount, pindex, icount);
if (m_indexVertexScreenBuffer != 0) {
(this->*pfnDraw)(
m_pvertexScreenBuffer,
m_indexVertexScreenBuffer,
m_pindexBuffer,
m_indexIndexBuffer
);
}
}
#ifndef USEASM
void TransformAndLightNoClip(
const Vertex* pvertex,
int vcount,
const MeshIndex* pindex,
int icount,
PFNClip pfnClip,
PFNDraw pfnDraw
) {
SizeVertexScreenBuffer(vcount);
UpdateLighting();
const Matrix& mat = GetFullMatrix();
for (int index = 0; index < vcount; index++) {
const float x = pvertex[index].x;
const float y = pvertex[index].y;
const float z = pvertex[index].z;
const float rhw = 1.0f / (mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3]);
m_pvertexScreenBuffer[index].x = rhw * (mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3]);
m_pvertexScreenBuffer[index].y = rhw * (mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3]);
m_pvertexScreenBuffer[index].z = rhw * (mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3]);
m_pvertexScreenBuffer[index].qw = rhw;
m_pvertexScreenBuffer[index].u = pvertex[index].u;
m_pvertexScreenBuffer[index].v = pvertex[index].v;
{
float fbright =
255.0f * (
pvertex[index].nx * m_vecLight.X()
+ pvertex[index].ny * m_vecLight.Y()
+ pvertex[index].nz * m_vecLight.Z()
+ m_brightAmbient
);
int bright = MakeInt(fbrigth);
if (bright > 255) {
bright = 255;
} else if (bright < 0) {
bright = 0;
}
m_pvertexScreenBuffer[index].color = 0xff000000 | bright | (bright << 8) | (bright << 16);
}
}
(this->*pfnDraw)(m_pvertexScreenBuffer, vcount, pindex, icount);
}
#else
void TransformAndLightNoClip(
const Vertex* pvertex,
int vcount,
const MeshIndex* pindex,
int icount,
PFNClip pfnClip,
PFNDraw pfnDraw
) {
UpdateLighting();
SizeVertexScreenBuffer(vcount);
const Matrix mat = GetFullMatrix();
const Vector vecLight = m_vecLight;
const float brightAmbient = m_brightAmbient;
const float mult = 255.0f;
const float one = 1.0f;
int bright;
_asm {
mov ebx, 255
mov ecx, this
mov esi, pvertex
mov edi, [ecx].m_pvertexScreenBuffer
mov ecx, vcount
loopTop:
fld [vecLight].x fmul [esi]Vertex.nx fld [vecLight].y fmul [esi]Vertex.ny fld [vecLight].z fmul [esi]Vertex.nz fxch st(2) faddp st(1), st(0) fld one fld [mat + 48 + 0] fmul [esi]Vertex.x fxch st(3) fadd [brightAmbient] fld [mat + 48 + 4] fmul [esi]Vertex.y fxch st(1) faddp st(3), st(0) fld [mat + 48 + 8] fmul [esi]Vertex.z fxch st(1) faddp st(4), st(0) fxch st(2) fmul mult fld [mat + 0 + 0] fmul [esi]Vertex.x fxch st(3) fadd DWORD PTR [mat + 48 + 12] fxch st(1) fistp bright fld [mat + 0 + 4] fmul [esi]Vertex.y fxch st(1) faddp st(4), st(0) fld [mat + 0 + 8] fmul [esi]Vertex.z fxch st(1) faddp st(3), st(0) fxch st(3) fdivp st(1), st(0) fxch st(2) mov eax,bright
cmp eax,ebx
jle label1
mov eax,ebx
jmp label2
label1:
test eax,eax
jge label2
xor eax,eax
label2:
mov edx,eax
shl edx,8
or edx,eax
shl edx,8
or edx,eax
or edx, 0xff000000
mov [edi]VertexScreen.color, edx
mov eax, [esi]Vertex.u
mov edx, [esi]Vertex.v
mov [edi]VertexScreen.u, eax
mov [edi]VertexScreen.v, edx
fadd DWORD PTR [mat + 0 + 12] fld [mat + 16 + 0] fmul [esi]Vertex.x fld [mat + 16 + 4] fmul [esi]Vertex.y fld [mat + 16 + 8] fmul [esi]Vertex.z fxch st(1) faddp st(2), st(0) fld [mat + 32 + 0] fmul [esi]Vertex.x fld [mat + 32 + 4] fmul [esi]Vertex.y fld [mat + 32 + 8] fmul [esi]Vertex.z fxch st(3) fadd DWORD PTR [mat + 16 + 12] fxch st(1) faddp st(2), st(0) fxch st(2) fadd DWORD PTR [mat + 32 + 12] fxch st(4) faddp st(5), st(0) fxch st(1) faddp st(2), st(0) faddp st(2), st(0) fxch st(2) fmul st(0), st(3) fxch st(2) fmul st(0), st(3) fxch st(1) fmul st(0), st(3) fxch st(3) fstp [edi]VertexScreen.qw fxch st(1) fstp [edi]VertexScreen.x fstp [edi]VertexScreen.y fstp [edi]VertexScreen.z add edi, SIZE VertexScreen
add esi, SIZE Vertex
dec ecx
jne loopTop
}
(this->*pfnDraw)(m_pvertexScreenBuffer, vcount, pindex, icount);
}
#endif
void TransformNoClip(const VertexL* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
SizeVertexScreenBuffer(vcount);
const Matrix& mat = GetFullMatrix();
for (int index = 0; index < vcount; index++) {
const float x = pvertex[index].x;
const float y = pvertex[index].y;
const float z = pvertex[index].z;
const float rhw = 1.0f / (mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3]);
m_pvertexScreenBuffer[index].x = rhw * (mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3]);
m_pvertexScreenBuffer[index].y = rhw * (mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3]);
m_pvertexScreenBuffer[index].z = rhw * (mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3]);
m_pvertexScreenBuffer[index].qw = rhw;
m_pvertexScreenBuffer[index].u = pvertex[index].u;
m_pvertexScreenBuffer[index].v = pvertex[index].v;
m_pvertexScreenBuffer[index].color =
MakeD3DCOLOR(
Color(
pvertex[index].r,
pvertex[index].g,
pvertex[index].b,
pvertex[index].a
)
);
}
(this->*pfnDraw)(m_pvertexScreenBuffer, vcount, pindex, icount);
}
void TransformNoClipNoLight(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
SizeVertexScreenBuffer(vcount);
const Matrix& mat = GetFullMatrix();
for (int index = 0; index < vcount; index++) {
const float x = pvertex[index].x;
const float y = pvertex[index].y;
const float z = pvertex[index].z;
const float rhw = 1.0f / (mat[3][0] * x + mat[3][1] * y + mat[3][2] * z + mat[3][3]);
m_pvertexScreenBuffer[index].x = rhw * (mat[0][0] * x + mat[0][1] * y + mat[0][2] * z + mat[0][3]);
m_pvertexScreenBuffer[index].y = rhw * (mat[1][0] * x + mat[1][1] * y + mat[1][2] * z + mat[1][3]);
m_pvertexScreenBuffer[index].z = rhw * (mat[2][0] * x + mat[2][1] * y + mat[2][2] * z + mat[2][3]);
m_pvertexScreenBuffer[index].qw = rhw;
m_pvertexScreenBuffer[index].u = pvertex[index].u;
m_pvertexScreenBuffer[index].v = pvertex[index].v;
}
(this->*pfnDraw)(m_pvertexScreenBuffer, vcount, pindex, icount);
}
void LightVertexCopy(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
SizeVertexLBuffer(vcount);
for (int index = 0; index < vcount; index++) {
m_pvertexLBuffer[index].x = pvertex[index].x;
m_pvertexLBuffer[index].y = pvertex[index].y;
m_pvertexLBuffer[index].z = pvertex[index].z;
m_pvertexLBuffer[index].u = pvertex[index].u;
m_pvertexLBuffer[index].v = pvertex[index].v;
m_pvertexLBuffer[index].r = 1;
m_pvertexLBuffer[index].g = 1;
m_pvertexLBuffer[index].b = 1;
m_pvertexLBuffer[index].a = 1;
}
(this->*m_pfnTransform)(m_pvertexLBuffer, vcount, pindex, icount, pfnClip, pfnDraw);
}
void LightVertexGlobalColor(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
SizeVertexLBuffer(vcount);
float r = m_colorGlobal.R();
float g = m_colorGlobal.G();
float b = m_colorGlobal.B();
float a = m_colorGlobal.A();
for (int index = 0; index < vcount; index++) {
m_pvertexLBuffer[index].x = pvertex[index].x;
m_pvertexLBuffer[index].y = pvertex[index].y;
m_pvertexLBuffer[index].z = pvertex[index].z;
m_pvertexLBuffer[index].u = pvertex[index].u;
m_pvertexLBuffer[index].v = pvertex[index].v;
m_pvertexLBuffer[index].r = r;
m_pvertexLBuffer[index].g = g;
m_pvertexLBuffer[index].b = b;
m_pvertexLBuffer[index].a = a;
}
(this->*m_pfnTransform)(m_pvertexLBuffer, vcount, pindex, icount, pfnClip, pfnDraw);
}
float Saturate(float value)
{
if (value > 1) {
return 1;
} else if (value < 0) {
return 0;
}
return value;
}
void BidirectionalLightVertex(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
UpdateLighting();
SizeVertexLBuffer(vcount);
for (int index = 0; index < vcount; index++) {
m_pvertexLBuffer[index].x = pvertex[index].x;
m_pvertexLBuffer[index].y = pvertex[index].y;
m_pvertexLBuffer[index].z = pvertex[index].z;
m_pvertexLBuffer[index].u = pvertex[index].u;
m_pvertexLBuffer[index].v = pvertex[index].v;
float bright =
pvertex[index].nx * m_vecLight.X()
+ pvertex[index].ny * m_vecLight.Y()
+ pvertex[index].nz * m_vecLight.Z();
if (bright >= 0) {
m_pvertexLBuffer[index].r = Saturate(bright * m_color.R() + m_brightAmbient);
m_pvertexLBuffer[index].g = Saturate(bright * m_color.G() + m_brightAmbient);
m_pvertexLBuffer[index].b = Saturate(bright * m_color.B() + m_brightAmbient);
} else {
bright = - bright;
m_pvertexLBuffer[index].r = Saturate(bright * m_colorAlt.R() + m_brightAmbient);
m_pvertexLBuffer[index].g = Saturate(bright * m_colorAlt.G() + m_brightAmbient);
m_pvertexLBuffer[index].b = Saturate(bright * m_colorAlt.B() + m_brightAmbient);
}
m_pvertexLBuffer[index].a = 1;
}
(this->*m_pfnTransform)(m_pvertexLBuffer, vcount, pindex, icount, pfnClip, pfnDraw);
}
void LightVertex(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
UpdateLighting();
SizeVertexLBuffer(vcount);
for (int index = 0; index < vcount; index++) {
m_pvertexLBuffer[index].x = pvertex[index].x;
m_pvertexLBuffer[index].y = pvertex[index].y;
m_pvertexLBuffer[index].z = pvertex[index].z;
m_pvertexLBuffer[index].u = pvertex[index].u;
m_pvertexLBuffer[index].v = pvertex[index].v;
float bright =
pvertex[index].nx * m_vecLight.X()
+ pvertex[index].ny * m_vecLight.Y()
+ pvertex[index].nz * m_vecLight.Z()
+ m_brightAmbient;
if (bright > 1) {
bright = 1;
} else if (bright < 0) {
bright = 0;
}
m_pvertexLBuffer[index].r = bright;
m_pvertexLBuffer[index].g = bright;
m_pvertexLBuffer[index].b = bright;
m_pvertexLBuffer[index].a = 1;
}
(this->*m_pfnTransform)(m_pvertexLBuffer, vcount, pindex, icount, pfnClip, pfnDraw);
}
void MaterialLightVertex(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount, PFNClip pfnClip, PFNDraw pfnDraw)
{
UpdateLighting();
SizeVertexLBuffer(vcount);
float r = m_pmaterial->GetDiffuse().GetRed();
float g = m_pmaterial->GetDiffuse().GetGreen();
float b = m_pmaterial->GetDiffuse().GetBlue();
float a = m_pmaterial->GetDiffuse().GetAlpha();
for (int index = 0; index < vcount; index++) {
m_pvertexLBuffer[index].x = pvertex[index].x;
m_pvertexLBuffer[index].y = pvertex[index].y;
m_pvertexLBuffer[index].z = pvertex[index].z;
m_pvertexLBuffer[index].u = pvertex[index].u;
m_pvertexLBuffer[index].v = pvertex[index].v;
float bright =
pvertex[index].nx * m_vecLight.X()
+ pvertex[index].ny * m_vecLight.Y()
+ pvertex[index].nz * m_vecLight.Z()
+ m_brightAmbient;
if (bright > 1) {
bright = 1;
} else if (bright < 0) {
bright = 0;
}
m_pvertexLBuffer[index].r = r * bright;
m_pvertexLBuffer[index].g = g * bright;
m_pvertexLBuffer[index].b = b * bright;
m_pvertexLBuffer[index].a = a;
}
(this->*m_pfnTransform)(m_pvertexLBuffer, vcount, pindex, icount, pfnClip, pfnDraw);
}
void StoreVertex(
VertexScreen& pvertex,
float x,
float y,
float z,
float qw,
D3DCOLOR color,
float u,
float v
) {
pvertex.x = x;
pvertex.y = y;
pvertex.z = z;
pvertex.qw = qw;
pvertex.color = color;
pvertex.specular = 0;
pvertex.u = u;
pvertex.v = v;
}
void DrawLinesWithPolygons(const VertexScreen* pvertexInArg, int vcount, const MeshIndex* pindexInArg, int icount)
{
bool bUsingVertexBuffer = (pvertexInArg == m_pvertexScreenBuffer);
bool bUsingIndexBuffer = (pindexInArg == m_pindexBuffer );
SizeIndexBuffer(icount + icount * 3);
VertexScreen* pvertexOut = GetVertexScreenBuffer(vcount + icount * 2) + vcount;
MeshIndex* pindexOut = m_pindexBuffer + icount;
const VertexScreen* pvertexIn = bUsingVertexBuffer ? m_pvertexScreenBuffer : pvertexInArg;
const MeshIndex* pindexIn = bUsingIndexBuffer ? m_pindexBuffer : pindexInArg ;
Vector vecUp(0, 0, 1);
VertexScreen* pvertex = pvertexOut;
MeshIndex* pindex = pindexOut;
int indexOut = 0;
for (int index = 0; index < icount; index += 2) {
const VertexScreen& vertex1 = pvertexIn[pindexIn[index ]];
const VertexScreen& vertex2 = pvertexIn[pindexIn[index + 1]];
if (
vertex1.x != vertex2.x
|| vertex1.y != vertex2.y
) {
Vector vecForward(vertex2.x - vertex1.x, vertex2.y - vertex1.y, 0);
Vector vecLeft = CrossProduct(vecUp, vecForward);
vecLeft = vecLeft.Normalize() * m_lineWidth;
pvertex[0] = vertex1;
pvertex[0].x = vertex1.x + vecLeft.X(); pvertex[0].y = vertex1.y + vecLeft.Y(); pvertex[0].z = vertex1.z;
pvertex[0].qw = vertex1.qw;
pvertex[0].u = vertex1.u;
pvertex[0].v = 0;
pvertex[0].color = vertex1.color;
pvertex[0].specular = vertex1.specular;
pvertex[1] = vertex1;
pvertex[1].x = vertex1.x - vecLeft.X(); pvertex[1].y = vertex1.y - vecLeft.Y(); pvertex[1].z = vertex1.z;
pvertex[1].qw = vertex1.qw;
pvertex[1].u = vertex1.u;
pvertex[1].v = 1;
pvertex[1].color = vertex1.color;
pvertex[1].specular = vertex1.specular;
pvertex[2] = vertex2;
pvertex[2].x = vertex2.x + vecLeft.X(); pvertex[2].y = vertex2.y + vecLeft.Y(); pvertex[2].z = vertex2.z;
pvertex[2].qw = vertex2.qw;
pvertex[2].u = vertex2.u;
pvertex[2].v = 0;
pvertex[2].color = vertex2.color;
pvertex[2].specular = vertex2.specular;
pvertex[3] = vertex2;
pvertex[3].x = vertex2.x - vecLeft.X(); pvertex[3].y = vertex2.y - vecLeft.Y(); pvertex[3].z = vertex2.z;
pvertex[3].qw = vertex2.qw;
pvertex[3].u = vertex2.u;
pvertex[3].v = 1;
pvertex[3].color = vertex2.color;
pvertex[3].specular = vertex2.specular;
pvertex += 4;
pindex[0] = indexOut + 0;
pindex[1] = indexOut + 1;
pindex[2] = indexOut + 2;
pindex[3] = indexOut + 1;
pindex[4] = indexOut + 3;
pindex[5] = indexOut + 2;
pindex += 6;
indexOut += 4;
}
}
#ifdef EnablePerformanceCounters
m_countTriangles += icount;
#endif
m_prasterizer->DrawTriangles(pvertexOut, pvertex - pvertexOut, pindexOut, pindex - pindexOut);
}
void DrawLinesRasterizer(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
m_prasterizer->DrawLines(pvertex, vcount, pindex, icount);
}
void DrawTriangles(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
m_prasterizer->DrawTriangles(pvertex, vcount, pindex, icount);
}
void DrawLines(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
UpdatePointers();
(this->*m_pfnDrawLines)(pvertex, vcount, pindex, icount);
}
void DrawPoints(const VertexScreen* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
m_prasterizer->DrawPoints(pvertex, vcount);
}
void DrawPoints(const VertexScreen* pvertex, int vcount)
{
m_prasterizer->DrawPoints(pvertex, vcount);
}
void DrawTriangles(const D3DVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
ZAssert(false);
}
void DrawLines(const D3DVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
ZAssert(false);
}
void DrawPoints(const D3DVertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
ZAssert(false);
}
void DrawPoints(const D3DVertex* pvertex, int vcount)
{
ZAssert(false);
}
void DrawTriangles(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
#ifdef EnablePerformanceCounters
m_countTriangles += icount / 3;
#endif
UpdatePointers();
(this->*m_pfnLightVertex)(pvertex, vcount, pindex, icount, &Device3D::ClipTriangles, &Device3D::DrawTriangles);
}
void DrawLines(const Vertex* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
#ifdef EnablePerformanceCounters
m_countLines += icount - 1;
#endif
UpdatePointers();
(this->*m_pfnLightVertex)(pvertex, vcount, pindex, icount, &Device3D::ClipLines, m_pfnDrawLines);
}
void DrawPoints(const Vertex* pvertex, int vcount)
{
#ifdef EnablePerformanceCounters
m_countPoints += vcount;
#endif
UpdatePointers();
(this->*m_pfnLightVertex)(pvertex, vcount, NULL, 0, &Device3D::ClipPoints, &Device3D::DrawPoints);
}
void DrawTriangles(const VertexL* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
#ifdef EnablePerformanceCounters
m_countTriangles += icount / 3;
#endif
UpdatePointers();
(this->*m_pfnLightVertexL)(pvertex, vcount, pindex, icount, &Device3D::ClipTriangles, &Device3D::DrawTriangles);
}
void DrawLines(const VertexL* pvertex, int vcount, const MeshIndex* pindex, int icount)
{
#ifdef EnablePerformanceCounters
m_countLines += icount - 1;
#endif
UpdatePointers();
(this->*m_pfnLightVertexL)(pvertex, vcount, pindex, icount, &Device3D::ClipLines, m_pfnDrawLines);
}
void DrawPoints(const VertexL* pvertex, int vcount)
{
#ifdef EnablePerformanceCounters
m_countPoints += vcount;
#endif
UpdatePointers();
(this->*m_pfnLightVertexL)(pvertex, vcount, NULL, 0, &Device3D::ClipPoints, &Device3D::DrawPoints);
}
};
TRef<IDevice3D> CreateDevice3D(Rasterizer* prasterizer)
{
return new Device3D(prasterizer);
}