aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8.1/source/Irrlicht/CTRTextureGouraud.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8.1/source/Irrlicht/CTRTextureGouraud.cpp')
-rw-r--r--libraries/irrlicht-1.8.1/source/Irrlicht/CTRTextureGouraud.cpp468
1 files changed, 468 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CTRTextureGouraud.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CTRTextureGouraud.cpp
new file mode 100644
index 0000000..3b2795d
--- /dev/null
+++ b/libraries/irrlicht-1.8.1/source/Irrlicht/CTRTextureGouraud.cpp
@@ -0,0 +1,468 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "CTRTextureGouraud.h"
6
7#ifdef _IRR_COMPILE_WITH_SOFTWARE_
8
9namespace irr
10{
11namespace video
12{
13
14//! constructor
15CTRTextureGouraud::CTRTextureGouraud(IZBuffer* zbuffer)
16 : RenderTarget(0), ZBuffer(zbuffer), SurfaceWidth(0), SurfaceHeight(0),
17 BackFaceCullingEnabled(true), lockedZBuffer(0),
18 lockedSurface(0), lockedTexture(0), lockedTextureWidth(0),
19 textureXMask(0), textureYMask(0), Texture(0)
20{
21 #ifdef _DEBUG
22 setDebugName("CTRTextureGouraud");
23 #endif
24
25 if (ZBuffer)
26 zbuffer->grab();
27}
28
29
30
31//! destructor
32CTRTextureGouraud::~CTRTextureGouraud()
33{
34 if (RenderTarget)
35 RenderTarget->drop();
36
37 if (ZBuffer)
38 ZBuffer->drop();
39
40 if (Texture)
41 Texture->drop();
42}
43
44
45
46//! sets the Texture
47void CTRTextureGouraud::setTexture(video::IImage* texture)
48{
49 if (Texture)
50 Texture->drop();
51
52 Texture = texture;
53
54 if (Texture)
55 {
56 Texture->grab();
57 lockedTextureWidth = Texture->getDimension().Width;
58
59 textureXMask = lockedTextureWidth-1;
60 textureYMask = Texture->getDimension().Height-1;
61 }
62}
63
64
65
66
67//! en or disables the backface culling
68void CTRTextureGouraud::setBackfaceCulling(bool enabled)
69{
70 BackFaceCullingEnabled = enabled;
71}
72
73
74
75//! sets a render target
76void CTRTextureGouraud::setRenderTarget(video::IImage* surface, const core::rect<s32>& viewPort)
77{
78 if (RenderTarget)
79 RenderTarget->drop();
80
81 RenderTarget = surface;
82
83 if (RenderTarget)
84 {
85 SurfaceWidth = RenderTarget->getDimension().Width;
86 SurfaceHeight = RenderTarget->getDimension().Height;
87 RenderTarget->grab();
88 ViewPortRect = viewPort;
89 }
90}
91
92
93
94//! draws an indexed triangle list
95void CTRTextureGouraud::drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount)
96{
97 const S2DVertex *v1, *v2, *v3;
98
99 f32 tmpDiv; // temporary division factor
100 f32 longest; // saves the longest span
101 s32 height; // saves height of triangle
102 u16* targetSurface; // target pointer where to plot pixels
103 s32 spanEnd; // saves end of spans
104 f32 leftdeltaxf; // amount of pixels to increase on left side of triangle
105 f32 rightdeltaxf; // amount of pixels to increase on right side of triangle
106 s32 leftx, rightx; // position where we are
107 f32 leftxf, rightxf; // same as above, but as f32 values
108 s32 span; // current span
109 u16 *hSpanBegin, *hSpanEnd; // pointer used when plotting pixels
110 s32 leftR, leftG, leftB, rightR, rightG, rightB; // color values
111 s32 leftStepR, leftStepG, leftStepB,
112 rightStepR, rightStepG, rightStepB; // color steps
113 s32 spanR, spanG, spanB, spanStepR, spanStepG, spanStepB; // color interpolating values while drawing a span.
114 s32 leftTx, rightTx, leftTy, rightTy; // texture interpolating values
115 s32 leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values
116 s32 spanTx, spanTy, spanTxStep, spanTyStep; // values of Texturecoords when drawing a span
117 core::rect<s32> TriangleRect;
118
119 s32 leftZValue, rightZValue;
120 s32 leftZStep, rightZStep;
121 s32 spanZValue, spanZStep; // ZValues when drawing a span
122 TZBufferType* zTarget, *spanZTarget; // target of ZBuffer;
123
124 lockedSurface = (u16*)RenderTarget->lock();
125 lockedZBuffer = ZBuffer->lock();
126 lockedTexture = (u16*)Texture->lock();
127
128 for (s32 i=0; i<triangleCount; ++i)
129 {
130 v1 = &vertices[*indexList];
131 ++indexList;
132 v2 = &vertices[*indexList];
133 ++indexList;
134 v3 = &vertices[*indexList];
135 ++indexList;
136
137 // back face culling
138
139 if (BackFaceCullingEnabled)
140 {
141 s32 z = ((v3->Pos.X - v1->Pos.X) * (v3->Pos.Y - v2->Pos.Y)) -
142 ((v3->Pos.Y - v1->Pos.Y) * (v3->Pos.X - v2->Pos.X));
143
144 if (z < 0)
145 continue;
146 }
147
148 //near plane clipping
149
150 if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0)
151 continue;
152
153 // sort for width for inscreen clipping
154
155 if (v1->Pos.X > v2->Pos.X) swapVertices(&v1, &v2);
156 if (v1->Pos.X > v3->Pos.X) swapVertices(&v1, &v3);
157 if (v2->Pos.X > v3->Pos.X) swapVertices(&v2, &v3);
158
159 if ((v1->Pos.X - v3->Pos.X) == 0)
160 continue;
161
162 TriangleRect.UpperLeftCorner.X = v1->Pos.X;
163 TriangleRect.LowerRightCorner.X = v3->Pos.X;
164
165 // sort for height for faster drawing.
166
167 if (v1->Pos.Y > v2->Pos.Y) swapVertices(&v1, &v2);
168 if (v1->Pos.Y > v3->Pos.Y) swapVertices(&v1, &v3);
169 if (v2->Pos.Y > v3->Pos.Y) swapVertices(&v2, &v3);
170
171 TriangleRect.UpperLeftCorner.Y = v1->Pos.Y;
172 TriangleRect.LowerRightCorner.Y = v3->Pos.Y;
173
174 if (!TriangleRect.isRectCollided(ViewPortRect))
175 continue;
176
177 // calculate height of triangle
178 height = v3->Pos.Y - v1->Pos.Y;
179 if (!height)
180 continue;
181
182 // calculate longest span
183
184 longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X);
185
186 spanEnd = v2->Pos.Y;
187 span = v1->Pos.Y;
188 leftxf = (f32)v1->Pos.X;
189 rightxf = (f32)v1->Pos.X;
190
191 leftZValue = v1->ZValue;
192 rightZValue = v1->ZValue;
193
194 leftR = rightR = video::getRed(v1->Color)<<8;
195 leftG = rightG = video::getGreen(v1->Color)<<8;
196 leftB = rightB = video::getBlue(v1->Color)<<8;
197 leftTx = rightTx = v1->TCoords.X;
198 leftTy = rightTy = v1->TCoords.Y;
199
200 targetSurface = lockedSurface + span * SurfaceWidth;
201 zTarget = lockedZBuffer + span * SurfaceWidth;
202
203 if (longest < 0.0f)
204 {
205 tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y);
206 rightdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv;
207 rightZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv);
208 rightStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - rightR) * tmpDiv);
209 rightStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - rightG) * tmpDiv);
210 rightStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - rightB) * tmpDiv);
211 rightTxStep = (s32)((v2->TCoords.X - rightTx) * tmpDiv);
212 rightTyStep = (s32)((v2->TCoords.Y - rightTy) * tmpDiv);
213
214 tmpDiv = 1.0f / (f32)height;
215 leftdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv;
216 leftZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv);
217 leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv);
218 leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv);
219 leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv);
220 leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv);
221 leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv);
222 }
223 else
224 {
225 tmpDiv = 1.0f / (f32)height;
226 rightdeltaxf = (v3->Pos.X - v1->Pos.X) * tmpDiv;
227 rightZStep = (s32)((v3->ZValue - v1->ZValue) * tmpDiv);
228 rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv);
229 rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv);
230 rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv);
231 rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv);
232 rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv);
233
234 tmpDiv = 1.0f / (f32)(v2->Pos.Y - v1->Pos.Y);
235 leftdeltaxf = (v2->Pos.X - v1->Pos.X) * tmpDiv;
236 leftZStep = (s32)((v2->ZValue - v1->ZValue) * tmpDiv);
237 leftStepR = (s32)(((s32)(video::getRed(v2->Color)<<8) - leftR) * tmpDiv);
238 leftStepG = (s32)(((s32)(video::getGreen(v2->Color)<<8) - leftG) * tmpDiv);
239 leftStepB = (s32)(((s32)(video::getBlue(v2->Color)<<8) - leftB) * tmpDiv);
240 leftTxStep = (s32)((v2->TCoords.X - leftTx) * tmpDiv);
241 leftTyStep = (s32)((v2->TCoords.Y - leftTy) * tmpDiv);
242 }
243
244
245 // do it twice, once for the first half of the triangle,
246 // end then for the second half.
247
248 for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf)
249 {
250 if (spanEnd > ViewPortRect.LowerRightCorner.Y)
251 spanEnd = ViewPortRect.LowerRightCorner.Y;
252
253 // if the span <0, than we can skip these spans,
254 // and proceed to the next spans which are really on the screen.
255 if (span < ViewPortRect.UpperLeftCorner.Y)
256 {
257 // we'll use leftx as temp variable
258 if (spanEnd < ViewPortRect.UpperLeftCorner.Y)
259 {
260 leftx = spanEnd - span;
261 span = spanEnd;
262 }
263 else
264 {
265 leftx = ViewPortRect.UpperLeftCorner.Y - span;
266 span = ViewPortRect.UpperLeftCorner.Y;
267 }
268
269 leftxf += leftdeltaxf*leftx;
270 rightxf += rightdeltaxf*leftx;
271 targetSurface += SurfaceWidth*leftx;
272 zTarget += SurfaceWidth*leftx;
273 leftZValue += leftZStep*leftx;
274 rightZValue += rightZStep*leftx;
275
276 leftR += leftStepR*leftx;
277 leftG += leftStepG*leftx;
278 leftB += leftStepB*leftx;
279 rightR += rightStepR*leftx;
280 rightG += rightStepG*leftx;
281 rightB += rightStepB*leftx;
282
283 leftTx += leftTxStep*leftx;
284 leftTy += leftTyStep*leftx;
285 rightTx += rightTxStep*leftx;
286 rightTy += rightTyStep*leftx;
287 }
288
289
290 // the main loop. Go through every span and draw it.
291
292 while (span < spanEnd)
293 {
294 leftx = (s32)(leftxf);
295 rightx = (s32)(rightxf + 0.5f);
296
297 // perform some clipping
298 // thanks to a correction by hybrid
299 // calculations delayed to correctly propagate to textures etc.
300 s32 tDiffLeft=0, tDiffRight=0;
301 if (leftx<ViewPortRect.UpperLeftCorner.X)
302 tDiffLeft=ViewPortRect.UpperLeftCorner.X-leftx;
303 else
304 if (leftx>ViewPortRect.LowerRightCorner.X)
305 tDiffLeft=ViewPortRect.LowerRightCorner.X-leftx;
306
307 if (rightx<ViewPortRect.UpperLeftCorner.X)
308 tDiffRight=ViewPortRect.UpperLeftCorner.X-rightx;
309 else
310 if (rightx>ViewPortRect.LowerRightCorner.X)
311 tDiffRight=ViewPortRect.LowerRightCorner.X-rightx;
312
313 // draw the span
314 if (rightx + tDiffRight - leftx - tDiffLeft)
315 {
316 tmpDiv = 1.0f / (f32)(rightx - leftx);
317 spanZStep = (s32)((rightZValue - leftZValue) * tmpDiv);
318 spanZValue = leftZValue+tDiffLeft*spanZStep;
319
320 spanStepR = (s32)((rightR - leftR) * tmpDiv);
321 spanR = leftR+tDiffLeft*spanStepR;
322 spanStepG = (s32)((rightG - leftG) * tmpDiv);
323 spanG = leftG+tDiffLeft*spanStepG;
324 spanStepB = (s32)((rightB - leftB) * tmpDiv);
325 spanB = leftB+tDiffLeft*spanStepB;
326
327 spanTxStep = (s32)((rightTx - leftTx) * tmpDiv);
328 spanTx = leftTx + tDiffLeft*spanTxStep;
329 spanTyStep = (s32)((rightTy - leftTy) * tmpDiv);
330 spanTy = leftTy+tDiffLeft*spanTyStep;
331
332 hSpanBegin = targetSurface + leftx+tDiffLeft;
333 spanZTarget = zTarget + leftx+tDiffLeft;
334 hSpanEnd = targetSurface + rightx+tDiffRight;
335
336 while (hSpanBegin < hSpanEnd)
337 {
338 if (spanZValue > *spanZTarget)
339 {
340 *spanZTarget = spanZValue;
341 u16 color = lockedTexture[((spanTy>>8)&textureYMask) * lockedTextureWidth + ((spanTx>>8)&textureXMask)];
342 *hSpanBegin = video::RGB16(video::getRed(color) * (spanR>>8) >>2,
343 video::getGreen(color) * (spanG>>8) >>2,
344 video::getBlue(color) * (spanB>>8) >>2);
345 }
346
347 spanR += spanStepR;
348 spanG += spanStepG;
349 spanB += spanStepB;
350
351 spanTx += spanTxStep;
352 spanTy += spanTyStep;
353
354 spanZValue += spanZStep;
355 ++hSpanBegin;
356 ++spanZTarget;
357 }
358 }
359
360 leftxf += leftdeltaxf;
361 rightxf += rightdeltaxf;
362 ++span;
363 targetSurface += SurfaceWidth;
364 zTarget += SurfaceWidth;
365 leftZValue += leftZStep;
366 rightZValue += rightZStep;
367
368 leftR += leftStepR;
369 leftG += leftStepG;
370 leftB += leftStepB;
371 rightR += rightStepR;
372 rightG += rightStepG;
373 rightB += rightStepB;
374
375 leftTx += leftTxStep;
376 leftTy += leftTyStep;
377 rightTx += rightTxStep;
378 rightTy += rightTyStep;
379 }
380
381 if (triangleHalf>0) // break, we've gout only two halves
382 break;
383
384
385 // setup variables for second half of the triangle.
386
387 if (longest < 0.0f)
388 {
389 tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);
390
391 rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;
392 rightxf = (f32)v2->Pos.X;
393
394 rightZValue = v2->ZValue;
395 rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);
396
397 rightR = video::getRed(v2->Color)<<8;
398 rightG = video::getGreen(v2->Color)<<8;
399 rightB = video::getBlue(v2->Color)<<8;
400 rightStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - rightR) * tmpDiv);
401 rightStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - rightG) * tmpDiv);
402 rightStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - rightB) * tmpDiv);
403
404 rightTx = v2->TCoords.X;
405 rightTy = v2->TCoords.Y;
406 rightTxStep = (s32)((v3->TCoords.X - rightTx) * tmpDiv);
407 rightTyStep = (s32)((v3->TCoords.Y - rightTy) * tmpDiv);
408 }
409 else
410 {
411 tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);
412
413 leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;
414 leftxf = (f32)v2->Pos.X;
415
416 leftZValue = v2->ZValue;
417 leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);
418
419 leftR = video::getRed(v2->Color)<<8;
420 leftG = video::getGreen(v2->Color)<<8;
421 leftB = video::getBlue(v2->Color)<<8;
422 leftStepR = (s32)(((s32)(video::getRed(v3->Color)<<8) - leftR) * tmpDiv);
423 leftStepG = (s32)(((s32)(video::getGreen(v3->Color)<<8) - leftG) * tmpDiv);
424 leftStepB = (s32)(((s32)(video::getBlue(v3->Color)<<8) - leftB) * tmpDiv);
425
426 leftTx = v2->TCoords.X;
427 leftTy = v2->TCoords.Y;
428 leftTxStep = (s32)((v3->TCoords.X - leftTx) * tmpDiv);
429 leftTyStep = (s32)((v3->TCoords.Y - leftTy) * tmpDiv);
430 }
431
432
433 spanEnd = v3->Pos.Y;
434 }
435
436 }
437
438 RenderTarget->unlock();
439 ZBuffer->unlock();
440 Texture->unlock();
441}
442
443
444} // end namespace video
445} // end namespace irr
446
447#endif // _IRR_COMPILE_WITH_SOFTWARE_
448
449namespace irr
450{
451namespace video
452{
453
454//! creates a flat triangle renderer
455ITriangleRenderer* createTriangleRendererTextureGouraud(IZBuffer* zbuffer)
456{
457 #ifdef _IRR_COMPILE_WITH_SOFTWARE_
458 return new CTRTextureGouraud(zbuffer);
459 #else
460 return 0;
461 #endif // _IRR_COMPILE_WITH_SOFTWARE_
462}
463
464
465} // end namespace video
466} // end namespace irr
467
468