]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CTRTextureFlat.cpp
Set includes and libs on object targets
[irrlicht.git] / source / Irrlicht / CTRTextureFlat.cpp
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
4 \r
5 #include "IrrCompileConfig.h"\r
6 #include "CTRTextureGouraud.h"\r
7 \r
8 #ifdef _IRR_COMPILE_WITH_SOFTWARE_\r
9 \r
10 namespace irr\r
11 {\r
12 namespace video\r
13 {\r
14 \r
15 class CTRTextureFlat : public CTRTextureGouraud\r
16 {\r
17 public:\r
18 \r
19         CTRTextureFlat(IZBuffer* zbuffer)\r
20                 : CTRTextureGouraud(zbuffer)\r
21         {\r
22                 #ifdef _DEBUG\r
23                 setDebugName("CTRTextureFlat");\r
24                 #endif\r
25         }\r
26 \r
27         //! draws an indexed triangle list\r
28         virtual void drawIndexedTriangleList(S2DVertex* vertices, s32 vertexCount, const u16* indexList, s32 triangleCount) _IRR_OVERRIDE_\r
29         {\r
30                 const S2DVertex *v1, *v2, *v3;\r
31 \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
47 \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
52 \r
53                 lockedSurface = (u16*)RenderTarget->getData();\r
54                 lockedZBuffer = ZBuffer->lock();\r
55                 lockedTexture = (u16*)Texture->getData();\r
56 \r
57                 for (s32 i=0; i<triangleCount; ++i)\r
58                 {\r
59                         v1 = &vertices[*indexList];\r
60                         ++indexList;\r
61                         v2 = &vertices[*indexList];\r
62                         ++indexList;\r
63                         v3 = &vertices[*indexList];\r
64                         ++indexList;\r
65 \r
66                         // back face culling\r
67 \r
68                         if (BackFaceCullingEnabled)\r
69                         {\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
72 \r
73                                 if (z < 0)\r
74                                         continue;\r
75                         }\r
76 \r
77                         //near plane clipping\r
78 \r
79                         if (v1->ZValue<0 && v2->ZValue<0 && v3->ZValue<0)\r
80                                 continue;\r
81 \r
82                         // sort for width for inscreen clipping\r
83 \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
87 \r
88                         if ((v1->Pos.X - v3->Pos.X) == 0)\r
89                                 continue;\r
90 \r
91                         TriangleRect.UpperLeftCorner.X = v1->Pos.X;\r
92                         TriangleRect.LowerRightCorner.X = v3->Pos.X;\r
93 \r
94                         // sort for height for faster drawing.\r
95 \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
99 \r
100                         TriangleRect.UpperLeftCorner.Y = v1->Pos.Y;\r
101                         TriangleRect.LowerRightCorner.Y = v3->Pos.Y;\r
102 \r
103                         if (!TriangleRect.isRectCollided(ViewPortRect))\r
104                                 continue;\r
105 \r
106                         // calculate height of triangle\r
107                         height = v3->Pos.Y - v1->Pos.Y;\r
108                         if (!height)\r
109                                 continue;\r
110 \r
111                         // calculate longest span\r
112 \r
113                         longest = (v2->Pos.Y - v1->Pos.Y) / (f32)height * (v3->Pos.X - v1->Pos.X) + (v1->Pos.X - v2->Pos.X);\r
114 \r
115                         spanEnd = v2->Pos.Y;\r
116                         span = v1->Pos.Y;\r
117                         leftxf = (f32)v1->Pos.X;\r
118                         rightxf = (f32)v1->Pos.X;\r
119 \r
120                         leftZValue = v1->ZValue;\r
121                         rightZValue = v1->ZValue;\r
122 \r
123                         leftTx = rightTx = v1->TCoords.X;\r
124                         leftTy = rightTy = v1->TCoords.Y;\r
125 \r
126                         targetSurface = lockedSurface + span * SurfaceWidth;\r
127                         zTarget = lockedZBuffer + span * SurfaceWidth;\r
128 \r
129                         if (longest < 0.0f)\r
130                         {\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
136 \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
142                         }\r
143                         else\r
144                         {\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
150 \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
156                         }\r
157 \r
158 \r
159                         // do it twice, once for the first half of the triangle,\r
160                         // end then for the second half.\r
161 \r
162                         for (s32 triangleHalf=0; triangleHalf<2; ++triangleHalf)\r
163                         {\r
164                                 if (spanEnd > ViewPortRect.LowerRightCorner.Y)\r
165                                         spanEnd = ViewPortRect.LowerRightCorner.Y;\r
166 \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
170                                 {\r
171                                         // we'll use leftx as temp variable\r
172                                         if (spanEnd < ViewPortRect.UpperLeftCorner.Y)\r
173                                         {\r
174                                                 leftx = spanEnd - span;\r
175                                                 span = spanEnd;\r
176                                         }\r
177                                         else\r
178                                         {\r
179                                                 leftx = ViewPortRect.UpperLeftCorner.Y - span;\r
180                                                 span = ViewPortRect.UpperLeftCorner.Y;\r
181                                         }\r
182 \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
189 \r
190                                         leftTx += leftTxStep*leftx;\r
191                                         leftTy += leftTyStep*leftx;\r
192                                         rightTx += rightTxStep*leftx;\r
193                                         rightTy += rightTyStep*leftx;\r
194                                 }\r
195 \r
196 \r
197                                 // the main loop. Go through every span and draw it.\r
198 \r
199                                 while (span < spanEnd)\r
200                                 {\r
201                                         leftx = (s32)(leftxf);\r
202                                         rightx = (s32)(rightxf + 0.5f);\r
203 \r
204                                         // perform some clipping\r
205 \r
206                                         // TODO: clipping is not correct when leftx is clipped.\r
207 \r
208                                         if (leftx<ViewPortRect.UpperLeftCorner.X)\r
209                                                 leftx = ViewPortRect.UpperLeftCorner.X;\r
210                                         else\r
211                                                 if (leftx>ViewPortRect.LowerRightCorner.X)\r
212                                                         leftx = ViewPortRect.LowerRightCorner.X;\r
213 \r
214                                         if (rightx<ViewPortRect.UpperLeftCorner.X)\r
215                                                 rightx = ViewPortRect.UpperLeftCorner.X;\r
216                                         else\r
217                                                 if (rightx>ViewPortRect.LowerRightCorner.X)\r
218                                                         rightx = ViewPortRect.LowerRightCorner.X;\r
219 \r
220                                         // draw the span\r
221 \r
222                                         if (rightx - leftx != 0)\r
223                                         {\r
224                                                 tmpDiv = 1.0f / (rightx - leftx);\r
225                                                 spanZValue = leftZValue;\r
226                                                 spanZStep = (s32)((rightZValue - leftZValue) * tmpDiv);\r
227 \r
228                                                 hSpanBegin = targetSurface + leftx;\r
229                                                 spanZTarget = zTarget + leftx;\r
230                                                 hSpanEnd = targetSurface + rightx;\r
231 \r
232                                                 spanTx = leftTx;\r
233                                                 spanTy = leftTy;\r
234                                                 spanTxStep = (s32)((rightTx - leftTx) * tmpDiv);\r
235                                                 spanTyStep = (s32)((rightTy - leftTy) * tmpDiv);\r
236 \r
237                                                 while (hSpanBegin < hSpanEnd)\r
238                                                 {\r
239                                                         if (spanZValue > *spanZTarget)\r
240                                                         {\r
241                                                                 *spanZTarget = spanZValue;\r
242                                                                 *hSpanBegin = lockedTexture[((spanTy>>8)&textureYMask) * lockedTextureWidth + ((spanTx>>8)&textureXMask)];\r
243                                                         }\r
244 \r
245                                                         spanTx += spanTxStep;\r
246                                                         spanTy += spanTyStep;\r
247 \r
248                                                         spanZValue += spanZStep;\r
249                                                         ++hSpanBegin;\r
250                                                         ++spanZTarget;\r
251                                                 }\r
252                                         }\r
253 \r
254                                         leftxf += leftdeltaxf;\r
255                                         rightxf += rightdeltaxf;\r
256                                         ++span;\r
257                                         targetSurface += SurfaceWidth;\r
258                                         zTarget += SurfaceWidth;\r
259                                         leftZValue += leftZStep;\r
260                                         rightZValue += rightZStep;\r
261 \r
262                                         leftTx += leftTxStep;\r
263                                         leftTy += leftTyStep;\r
264                                         rightTx += rightTxStep;\r
265                                         rightTy += rightTyStep;\r
266                                 }\r
267 \r
268                                 if (triangleHalf>0) // break, we've gout only two halves\r
269                                         break;\r
270 \r
271 \r
272                                 // setup variables for second half of the triangle.\r
273 \r
274                                 if (longest < 0.0f)\r
275                                 {\r
276                                         tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);\r
277 \r
278                                         rightdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;\r
279                                         rightxf = (f32)v2->Pos.X;\r
280 \r
281                                         rightZValue = v2->ZValue;\r
282                                         rightZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);\r
283 \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
288                                 }\r
289                                 else\r
290                                 {\r
291                                         tmpDiv = 1.0f / (v3->Pos.Y - v2->Pos.Y);\r
292 \r
293                                         leftdeltaxf = (v3->Pos.X - v2->Pos.X) * tmpDiv;\r
294                                         leftxf = (f32)v2->Pos.X;\r
295 \r
296                                         leftZValue = v2->ZValue;\r
297                                         leftZStep = (s32)((v3->ZValue - v2->ZValue) * tmpDiv);\r
298 \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
303                                 }\r
304 \r
305 \r
306                                 spanEnd = v3->Pos.Y;\r
307                         }\r
308 \r
309                 }\r
310 \r
311                 ZBuffer->unlock();\r
312         }\r
313 };\r
314 \r
315 } // end namespace video\r
316 } // end namespace irr\r
317 \r
318 #endif // _IRR_COMPILE_WITH_SOFTWARE_\r
319 \r
320 namespace irr\r
321 {\r
322 namespace video\r
323 {\r
324 \r
325 //! creates a flat triangle renderer\r
326 ITriangleRenderer* createTriangleRendererTextureFlat(IZBuffer* zbuffer)\r
327 {\r
328         #ifdef _IRR_COMPILE_WITH_SOFTWARE_\r
329         return new CTRTextureFlat(zbuffer);\r
330         #else\r
331         return 0;\r
332         #endif // _IRR_COMPILE_WITH_SOFTWARE_\r
333 }\r
334 \r
335 } // end namespace video\r
336 } // end namespace irr\r