1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "IrrCompileConfig.h"
\r
6 #include "CTRTextureGouraud.h"
\r
8 #ifdef _IRR_COMPILE_WITH_SOFTWARE_
\r
15 class CTRTextureFlat : public CTRTextureGouraud
\r
19 CTRTextureFlat(IZBuffer* zbuffer)
\r
20 : CTRTextureGouraud(zbuffer)
\r
23 setDebugName("CTRTextureFlat");
\r
27 //! draws an indexed triangle list
\r
28 virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) _IRR_OVERRIDE_
\r
30 const S2DVertex *v1, *v2, *v3;
\r
32 f32 tmpDiv; // temporary division factor
\r
33 f32 longest; // saves the longest span
\r
34 s32 height; // saves height of triangle
\r
35 u16* targetSurface; // target pointer where to plot pixels
\r
36 s32 spanEnd; // saves end of spans
\r
37 f32 leftdeltaxf; // amount of pixels to increase on left side of triangle
\r
38 f32 rightdeltaxf; // amount of pixels to increase on right side of triangle
\r
39 s32 leftx, rightx; // position where we are
\r
40 f32 leftxf, rightxf; // same as above, but as f32 values
\r
41 s32 span; // current span
\r
42 u16 *hSpanBegin, *hSpanEnd; // pointer used when plotting pixels
\r
43 s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values
\r
44 s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values
\r
45 s32 spanTx, spanTy, spanTxStep, spanTyStep; // values of Texturecoords when drawing a span
\r
46 core::rect<s32> TriangleRect;
\r
48 s32 leftZValue, rightZValue;
\r
49 s32 leftZStep, rightZStep;
\r
50 s32 spanZValue, spanZStep; // ZValues when drawing a span
\r
51 TZBufferType* zTarget, *spanZTarget; // target of ZBuffer;
\r
53 lockedSurface = (u16*)RenderTarget->getData();
\r
54 lockedZBuffer = ZBuffer->lock();
\r
55 lockedTexture = (u16*)Texture->getData();
\r
57 for (s32 i=0; i<triangleCount; ++i)
\r
59 v1 = &vertices[*indexList];
\r
61 v2 = &vertices[*indexList];
\r
63 v3 = &vertices[*indexList];
\r
66 // back face culling
\r
68 if (BackFaceCullingEnabled)
\r
70 s32 z = ((v3->Pos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) -
\r
71 ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X));
\r
77 //near plane clipping
\r
79 if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0)
\r
82 // sort for width for inscreen clipping
\r
84 if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2);
\r
85 if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3);
\r
86 if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3);
\r
88 if ((v1->Pos.X - v3->Pos.X) == 0)
\r
91 TriangleRect.UpperLeftCorner.X = v1->Pos.X;
\r
92 TriangleRect.LowerRightCorner.X = v3->Pos.X;
\r
94 // sort for height for faster drawing.
\r
96 if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2);
\r
97 if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3);
\r
98 if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3);
\r
100 TriangleRect.UpperLeftCorner.Y = v1->Pos.Y;
\r
101 TriangleRect.LowerRightCorner.Y = v3->Pos.Y;
\r
103 if (!TriangleRect.isRectCollided(ViewPortRect))
\r
106 // calculate height of triangle
\r
107 height = v3->Pos.Y - v1->Pos.Y;
\r
111 // calculate longest span
\r
113 longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X);
\r
115 spanEnd = v2->Pos.Y;
\r
117 leftxf = (f32)v1->Pos.X;
\r
118 rightxf = (f32)v1->Pos.X;
\r
120 leftZValue = v1->ZValue;
\r
121 rightZValue = v1->ZValue;
\r
123 leftTx = rightTx = v1->TCoords.X;
\r
124 leftTy = rightTy = v1->TCoords.Y;
\r
126 targetSurface = lockedSurface + span * SurfaceWidth;
\r
127 zTarget = lockedZBuffer + span * SurfaceWidth;
\r
129 if (longest < 0.0f)
\r
131 tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y);
\r
132 rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv;
\r
133 rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv);
\r
134 rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv);
\r
135 rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv);
\r
137 tmpDiv = 1.0f / (f32)height;
\r
138 leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv;
\r
139 leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv);
\r
140 leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv);
\r
141 leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv);
\r
145 tmpDiv = 1.0f / (f32)height;
\r
146 rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv;
\r
147 rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv);
\r
148 rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv);
\r
149 rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv);
\r
151 tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y);
\r
152 leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv;
\r
153 leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv);
\r
154 leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv);
\r
155 leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv);
\r
159 // do it twice, once for the first half of the triangle,
\r
160 // end then for the second half.
\r
162 for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf)
\r
164 if (spanEnd > ViewPortRect.LowerRightCorner.Y)
\r
165 spanEnd = ViewPortRect.LowerRightCorner.Y;
\r
167 // if the span <0, than we can skip these spans,
\r
168 // and proceed to the next spans which are really on the screen.
\r
169 if (span < ViewPortRect.UpperLeftCorner.Y)
\r
171 // we'll use leftx as temp variable
\r
172 if (spanEnd < ViewPortRect.UpperLeftCorner.Y)
\r
174 leftx = spanEnd - span;
\r
179 leftx = ViewPortRect.UpperLeftCorner.Y - span;
\r
180 span = ViewPortRect.UpperLeftCorner.Y;
\r
183 leftxf += leftdeltaxf*leftx;
\r
184 rightxf += rightdeltaxf*leftx;
\r
185 targetSurface += SurfaceWidth*leftx;
\r
186 zTarget += SurfaceWidth*leftx;
\r
187 leftZValue += leftZStep*leftx;
\r
188 rightZValue += rightZStep*leftx;
\r
190 leftTx += leftTxStep*leftx;
\r
191 leftTy += leftTyStep*leftx;
\r
192 rightTx += rightTxStep*leftx;
\r
193 rightTy += rightTyStep*leftx;
\r
197 // the main loop. Go through every span and draw it.
\r
199 while (span < spanEnd)
\r
201 leftx = (s32)(leftxf);
\r
202 rightx = (s32)(rightxf + 0.5f);
\r
204 // perform some clipping
\r
206 // TODO: clipping is not correct when leftx is clipped.
\r
208 if (leftx<ViewPortRect.UpperLeftCorner.X)
\r
209 leftx = ViewPortRect.UpperLeftCorner.X;
\r
211 if (leftx>ViewPortRect.LowerRightCorner.X)
\r
212 leftx = ViewPortRect.LowerRightCorner.X;
\r
214 if (rightx<ViewPortRect.UpperLeftCorner.X)
\r
215 rightx = ViewPortRect.UpperLeftCorner.X;
\r
217 if (rightx>ViewPortRect.LowerRightCorner.X)
\r
218 rightx = ViewPortRect.LowerRightCorner.X;
\r
222 if (rightx - leftx != 0)
\r
224 tmpDiv = 1.0f / (rightx - leftx);
\r
225 spanZValue = leftZValue;
\r
226 spanZStep = (s32)((rightZValue - leftZValue) * tmpDiv);
\r
228 hSpanBegin = targetSurface + leftx;
\r
229 spanZTarget = zTarget + leftx;
\r
230 hSpanEnd = targetSurface + rightx;
\r
234 spanTxStep = (s32)((rightTx - leftTx) * tmpDiv);
\r
235 spanTyStep = (s32)((rightTy - leftTy) * tmpDiv);
\r
237 while (hSpanBegin < hSpanEnd)
\r
239 if (spanZValue > *spanZTarget)
\r
241 *spanZTarget = spanZValue;
\r
242 *hSpanBegin = lockedTexture[((spanTy>>8)&textureYMask) * lockedTextureWidth + ((spanTx>>8)&textureXMask)];
\r
245 spanTx += spanTxStep;
\r
246 spanTy += spanTyStep;
\r
248 spanZValue += spanZStep;
\r
254 leftxf += leftdeltaxf;
\r
255 rightxf += rightdeltaxf;
\r
257 targetSurface += SurfaceWidth;
\r
258 zTarget += SurfaceWidth;
\r
259 leftZValue += leftZStep;
\r
260 rightZValue += rightZStep;
\r
262 leftTx += leftTxStep;
\r
263 leftTy += leftTyStep;
\r
264 rightTx += rightTxStep;
\r
265 rightTy += rightTyStep;
\r
268 if (triangleHalf>0) // break, we've gout only two halves
\r
272 // setup variables for second half of the triangle.
\r
274 if (longest < 0.0f)
\r
276 tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);
\r
278 rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;
\r
279 rightxf = (f32)v2->Pos.X;
\r
281 rightZValue = v2->ZValue;
\r
282 rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);
\r
284 rightTx = v2->TCoords.X;
\r
285 rightTy = v2->TCoords.Y;
\r
286 rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv);
\r
287 rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv);
\r
291 tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);
\r
293 leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;
\r
294 leftxf = (f32)v2->Pos.X;
\r
296 leftZValue = v2->ZValue;
\r
297 leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);
\r
299 leftTx = v2->TCoords.X;
\r
300 leftTy = v2->TCoords.Y;
\r
301 leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv);
\r
302 leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv);
\r
306 spanEnd = v3->Pos.Y;
\r
315 } // end namespace video
\r
316 } // end namespace irr
\r
318 #endif // _IRR_COMPILE_WITH_SOFTWARE_
\r
325 //! creates a flat triangle renderer
\r
326 ITriangleRenderer* createTriangleRendererTextureFlat(IZBuffer* zbuffer)
\r
328 #ifdef _IRR_COMPILE_WITH_SOFTWARE_
\r
329 return new CTRTextureFlat(zbuffer);
\r
332 #endif // _IRR_COMPILE_WITH_SOFTWARE_
\r
335 } // end namespace video
\r
336 } // end namespace irr
\r