1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
2
// This file is part of the "Irrlicht Engine".
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
5
#include "IrrCompileConfig.h"
6
#include "CTRTextureGouraud.h"
8
#ifdef _IRR_COMPILE_WITH_SOFTWARE_
15
class CTRTextureGouraudWire : public CTRTextureGouraud
19
CTRTextureGouraudWire(IZBuffer* zbuffer)
20
: CTRTextureGouraud(zbuffer)
23
setDebugName("CTRGouraudWire");
27
//! draws an indexed triangle list
28
virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount)
30
const S2DVertex *v1, *v2, *v3;
33
f32 tmpDiv; // temporary division factor
34
f32 longest; // saves the longest span
35
s32 height; // saves height of triangle
36
u16* targetSurface; // target pointer where to plot pixels
37
s32 spanEnd; // saves end of spans
38
f32 leftdeltaxf; // amount of pixels to increase on left side of triangle
39
f32 rightdeltaxf; // amount of pixels to increase on right side of triangle
40
s32 leftx, rightx; // position where we are
41
f32 leftxf, rightxf; // same as above, but as f32 values
42
s32 span; // current span
43
s32 leftR, leftG, leftB, rightR, rightG, rightB; // color values
44
s32 leftStepR, leftStepG, leftStepB,
45
rightStepR, rightStepG, rightStepB; // color steps
46
s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values
47
s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values
48
core::rect<s32> TriangleRect;
50
s32 leftZValue, rightZValue;
51
s32 leftZStep, rightZStep;
52
TZBufferType* zTarget;//, *spanZTarget; // target of ZBuffer;
54
lockedSurface = (u16*)RenderTarget->lock();
55
lockedZBuffer = ZBuffer->lock();
56
lockedTexture = (u16*)Texture->lock();
58
for (s32 i=0; i<triangleCount; ++i)
60
v1 = &vertices[*indexList];
62
v2 = &vertices[*indexList];
64
v3 = &vertices[*indexList];
69
if (BackFaceCullingEnabled)
71
s32 z = ((v3->Pos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) -
72
((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X));
80
if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0)
83
// sort for width for inscreen clipping
85
if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2);
86
if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3);
87
if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3);
89
if ((v1->Pos.X - v3->Pos.X) == 0)
92
TriangleRect.UpperLeftCorner.X = v1->Pos.X;
93
TriangleRect.LowerRightCorner.X = v3->Pos.X;
95
// sort for height for faster drawing.
97
if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2);
98
if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3);
99
if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3);
101
TriangleRect.UpperLeftCorner.Y = v1->Pos.Y;
102
TriangleRect.LowerRightCorner.Y = v3->Pos.Y;
104
if (!TriangleRect.isRectCollided(ViewPortRect))
107
// calculate height of triangle
108
height = v3->Pos.Y - v1->Pos.Y;
112
// calculate longest span
114
longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X);
118
leftxf = (f32)v1->Pos.X;
119
rightxf = (f32)v1->Pos.X;
121
leftZValue = v1->ZValue;
122
rightZValue = v1->ZValue;
124
leftR = rightR = video::getRed(v1->Color)<<8;
125
leftG = rightG = video::getGreen(v1->Color)<<8;
126
leftB = rightB = video::getBlue(v1->Color)<<8;
127
leftTx = rightTx = v1->TCoords.X;
128
leftTy = rightTy = v1->TCoords.Y;
130
targetSurface = lockedSurface + span * SurfaceWidth;
131
zTarget = lockedZBuffer + span * SurfaceWidth;
135
tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y);
136
rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv;
137
rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv);
138
rightStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - rightR) * tmpDiv);
139
rightStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - rightG) * tmpDiv);
140
rightStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - rightB) * tmpDiv);
141
rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv);
142
rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv);
144
tmpDiv = 1.0f / (f32)height;
145
leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv;
146
leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv);
147
leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv);
148
leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv);
149
leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv);
150
leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv);
151
leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv);
155
tmpDiv = 1.0f / (f32)height;
156
rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv;
157
rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv);
158
rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv);
159
rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv);
160
rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv);
161
rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv);
162
rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv);
164
tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y);
165
leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv;
166
leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv);
167
leftStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - leftR) * tmpDiv);
168
leftStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - leftG) * tmpDiv);
169
leftStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - leftB) * tmpDiv);
170
leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv);
171
leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv);
175
// do it twice, once for the first half of the triangle,
176
// end then for the second half.
178
for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf)
180
if (spanEnd > ViewPortRect.LowerRightCorner.Y)
181
spanEnd = ViewPortRect.LowerRightCorner.Y;
183
// if the span <0, than we can skip these spans,
184
// and proceed to the next spans which are really on the screen.
185
if (span < ViewPortRect.UpperLeftCorner.Y)
187
// we'll use leftx as temp variable
188
if (spanEnd < ViewPortRect.UpperLeftCorner.Y)
190
leftx = spanEnd - span;
195
leftx = ViewPortRect.UpperLeftCorner.Y - span;
196
span = ViewPortRect.UpperLeftCorner.Y;
199
leftxf += leftdeltaxf*leftx;
200
rightxf += rightdeltaxf*leftx;
201
targetSurface += SurfaceWidth*leftx;
202
zTarget += SurfaceWidth*leftx;
203
leftZValue += leftZStep*leftx;
204
rightZValue += rightZStep*leftx;
206
leftR += leftStepR*leftx;
207
leftG += leftStepG*leftx;
208
leftB += leftStepB*leftx;
209
rightR += rightStepR*leftx;
210
rightG += rightStepG*leftx;
211
rightB += rightStepB*leftx;
213
leftTx += leftTxStep*leftx;
214
leftTy += leftTyStep*leftx;
215
rightTx += rightTxStep*leftx;
216
rightTy += rightTyStep*leftx;
220
// the main loop. Go through every span and draw it.
222
while (span < spanEnd)
224
leftx = (s32)(leftxf);
225
rightx = (s32)(rightxf + 0.5f);
227
// perform some clipping
229
if (leftx>=ViewPortRect.UpperLeftCorner.X &&
230
leftx<=ViewPortRect.LowerRightCorner.X)
232
if (leftZValue > *(zTarget + leftx))
234
*(zTarget + leftx) = leftZValue;
235
color = lockedTexture[((leftTy>>8)&textureYMask) * lockedTextureWidth + ((leftTx>>8)&textureXMask)];
236
*(targetSurface + leftx) = video::RGB16(video::getRed(color) * (leftR>>8) >>2,
237
video::getGreen(color) * (leftG>>8) >>2,
238
video::getBlue(color) * (leftR>>8) >>2);
243
if (rightx>=ViewPortRect.UpperLeftCorner.X &&
244
rightx<=ViewPortRect.LowerRightCorner.X)
246
if (rightZValue > *(zTarget + rightx))
248
*(zTarget + rightx) = rightZValue;
249
color = lockedTexture[((rightTy>>8)&textureYMask) * lockedTextureWidth + ((rightTx>>8)&textureXMask)];
250
*(targetSurface + rightx) = video::RGB16(video::getRed(color) * (rightR>>8) >>2,
251
video::getGreen(color) * (rightG>>8) >>2,
252
video::getBlue(color) * (rightR>>8) >>2);
257
leftxf += leftdeltaxf;
258
rightxf += rightdeltaxf;
260
targetSurface += SurfaceWidth;
261
zTarget += SurfaceWidth;
262
leftZValue += leftZStep;
263
rightZValue += rightZStep;
268
rightR += rightStepR;
269
rightG += rightStepG;
270
rightB += rightStepB;
272
leftTx += leftTxStep;
273
leftTy += leftTyStep;
274
rightTx += rightTxStep;
275
rightTy += rightTyStep;
278
if (triangleHalf>0) // break, we've gout only two halves
282
// setup variables for second half of the triangle.
286
tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);
288
rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;
289
rightxf = (f32)v2->Pos.X;
291
rightZValue = v2->ZValue;
292
rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);
294
rightR = video::getRed(v2->Color)<<8;
295
rightG = video::getGreen(v2->Color)<<8;
296
rightB = video::getBlue(v2->Color)<<8;
297
rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv);
298
rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv);
299
rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv);
301
rightTx = v2->TCoords.X;
302
rightTy = v2->TCoords.Y;
303
rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv);
304
rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv);
308
tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);
310
leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;
311
leftxf = (f32)v2->Pos.X;
313
leftZValue = v2->ZValue;
314
leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);
316
leftR = video::getRed(v2->Color)<<8;
317
leftG = video::getGreen(v2->Color)<<8;
318
leftB = video::getBlue(v2->Color)<<8;
319
leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv);
320
leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv);
321
leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv);
323
leftTx = v2->TCoords.X;
324
leftTy = v2->TCoords.Y;
325
leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv);
326
leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv);
335
RenderTarget->unlock();
342
} // end namespace video
343
} // end namespace irr
345
#endif // _IRR_COMPILE_WITH_SOFTWARE_
352
//! creates a flat triangle renderer
353
ITriangleRenderer* createTriangleRendererTextureGouraudWire(IZBuffer* zbuffer)
355
#ifdef _IRR_COMPILE_WITH_SOFTWARE_
356
return new CTRTextureGouraudWire(zbuffer);
359
#endif // _IRR_COMPILE_WITH_SOFTWARE_
362
} // end namespace video
363
} // end namespace irr