irrlicht/source/Irrlicht/CTRFlatWire.cpp
cutealien ffd7b63af0 API BREAKER: Replacing defines in irrTypes.h which are conflicting with c++ reserved identifier rules.
C++ has undefined behavior for identifiers starting with __ or with _ followed by an uppercase letter.
We still have many more (in IrrCompileConfig.h and in all header-guards), will likely replace those later as well.
As a workaround for users which might use irrlicht defines in their code, I've added the header irrLegacyDefines.h
Including that allows to continue using old defines for a while - or make it easier to have code which compiles 
with old and new Irrlicht library versions.


git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6251 dfc29bdd-3216-0410-991c-e03cc46cb475
2021-08-27 12:55:10 +00:00

281 lines
7.0 KiB
C++

// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "IrrCompileConfig.h"
#include "CTRTextureGouraud.h"
#ifdef _IRR_COMPILE_WITH_SOFTWARE_
namespace irr
{
namespace video
{
class CTRFlatWire : public CTRTextureGouraud
{
public:
CTRFlatWire(IZBuffer* zbuffer)
: CTRTextureGouraud(zbuffer)
{
#ifdef _DEBUG
setDebugName("CTRWire");
#endif
}
//! draws an indexed triangle list
virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) IRR_OVERRIDE
{
const S2DVertex *v1, *v2, *v3;
u16 color;
f32 tmpDiv; // temporary division factor
f32 longest; // saves the longest span
s32 height; // saves height of triangle
u16* targetSurface; // target pointer where to plot pixels
s32 spanEnd; // saves end of spans
f32 leftdeltaxf; // amount of pixels to increase on left side of triangle
f32 rightdeltaxf; // amount of pixels to increase on right side of triangle
s32 leftx, rightx; // position where we are
f32 leftxf, rightxf; // same as above, but as f32 values
s32 span; // current span
core::rect<s32> TriangleRect;
s32 leftZValue, rightZValue;
s32 leftZStep, rightZStep;
TZBufferType* zTarget; // target of ZBuffer;
lockedSurface = (u16*)RenderTarget->getData();
lockedZBuffer = ZBuffer->lock();
for (s32 i=0; i<triangleCount; ++i)
{
v1 = &vertices[*indexList];
++indexList;
v2 = &vertices[*indexList];
++indexList;
v3 = &vertices[*indexList];
++indexList;
// back face culling
if (BackFaceCullingEnabled)
{
s32 z = ((v3->Pos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) -
((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X));
if (z < 0)
continue;
}
//near plane clipping
if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0)
continue;
// sort for width for inscreen clipping
if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2);
if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3);
if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3);
if ((v1->Pos.X - v3->Pos.X) == 0)
continue;
TriangleRect.UpperLeftCorner.X = v1->Pos.X;
TriangleRect.LowerRightCorner.X = v3->Pos.X;
// sort for height for faster drawing.
if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2);
if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3);
if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3);
TriangleRect.UpperLeftCorner.Y = v1->Pos.Y;
TriangleRect.LowerRightCorner.Y = v3->Pos.Y;
if (!TriangleRect.isRectCollided(ViewPortRect))
continue;
// calculate height of triangle
height = v3->Pos.Y - v1->Pos.Y;
if (!height)
continue;
// calculate longest span
longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X);
spanEnd = v2->Pos.Y;
span = v1->Pos.Y;
leftxf = (f32)v1->Pos.X;
rightxf = (f32)v1->Pos.X;
leftZValue = v1->ZValue;
rightZValue = v1->ZValue;
color = v1->Color;
targetSurface = lockedSurface + span * SurfaceWidth;
zTarget = lockedZBuffer + span * SurfaceWidth;
if (longest < 0.0f)
{
tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y);
rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv;
rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv);
tmpDiv = 1.0f / (f32)height;
leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv;
leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv);
}
else
{
tmpDiv = 1.0f / (f32)height;
rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv;
rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv);
tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y);
leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv;
leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv);
}
// do it twice, once for the first half of the triangle,
// end then for the second half.
for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf)
{
if (spanEnd > ViewPortRect.LowerRightCorner.Y)
spanEnd = ViewPortRect.LowerRightCorner.Y;
// if the span <0, than we can skip these spans,
// and proceed to the next spans which are really on the screen.
if (span < ViewPortRect.UpperLeftCorner.Y)
{
// we'll use leftx as temp variable
if (spanEnd < ViewPortRect.UpperLeftCorner.Y)
{
leftx = spanEnd - span;
span = spanEnd;
}
else
{
leftx = ViewPortRect.UpperLeftCorner.Y - span;
span = ViewPortRect.UpperLeftCorner.Y;
}
leftxf += leftdeltaxf*leftx;
rightxf += rightdeltaxf*leftx;
targetSurface += SurfaceWidth*leftx;
zTarget += SurfaceWidth*leftx;
leftZValue += leftZStep*leftx;
rightZValue += rightZStep*leftx;
}
// the main loop. Go through every span and draw it.
while (span < spanEnd)
{
leftx = (s32)(leftxf);
rightx = (s32)(rightxf + 0.5f);
// perform some clipping
if (leftx>=ViewPortRect.UpperLeftCorner.X &&
leftx<=ViewPortRect.LowerRightCorner.X)
{
if (leftZValue > *(zTarget + leftx))
{
*(zTarget + leftx) = leftZValue;
*(targetSurface + leftx) = color;
}
}
if (rightx>=ViewPortRect.UpperLeftCorner.X &&
rightx<=ViewPortRect.LowerRightCorner.X)
{
if (rightZValue > *(zTarget + rightx))
{
*(zTarget + rightx) = rightZValue;
*(targetSurface + rightx) = color;
}
}
// draw the span
leftxf += leftdeltaxf;
rightxf += rightdeltaxf;
++span;
targetSurface += SurfaceWidth;
zTarget += SurfaceWidth;
leftZValue += leftZStep;
rightZValue += rightZStep;
}
if (triangleHalf>0) // break, we've gout only two halves
break;
// setup variables for second half of the triangle.
if (longest < 0.0f)
{
tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);
rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;
rightxf = (f32)v2->Pos.X;
rightZValue = v2->ZValue;
rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);
}
else
{
tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);
leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;
leftxf = (f32)v2->Pos.X;
leftZValue = v2->ZValue;
leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);
}
spanEnd = v3->Pos.Y;
}
}
ZBuffer->unlock();
}
};
} // end namespace video
} // end namespace irr
#endif // _IRR_COMPILE_WITH_SOFTWARE_
namespace irr
{
namespace video
{
//! creates a flat triangle renderer
ITriangleRenderer* createTriangleRendererFlatWire(IZBuffer* zbuffer)
{
#ifdef _IRR_COMPILE_WITH_SOFTWARE_
return new CTRFlatWire(zbuffer);
#else
return 0;
#endif // _IRR_COMPILE_WITH_SOFTWARE_
}
} // end namespace video
} // end namespace irr