diff options
author | David Walter Seikel | 2014-01-13 19:47:58 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-01-13 19:47:58 +1000 |
commit | f9158592e1478b2013afc7041d9ed041cf2d2f4a (patch) | |
tree | b16e389d7988700e21b4c9741044cefa536dcbae /libraries/irrlicht-1.8/source/Irrlicht/CSoftwareDriver.cpp | |
parent | Libraries readme updated with change markers and more of the Irrlicht changes. (diff) | |
download | SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.zip SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.gz SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.bz2 SledjHamr-f9158592e1478b2013afc7041d9ed041cf2d2f4a.tar.xz |
Update Irrlicht to 1.8.1. Include actual change markers this time. lol
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CSoftwareDriver.cpp | 973 |
1 files changed, 0 insertions, 973 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CSoftwareDriver.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CSoftwareDriver.cpp deleted file mode 100644 index 794b79b..0000000 --- a/libraries/irrlicht-1.8/source/Irrlicht/CSoftwareDriver.cpp +++ /dev/null | |||
@@ -1,973 +0,0 @@ | |||
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 "IrrCompileConfig.h" | ||
6 | #include "CSoftwareDriver.h" | ||
7 | |||
8 | #ifdef _IRR_COMPILE_WITH_SOFTWARE_ | ||
9 | |||
10 | #include "CSoftwareTexture.h" | ||
11 | #include "CBlit.h" | ||
12 | #include "os.h" | ||
13 | #include "S3DVertex.h" | ||
14 | |||
15 | namespace irr | ||
16 | { | ||
17 | namespace video | ||
18 | { | ||
19 | |||
20 | |||
21 | //! constructor | ||
22 | CSoftwareDriver::CSoftwareDriver(const core::dimension2d<u32>& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) | ||
23 | : CNullDriver(io, windowSize), BackBuffer(0), Presenter(presenter), WindowId(0), | ||
24 | SceneSourceRect(0), RenderTargetTexture(0), RenderTargetSurface(0), | ||
25 | CurrentTriangleRenderer(0), ZBuffer(0), Texture(0) | ||
26 | { | ||
27 | #ifdef _DEBUG | ||
28 | setDebugName("CSoftwareDriver"); | ||
29 | #endif | ||
30 | |||
31 | // create backbuffer | ||
32 | |||
33 | BackBuffer = new CImage(ECF_A1R5G5B5, windowSize); | ||
34 | if (BackBuffer) | ||
35 | { | ||
36 | BackBuffer->fill(SColor(0)); | ||
37 | |||
38 | // create z buffer | ||
39 | ZBuffer = video::createZBuffer(BackBuffer->getDimension()); | ||
40 | } | ||
41 | |||
42 | DriverAttributes->setAttribute("MaxTextures", 1); | ||
43 | DriverAttributes->setAttribute("MaxIndices", 1<<16); | ||
44 | DriverAttributes->setAttribute("MaxTextureSize", 1024); | ||
45 | DriverAttributes->setAttribute("Version", 1); | ||
46 | |||
47 | // create triangle renderers | ||
48 | |||
49 | TriangleRenderers[ETR_FLAT] = createTriangleRendererFlat(ZBuffer); | ||
50 | TriangleRenderers[ETR_FLAT_WIRE] = createTriangleRendererFlatWire(ZBuffer); | ||
51 | TriangleRenderers[ETR_GOURAUD] = createTriangleRendererGouraud(ZBuffer); | ||
52 | TriangleRenderers[ETR_GOURAUD_WIRE] = createTriangleRendererGouraudWire(ZBuffer); | ||
53 | TriangleRenderers[ETR_TEXTURE_FLAT] = createTriangleRendererTextureFlat(ZBuffer); | ||
54 | TriangleRenderers[ETR_TEXTURE_FLAT_WIRE] = createTriangleRendererTextureFlatWire(ZBuffer); | ||
55 | TriangleRenderers[ETR_TEXTURE_GOURAUD] = createTriangleRendererTextureGouraud(ZBuffer); | ||
56 | TriangleRenderers[ETR_TEXTURE_GOURAUD_WIRE] = createTriangleRendererTextureGouraudWire(ZBuffer); | ||
57 | TriangleRenderers[ETR_TEXTURE_GOURAUD_NOZ] = createTriangleRendererTextureGouraudNoZ(); | ||
58 | TriangleRenderers[ETR_TEXTURE_GOURAUD_ADD] = createTriangleRendererTextureGouraudAdd(ZBuffer); | ||
59 | |||
60 | // select render target | ||
61 | |||
62 | setRenderTarget(BackBuffer); | ||
63 | |||
64 | // select the right renderer | ||
65 | |||
66 | selectRightTriangleRenderer(); | ||
67 | } | ||
68 | |||
69 | |||
70 | |||
71 | //! destructor | ||
72 | CSoftwareDriver::~CSoftwareDriver() | ||
73 | { | ||
74 | // delete Backbuffer | ||
75 | if (BackBuffer) | ||
76 | BackBuffer->drop(); | ||
77 | |||
78 | // delete triangle renderers | ||
79 | |||
80 | for (s32 i=0; i<ETR_COUNT; ++i) | ||
81 | if (TriangleRenderers[i]) | ||
82 | TriangleRenderers[i]->drop(); | ||
83 | |||
84 | // delete zbuffer | ||
85 | |||
86 | if (ZBuffer) | ||
87 | ZBuffer->drop(); | ||
88 | |||
89 | // delete current texture | ||
90 | |||
91 | if (Texture) | ||
92 | Texture->drop(); | ||
93 | |||
94 | if (RenderTargetTexture) | ||
95 | RenderTargetTexture->drop(); | ||
96 | |||
97 | if (RenderTargetSurface) | ||
98 | RenderTargetSurface->drop(); | ||
99 | } | ||
100 | |||
101 | |||
102 | |||
103 | //! switches to a triangle renderer | ||
104 | void CSoftwareDriver::switchToTriangleRenderer(ETriangleRenderer renderer) | ||
105 | { | ||
106 | video::IImage* s = 0; | ||
107 | if (Texture) | ||
108 | s = ((CSoftwareTexture*)Texture)->getTexture(); | ||
109 | |||
110 | CurrentTriangleRenderer = TriangleRenderers[renderer]; | ||
111 | CurrentTriangleRenderer->setBackfaceCulling(Material.BackfaceCulling == true); | ||
112 | CurrentTriangleRenderer->setTexture(s); | ||
113 | CurrentTriangleRenderer->setRenderTarget(RenderTargetSurface, ViewPort); | ||
114 | } | ||
115 | |||
116 | |||
117 | //! void selects the right triangle renderer based on the render states. | ||
118 | void CSoftwareDriver::selectRightTriangleRenderer() | ||
119 | { | ||
120 | |||
121 | ETriangleRenderer renderer = ETR_FLAT; | ||
122 | |||
123 | if (Texture) | ||
124 | { | ||
125 | if (!Material.GouraudShading) | ||
126 | renderer = (!Material.Wireframe) ? ETR_TEXTURE_FLAT : ETR_TEXTURE_FLAT_WIRE; | ||
127 | else | ||
128 | { | ||
129 | if (Material.Wireframe) | ||
130 | renderer = ETR_TEXTURE_GOURAUD_WIRE; | ||
131 | else | ||
132 | { | ||
133 | if (Material.MaterialType == EMT_TRANSPARENT_ADD_COLOR || | ||
134 | Material.MaterialType == EMT_TRANSPARENT_ALPHA_CHANNEL || | ||
135 | Material.MaterialType == EMT_TRANSPARENT_VERTEX_ALPHA) | ||
136 | { | ||
137 | // simply draw all transparent stuff with the same renderer. at | ||
138 | // least it is transparent then. | ||
139 | renderer = ETR_TEXTURE_GOURAUD_ADD; | ||
140 | } | ||
141 | else | ||
142 | if ((Material.ZBuffer==ECFN_NEVER) && !Material.ZWriteEnable) | ||
143 | renderer = ETR_TEXTURE_GOURAUD_NOZ; | ||
144 | else | ||
145 | { | ||
146 | renderer = ETR_TEXTURE_GOURAUD; | ||
147 | } | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | else | ||
152 | { | ||
153 | if (!Material.GouraudShading) | ||
154 | renderer = (!Material.Wireframe) ? ETR_FLAT : ETR_FLAT_WIRE; | ||
155 | else | ||
156 | renderer = (!Material.Wireframe) ? ETR_GOURAUD : ETR_GOURAUD_WIRE; | ||
157 | } | ||
158 | |||
159 | switchToTriangleRenderer(renderer); | ||
160 | } | ||
161 | |||
162 | |||
163 | //! queries the features of the driver, returns true if feature is available | ||
164 | bool CSoftwareDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const | ||
165 | { | ||
166 | switch (feature) | ||
167 | { | ||
168 | case EVDF_RENDER_TO_TARGET: | ||
169 | case EVDF_TEXTURE_NSQUARE: | ||
170 | return FeatureEnabled[feature]; | ||
171 | default: | ||
172 | return false; | ||
173 | }; | ||
174 | } | ||
175 | |||
176 | |||
177 | //! sets transformation | ||
178 | void CSoftwareDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) | ||
179 | { | ||
180 | TransformationMatrix[state] = mat; | ||
181 | } | ||
182 | |||
183 | |||
184 | //! sets the current Texture | ||
185 | bool CSoftwareDriver::setActiveTexture(u32 stage, video::ITexture* texture) | ||
186 | { | ||
187 | if (texture && texture->getDriverType() != EDT_SOFTWARE) | ||
188 | { | ||
189 | os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); | ||
190 | return false; | ||
191 | } | ||
192 | |||
193 | if (Texture) | ||
194 | Texture->drop(); | ||
195 | |||
196 | Texture = texture; | ||
197 | |||
198 | if (Texture) | ||
199 | Texture->grab(); | ||
200 | |||
201 | selectRightTriangleRenderer(); | ||
202 | return true; | ||
203 | } | ||
204 | |||
205 | |||
206 | //! sets a material | ||
207 | void CSoftwareDriver::setMaterial(const SMaterial& material) | ||
208 | { | ||
209 | Material = material; | ||
210 | OverrideMaterial.apply(Material); | ||
211 | |||
212 | for (u32 i = 0; i < 1; ++i) | ||
213 | { | ||
214 | setActiveTexture(i, Material.getTexture(i)); | ||
215 | setTransform ((E_TRANSFORMATION_STATE) ( ETS_TEXTURE_0 + i ), | ||
216 | material.getTextureMatrix(i)); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | |||
221 | //! clears the zbuffer | ||
222 | bool CSoftwareDriver::beginScene(bool backBuffer, bool zBuffer, SColor color, | ||
223 | const SExposedVideoData& videoData, core::rect<s32>* sourceRect) | ||
224 | { | ||
225 | CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect); | ||
226 | WindowId=videoData.D3D9.HWnd; | ||
227 | SceneSourceRect = sourceRect; | ||
228 | |||
229 | if (backBuffer && BackBuffer) | ||
230 | BackBuffer->fill(color); | ||
231 | |||
232 | if (ZBuffer && zBuffer) | ||
233 | ZBuffer->clear(); | ||
234 | |||
235 | return true; | ||
236 | } | ||
237 | |||
238 | |||
239 | //! presents the rendered scene on the screen, returns false if failed | ||
240 | bool CSoftwareDriver::endScene() | ||
241 | { | ||
242 | CNullDriver::endScene(); | ||
243 | |||
244 | return Presenter->present(BackBuffer, WindowId, SceneSourceRect); | ||
245 | } | ||
246 | |||
247 | |||
248 | //! returns a device dependent texture from a software surface (IImage) | ||
249 | //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES | ||
250 | ITexture* CSoftwareDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData) | ||
251 | { | ||
252 | return new CSoftwareTexture(surface, name, false, mipmapData); | ||
253 | } | ||
254 | |||
255 | |||
256 | //! sets a render target | ||
257 | bool CSoftwareDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer, | ||
258 | bool clearZBuffer, SColor color) | ||
259 | { | ||
260 | if (texture && texture->getDriverType() != EDT_SOFTWARE) | ||
261 | { | ||
262 | os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR); | ||
263 | return false; | ||
264 | } | ||
265 | |||
266 | if (RenderTargetTexture) | ||
267 | RenderTargetTexture->drop(); | ||
268 | |||
269 | RenderTargetTexture = texture; | ||
270 | |||
271 | if (RenderTargetTexture) | ||
272 | { | ||
273 | RenderTargetTexture->grab(); | ||
274 | setRenderTarget(((CSoftwareTexture*)RenderTargetTexture)->getTexture()); | ||
275 | } | ||
276 | else | ||
277 | { | ||
278 | setRenderTarget(BackBuffer); | ||
279 | } | ||
280 | |||
281 | if (RenderTargetSurface && (clearBackBuffer || clearZBuffer)) | ||
282 | { | ||
283 | if (clearZBuffer) | ||
284 | ZBuffer->clear(); | ||
285 | |||
286 | if (clearBackBuffer) | ||
287 | RenderTargetSurface->fill(color); | ||
288 | } | ||
289 | |||
290 | return true; | ||
291 | } | ||
292 | |||
293 | |||
294 | //! sets a render target | ||
295 | void CSoftwareDriver::setRenderTarget(video::CImage* image) | ||
296 | { | ||
297 | if (RenderTargetSurface) | ||
298 | RenderTargetSurface->drop(); | ||
299 | |||
300 | RenderTargetSurface = image; | ||
301 | RenderTargetSize.Width = 0; | ||
302 | RenderTargetSize.Height = 0; | ||
303 | Render2DTranslation.X = 0; | ||
304 | Render2DTranslation.Y = 0; | ||
305 | |||
306 | if (RenderTargetSurface) | ||
307 | { | ||
308 | RenderTargetSurface->grab(); | ||
309 | RenderTargetSize = RenderTargetSurface->getDimension(); | ||
310 | } | ||
311 | |||
312 | setViewPort(core::rect<s32>(0,0,RenderTargetSize.Width,RenderTargetSize.Height)); | ||
313 | |||
314 | if (ZBuffer) | ||
315 | ZBuffer->setSize(RenderTargetSize); | ||
316 | } | ||
317 | |||
318 | |||
319 | //! sets a viewport | ||
320 | void CSoftwareDriver::setViewPort(const core::rect<s32>& area) | ||
321 | { | ||
322 | ViewPort = area; | ||
323 | |||
324 | //TODO: the clipping is not correct, because the projection is affected. | ||
325 | // to correct this, ViewPortSize and Render2DTranslation will have to be corrected. | ||
326 | core::rect<s32> rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height); | ||
327 | ViewPort.clipAgainst(rendert); | ||
328 | |||
329 | ViewPortSize = core::dimension2du(ViewPort.getSize()); | ||
330 | Render2DTranslation.X = (ViewPortSize.Width / 2) + ViewPort.UpperLeftCorner.X; | ||
331 | Render2DTranslation.Y = ViewPort.UpperLeftCorner.Y + ViewPortSize.Height - (ViewPortSize.Height / 2);// + ViewPort.UpperLeftCorner.Y; | ||
332 | |||
333 | if (CurrentTriangleRenderer) | ||
334 | CurrentTriangleRenderer->setRenderTarget(RenderTargetSurface, ViewPort); | ||
335 | } | ||
336 | |||
337 | |||
338 | void CSoftwareDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, | ||
339 | const void* indexList, u32 primitiveCount, | ||
340 | E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) | ||
341 | |||
342 | { | ||
343 | switch (iType) | ||
344 | { | ||
345 | case (EIT_16BIT): | ||
346 | { | ||
347 | drawVertexPrimitiveList16(vertices, vertexCount, (const u16*)indexList, primitiveCount, vType, pType); | ||
348 | break; | ||
349 | } | ||
350 | case (EIT_32BIT): | ||
351 | { | ||
352 | os::Printer::log("Software driver can not render 32bit buffers", ELL_ERROR); | ||
353 | break; | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | |||
358 | |||
359 | //! draws a vertex primitive list | ||
360 | void CSoftwareDriver::drawVertexPrimitiveList16(const void* vertices, u32 vertexCount, const u16* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType) | ||
361 | { | ||
362 | const u16* indexPointer=0; | ||
363 | core::array<u16> newBuffer; | ||
364 | switch (pType) | ||
365 | { | ||
366 | case scene::EPT_LINE_STRIP: | ||
367 | { | ||
368 | switch (vType) | ||
369 | { | ||
370 | case EVT_STANDARD: | ||
371 | { | ||
372 | for (u32 i=0; i < primitiveCount-1; ++i) | ||
373 | draw3DLine(((S3DVertex*)vertices)[indexList[i]].Pos, | ||
374 | ((S3DVertex*)vertices)[indexList[i+1]].Pos, | ||
375 | ((S3DVertex*)vertices)[indexList[i]].Color); | ||
376 | } | ||
377 | break; | ||
378 | case EVT_2TCOORDS: | ||
379 | { | ||
380 | for (u32 i=0; i < primitiveCount-1; ++i) | ||
381 | draw3DLine(((S3DVertex2TCoords*)vertices)[indexList[i]].Pos, | ||
382 | ((S3DVertex2TCoords*)vertices)[indexList[i+1]].Pos, | ||
383 | ((S3DVertex2TCoords*)vertices)[indexList[i]].Color); | ||
384 | } | ||
385 | break; | ||
386 | case EVT_TANGENTS: | ||
387 | { | ||
388 | for (u32 i=0; i < primitiveCount-1; ++i) | ||
389 | draw3DLine(((S3DVertexTangents*)vertices)[indexList[i]].Pos, | ||
390 | ((S3DVertexTangents*)vertices)[indexList[i+1]].Pos, | ||
391 | ((S3DVertexTangents*)vertices)[indexList[i]].Color); | ||
392 | } | ||
393 | break; | ||
394 | } | ||
395 | } | ||
396 | return; | ||
397 | case scene::EPT_LINE_LOOP: | ||
398 | drawVertexPrimitiveList16(vertices, vertexCount, indexList, primitiveCount-1, vType, scene::EPT_LINE_STRIP); | ||
399 | switch (vType) | ||
400 | { | ||
401 | case EVT_STANDARD: | ||
402 | draw3DLine(((S3DVertex*)vertices)[indexList[primitiveCount-1]].Pos, | ||
403 | ((S3DVertex*)vertices)[indexList[0]].Pos, | ||
404 | ((S3DVertex*)vertices)[indexList[primitiveCount-1]].Color); | ||
405 | break; | ||
406 | case EVT_2TCOORDS: | ||
407 | draw3DLine(((S3DVertex2TCoords*)vertices)[indexList[primitiveCount-1]].Pos, | ||
408 | ((S3DVertex2TCoords*)vertices)[indexList[0]].Pos, | ||
409 | ((S3DVertex2TCoords*)vertices)[indexList[primitiveCount-1]].Color); | ||
410 | break; | ||
411 | case EVT_TANGENTS: | ||
412 | draw3DLine(((S3DVertexTangents*)vertices)[indexList[primitiveCount-1]].Pos, | ||
413 | ((S3DVertexTangents*)vertices)[indexList[0]].Pos, | ||
414 | ((S3DVertexTangents*)vertices)[indexList[primitiveCount-1]].Color); | ||
415 | break; | ||
416 | } | ||
417 | return; | ||
418 | case scene::EPT_LINES: | ||
419 | { | ||
420 | switch (vType) | ||
421 | { | ||
422 | case EVT_STANDARD: | ||
423 | { | ||
424 | for (u32 i=0; i < 2*primitiveCount; i+=2) | ||
425 | draw3DLine(((S3DVertex*)vertices)[indexList[i]].Pos, | ||
426 | ((S3DVertex*)vertices)[indexList[i+1]].Pos, | ||
427 | ((S3DVertex*)vertices)[indexList[i]].Color); | ||
428 | } | ||
429 | break; | ||
430 | case EVT_2TCOORDS: | ||
431 | { | ||
432 | for (u32 i=0; i < 2*primitiveCount; i+=2) | ||
433 | draw3DLine(((S3DVertex2TCoords*)vertices)[indexList[i]].Pos, | ||
434 | ((S3DVertex2TCoords*)vertices)[indexList[i+1]].Pos, | ||
435 | ((S3DVertex2TCoords*)vertices)[indexList[i]].Color); | ||
436 | } | ||
437 | break; | ||
438 | case EVT_TANGENTS: | ||
439 | { | ||
440 | for (u32 i=0; i < 2*primitiveCount; i+=2) | ||
441 | draw3DLine(((S3DVertexTangents*)vertices)[indexList[i]].Pos, | ||
442 | ((S3DVertexTangents*)vertices)[indexList[i+1]].Pos, | ||
443 | ((S3DVertexTangents*)vertices)[indexList[i]].Color); | ||
444 | } | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | return; | ||
449 | case scene::EPT_TRIANGLE_FAN: | ||
450 | { | ||
451 | // TODO: don't convert fan to list | ||
452 | newBuffer.reallocate(primitiveCount*3); | ||
453 | for( u32 t=0; t<primitiveCount; ++t ) | ||
454 | { | ||
455 | newBuffer.push_back(indexList[0]); | ||
456 | newBuffer.push_back(indexList[t+1]); | ||
457 | newBuffer.push_back(indexList[t+2]); | ||
458 | } | ||
459 | |||
460 | indexPointer = newBuffer.pointer(); | ||
461 | } | ||
462 | break; | ||
463 | case scene::EPT_TRIANGLES: | ||
464 | indexPointer=indexList; | ||
465 | break; | ||
466 | default: | ||
467 | return; | ||
468 | } | ||
469 | switch (vType) | ||
470 | { | ||
471 | case EVT_STANDARD: | ||
472 | drawClippedIndexedTriangleListT((S3DVertex*)vertices, vertexCount, indexPointer, primitiveCount); | ||
473 | break; | ||
474 | case EVT_2TCOORDS: | ||
475 | drawClippedIndexedTriangleListT((S3DVertex2TCoords*)vertices, vertexCount, indexPointer, primitiveCount); | ||
476 | break; | ||
477 | case EVT_TANGENTS: | ||
478 | drawClippedIndexedTriangleListT((S3DVertexTangents*)vertices, vertexCount, indexPointer, primitiveCount); | ||
479 | break; | ||
480 | } | ||
481 | } | ||
482 | |||
483 | |||
484 | template<class VERTEXTYPE> | ||
485 | void CSoftwareDriver::drawClippedIndexedTriangleListT(const VERTEXTYPE* vertices, | ||
486 | s32 vertexCount, const u16* indexList, s32 triangleCount) | ||
487 | { | ||
488 | if (!RenderTargetSurface || !ZBuffer || !triangleCount) | ||
489 | return; | ||
490 | |||
491 | if (!checkPrimitiveCount(triangleCount)) | ||
492 | return; | ||
493 | |||
494 | // arrays for storing clipped vertices | ||
495 | core::array<VERTEXTYPE> clippedVertices; | ||
496 | core::array<u16> clippedIndices; | ||
497 | |||
498 | // calculate inverse world transformation | ||
499 | core::matrix4 worldinv(TransformationMatrix[ETS_WORLD]); | ||
500 | worldinv.makeInverse(); | ||
501 | |||
502 | // calculate view frustum planes | ||
503 | scene::SViewFrustum frustum(TransformationMatrix[ETS_PROJECTION] * TransformationMatrix[ETS_VIEW]); | ||
504 | |||
505 | // copy and transform clipping planes ignoring far plane | ||
506 | core::plane3df planes[5]; // ordered by near, left, right, bottom, top | ||
507 | for (int p=0; p<5; ++p) | ||
508 | worldinv.transformPlane(frustum.planes[p+1], planes[p]); | ||
509 | |||
510 | core::EIntersectionRelation3D inout[3]; // is point in front or back of plane? | ||
511 | |||
512 | // temporary buffer for vertices to be clipped by all planes | ||
513 | core::array<VERTEXTYPE> tClpBuf; | ||
514 | int t; | ||
515 | |||
516 | int i; | ||
517 | for (i=0; i<triangleCount; ++i) // for all input triangles | ||
518 | { | ||
519 | // add next triangle to tempClipBuffer | ||
520 | for (t=0; t<3; ++t) | ||
521 | tClpBuf.push_back(vertices[indexList[(i*3)+t]]); | ||
522 | |||
523 | for (int p=0; p<5; ++p) // for all clip planes | ||
524 | for (int v=0; v<(int)tClpBuf.size(); v+=3) // for all vertices in temp clip buffer | ||
525 | { | ||
526 | int inside = 0; | ||
527 | int outside = 0; | ||
528 | |||
529 | // test intersection relation of the current vertices | ||
530 | for (t=0; t<3; ++t) | ||
531 | { | ||
532 | inout[t] = planes[p].classifyPointRelation(tClpBuf[v+t].Pos); | ||
533 | if (inout[t] != core::ISREL3D_FRONT) | ||
534 | ++inside; | ||
535 | else | ||
536 | if (inout[t] == core::ISREL3D_FRONT) | ||
537 | ++outside; | ||
538 | } | ||
539 | |||
540 | if (!outside) | ||
541 | { | ||
542 | // add all vertices to new buffer, this triangle needs no clipping. | ||
543 | // so simply don't change this part of the temporary triangle buffer | ||
544 | continue; | ||
545 | } | ||
546 | |||
547 | if (!inside) | ||
548 | { | ||
549 | // all vertices are outside, don't add this triangle, so erase this | ||
550 | // triangle from the tClpBuf | ||
551 | tClpBuf.erase(v,3); | ||
552 | v -= 3; | ||
553 | continue; | ||
554 | } | ||
555 | |||
556 | // this vertex has to be clipped by this clipping plane. | ||
557 | |||
558 | // The following lines represent my try to implement some real clipping. | ||
559 | // There is a bug somewhere, and after some time I've given up. | ||
560 | // So now it is commented out, resulting that triangles which would need clipping | ||
561 | // are simply taken out (in the next two lines). | ||
562 | #ifndef __SOFTWARE_CLIPPING_PROBLEM__ | ||
563 | tClpBuf.erase(v,3); | ||
564 | v -= 3; | ||
565 | #endif | ||
566 | |||
567 | /* | ||
568 | // my idea is the following: | ||
569 | // current vertex to next vertex relation: | ||
570 | // out - out : add nothing | ||
571 | // out - in : add middle point | ||
572 | // in - out : add first and middle point | ||
573 | // in - in : add both | ||
574 | |||
575 | |||
576 | // now based on the number of intersections, create new vertices | ||
577 | // into tClpBuf (at the front for not letting them be clipped again) | ||
578 | |||
579 | int added = 0; | ||
580 | int prev = v+2; | ||
581 | for (int index=v; index<v+3; ++index) | ||
582 | { | ||
583 | if (inout[prev] == core::ISREL3D_BACK) | ||
584 | { | ||
585 | if (inout[index] != core::ISREL3D_BACK) | ||
586 | { | ||
587 | VERTEXTYPE& vt1 = tClpBuf[prev]; | ||
588 | VERTEXTYPE& vt2 = tClpBuf[index]; | ||
589 | |||
590 | f32 fact = planes[p].getKnownIntersectionWithLine(vt1.Pos, vt2.Pos); | ||
591 | VERTEXTYPE nvt; | ||
592 | nvt.Pos = vt1.Pos.getInterpolated(vt2.Pos, fact); | ||
593 | nvt.Color = vt1.Color.getInterpolated(vt2.Color, fact); | ||
594 | nvt.TCoords = vt1.TCoords.getInterpolated(vt2.TCoords, fact); | ||
595 | |||
596 | tClpBuf.push_front(nvt); ++index; ++prev; ++v; | ||
597 | ++added; | ||
598 | } | ||
599 | } | ||
600 | else | ||
601 | { | ||
602 | if (inout[index] != core::ISREL3D_BACK) | ||
603 | { | ||
604 | VERTEXTYPE vt1 = tClpBuf[index]; | ||
605 | VERTEXTYPE vt2 = tClpBuf[prev]; | ||
606 | tClpBuf.push_front(vt1); ++index; ++prev; ++v; | ||
607 | tClpBuf.push_front(vt2); ++index; ++prev; ++v; | ||
608 | added+= 2; | ||
609 | } | ||
610 | else | ||
611 | { | ||
612 | // same as above, but other way round. | ||
613 | VERTEXTYPE vt1 = tClpBuf[index]; | ||
614 | VERTEXTYPE vt2 = tClpBuf[prev]; | ||
615 | |||
616 | f32 fact = planes[p].getKnownIntersectionWithLine(vt1.Pos, vt2.Pos); | ||
617 | VERTEXTYPE nvt; | ||
618 | nvt.Pos = vt1.Pos.getInterpolated(vt2.Pos, fact); | ||
619 | nvt.Color = vt1.Color.getInterpolated(vt2.Color, fact); | ||
620 | nvt.TCoords = vt1.TCoords.getInterpolated(vt2.TCoords, fact); | ||
621 | |||
622 | tClpBuf.push_front(vt2); ++index; ++prev; ++v; | ||
623 | tClpBuf.push_front(nvt); ++index; ++prev; ++v; | ||
624 | added += 2; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | prev = index; | ||
629 | } | ||
630 | |||
631 | // erase original vertices | ||
632 | tClpBuf.erase(v,3); | ||
633 | v -= 3; | ||
634 | */ | ||
635 | |||
636 | |||
637 | } // end for all clip planes | ||
638 | |||
639 | // now add all remaining triangles in tempClipBuffer to clippedIndices | ||
640 | // and clippedVertices array. | ||
641 | if (clippedIndices.size() + tClpBuf.size() < 65535) | ||
642 | for (t=0; t<(int)tClpBuf.size(); ++t) | ||
643 | { | ||
644 | clippedIndices.push_back(clippedVertices.size()); | ||
645 | clippedVertices.push_back(tClpBuf[t]); | ||
646 | } | ||
647 | tClpBuf.clear(); | ||
648 | |||
649 | } // end for all input triangles | ||
650 | |||
651 | |||
652 | // draw newly created triangles. | ||
653 | |||
654 | // ----------------------------------------------------------- | ||
655 | // here all triangles are being drawn. I put this in a separate | ||
656 | // method, but the visual studio 6 compiler has great problems | ||
657 | // with templates and didn't accept two template methods in this | ||
658 | // class. | ||
659 | |||
660 | // draw triangles | ||
661 | |||
662 | CNullDriver::drawVertexPrimitiveList(clippedVertices.pointer(), clippedVertices.size(), | ||
663 | clippedIndices.pointer(), clippedIndices.size()/3, EVT_STANDARD, scene::EPT_TRIANGLES, EIT_16BIT); | ||
664 | |||
665 | if (TransformedPoints.size() < clippedVertices.size()) | ||
666 | TransformedPoints.set_used(clippedVertices.size()); | ||
667 | |||
668 | if (TransformedPoints.empty()) | ||
669 | return; | ||
670 | |||
671 | const VERTEXTYPE* currentVertex = clippedVertices.pointer(); | ||
672 | S2DVertex* tp = &TransformedPoints[0]; | ||
673 | |||
674 | core::dimension2d<u32> textureSize(0,0); | ||
675 | f32 zDiv; | ||
676 | |||
677 | if (Texture) | ||
678 | textureSize = ((CSoftwareTexture*)Texture)->getTexture()->getDimension(); | ||
679 | |||
680 | f32 transformedPos[4]; // transform all points in the list | ||
681 | |||
682 | core::matrix4 matrix(TransformationMatrix[ETS_PROJECTION]); | ||
683 | matrix *= TransformationMatrix[ETS_VIEW]; | ||
684 | matrix *= TransformationMatrix[ETS_WORLD]; | ||
685 | |||
686 | s32 ViewTransformWidth = (ViewPortSize.Width>>1); | ||
687 | s32 ViewTransformHeight = (ViewPortSize.Height>>1); | ||
688 | |||
689 | for (i=0; i<(int)clippedVertices.size(); ++i) | ||
690 | { | ||
691 | transformedPos[0] = currentVertex->Pos.X; | ||
692 | transformedPos[1] = currentVertex->Pos.Y; | ||
693 | transformedPos[2] = currentVertex->Pos.Z; | ||
694 | transformedPos[3] = 1.0f; | ||
695 | |||
696 | matrix.multiplyWith1x4Matrix(transformedPos); | ||
697 | zDiv = transformedPos[3] == 0.0f ? 1.0f : (1.0f / transformedPos[3]); | ||
698 | |||
699 | tp->Pos.X = (s32)(ViewTransformWidth * (transformedPos[0] * zDiv) + (Render2DTranslation.X)); | ||
700 | tp->Pos.Y = (Render2DTranslation.Y - (s32)(ViewTransformHeight * (transformedPos[1] * zDiv))); | ||
701 | tp->Color = currentVertex->Color.toA1R5G5B5(); | ||
702 | tp->ZValue = (TZBufferType)(32767.0f * zDiv); | ||
703 | |||
704 | tp->TCoords.X = (s32)(currentVertex->TCoords.X * textureSize.Width); | ||
705 | tp->TCoords.X <<= 8; | ||
706 | tp->TCoords.Y = (s32)(currentVertex->TCoords.Y * textureSize.Height); | ||
707 | tp->TCoords.Y <<= 8; | ||
708 | |||
709 | ++currentVertex; | ||
710 | ++tp; | ||
711 | } | ||
712 | |||
713 | // draw all transformed points from the index list | ||
714 | CurrentTriangleRenderer->drawIndexedTriangleList(&TransformedPoints[0], | ||
715 | clippedVertices.size(), clippedIndices.pointer(), clippedIndices.size()/3); | ||
716 | } | ||
717 | |||
718 | |||
719 | //! Draws a 3d line. | ||
720 | void CSoftwareDriver::draw3DLine(const core::vector3df& start, | ||
721 | const core::vector3df& end, SColor color) | ||
722 | { | ||
723 | core::vector3df vect = start.crossProduct(end); | ||
724 | vect.normalize(); | ||
725 | vect *= Material.Thickness*0.3f; | ||
726 | |||
727 | S3DVertex vtx[4]; | ||
728 | |||
729 | vtx[0].Color = color; | ||
730 | vtx[1].Color = color; | ||
731 | vtx[2].Color = color; | ||
732 | vtx[3].Color = color; | ||
733 | |||
734 | vtx[0].Pos = start; | ||
735 | vtx[1].Pos = end; | ||
736 | |||
737 | vtx[2].Pos = start + vect; | ||
738 | vtx[3].Pos = end + vect; | ||
739 | |||
740 | u16 idx[12] = {0,1,2, 0,2,1, 0,1,3, 0,3,1}; | ||
741 | |||
742 | drawIndexedTriangleList(vtx, 4, idx, 4); | ||
743 | } | ||
744 | |||
745 | |||
746 | //! clips a triangle against the viewing frustum | ||
747 | void CSoftwareDriver::clipTriangle(f32* transformedPos) | ||
748 | { | ||
749 | } | ||
750 | |||
751 | |||
752 | //! Only used by the internal engine. Used to notify the driver that | ||
753 | //! the window was resized. | ||
754 | void CSoftwareDriver::OnResize(const core::dimension2d<u32>& size) | ||
755 | { | ||
756 | // make sure width and height are multiples of 2 | ||
757 | core::dimension2d<u32> realSize(size); | ||
758 | |||
759 | if (realSize.Width % 2) | ||
760 | realSize.Width += 1; | ||
761 | |||
762 | if (realSize.Height % 2) | ||
763 | realSize.Height += 1; | ||
764 | |||
765 | if (ScreenSize != realSize) | ||
766 | { | ||
767 | if (ViewPort.getWidth() == (s32)ScreenSize.Width && | ||
768 | ViewPort.getHeight() == (s32)ScreenSize.Height) | ||
769 | { | ||
770 | ViewPort = core::rect<s32>(core::position2d<s32>(0,0), | ||
771 | core::dimension2di(realSize)); | ||
772 | } | ||
773 | |||
774 | ScreenSize = realSize; | ||
775 | |||
776 | bool resetRT = (RenderTargetSurface == BackBuffer); | ||
777 | |||
778 | if (BackBuffer) | ||
779 | BackBuffer->drop(); | ||
780 | BackBuffer = new CImage(ECF_A1R5G5B5, realSize); | ||
781 | |||
782 | if (resetRT) | ||
783 | setRenderTarget(BackBuffer); | ||
784 | } | ||
785 | } | ||
786 | |||
787 | //! returns the current render target size | ||
788 | const core::dimension2d<u32>& CSoftwareDriver::getCurrentRenderTargetSize() const | ||
789 | { | ||
790 | return RenderTargetSize; | ||
791 | } | ||
792 | |||
793 | |||
794 | //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. | ||
795 | void CSoftwareDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos, | ||
796 | const core::rect<s32>& sourceRect, | ||
797 | const core::rect<s32>* clipRect, SColor color, | ||
798 | bool useAlphaChannelOfTexture) | ||
799 | { | ||
800 | if (texture) | ||
801 | { | ||
802 | if (texture->getDriverType() != EDT_SOFTWARE) | ||
803 | { | ||
804 | os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR); | ||
805 | return; | ||
806 | } | ||
807 | |||
808 | if (useAlphaChannelOfTexture) | ||
809 | ((CSoftwareTexture*)texture)->getImage()->copyToWithAlpha( | ||
810 | RenderTargetSurface, destPos, sourceRect, color, clipRect); | ||
811 | else | ||
812 | ((CSoftwareTexture*)texture)->getImage()->copyTo( | ||
813 | RenderTargetSurface, destPos, sourceRect, clipRect); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | |||
818 | |||
819 | //! Draws a 2d line. | ||
820 | void CSoftwareDriver::draw2DLine(const core::position2d<s32>& start, | ||
821 | const core::position2d<s32>& end, | ||
822 | SColor color) | ||
823 | { | ||
824 | drawLine(RenderTargetSurface, start, end, color ); | ||
825 | } | ||
826 | |||
827 | |||
828 | //! Draws a pixel | ||
829 | void CSoftwareDriver::drawPixel(u32 x, u32 y, const SColor & color) | ||
830 | { | ||
831 | BackBuffer->setPixel(x, y, color, true); | ||
832 | } | ||
833 | |||
834 | |||
835 | //! draw a 2d rectangle | ||
836 | void CSoftwareDriver::draw2DRectangle(SColor color, const core::rect<s32>& pos, | ||
837 | const core::rect<s32>* clip) | ||
838 | { | ||
839 | if (clip) | ||
840 | { | ||
841 | core::rect<s32> p(pos); | ||
842 | |||
843 | p.clipAgainst(*clip); | ||
844 | |||
845 | if(!p.isValid()) | ||
846 | return; | ||
847 | |||
848 | drawRectangle(RenderTargetSurface, p, color); | ||
849 | } | ||
850 | else | ||
851 | { | ||
852 | if(!pos.isValid()) | ||
853 | return; | ||
854 | |||
855 | drawRectangle(RenderTargetSurface, pos, color); | ||
856 | } | ||
857 | } | ||
858 | |||
859 | |||
860 | //!Draws an 2d rectangle with a gradient. | ||
861 | void CSoftwareDriver::draw2DRectangle(const core::rect<s32>& pos, | ||
862 | SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, | ||
863 | const core::rect<s32>* clip) | ||
864 | { | ||
865 | // TODO: implement | ||
866 | draw2DRectangle(colorLeftUp, pos, clip); | ||
867 | } | ||
868 | |||
869 | |||
870 | //! \return Returns the name of the video driver. Example: In case of the Direct3D8 | ||
871 | //! driver, it would return "Direct3D8.1". | ||
872 | const wchar_t* CSoftwareDriver::getName() const | ||
873 | { | ||
874 | return L"Irrlicht Software Driver 1.0"; | ||
875 | } | ||
876 | |||
877 | |||
878 | //! Returns type of video driver | ||
879 | E_DRIVER_TYPE CSoftwareDriver::getDriverType() const | ||
880 | { | ||
881 | return EDT_SOFTWARE; | ||
882 | } | ||
883 | |||
884 | |||
885 | //! returns color format | ||
886 | ECOLOR_FORMAT CSoftwareDriver::getColorFormat() const | ||
887 | { | ||
888 | if (BackBuffer) | ||
889 | return BackBuffer->getColorFormat(); | ||
890 | else | ||
891 | return CNullDriver::getColorFormat(); | ||
892 | } | ||
893 | |||
894 | |||
895 | //! Returns the transformation set by setTransform | ||
896 | const core::matrix4& CSoftwareDriver::getTransform(E_TRANSFORMATION_STATE state) const | ||
897 | { | ||
898 | return TransformationMatrix[state]; | ||
899 | } | ||
900 | |||
901 | |||
902 | //! Creates a render target texture. | ||
903 | ITexture* CSoftwareDriver::addRenderTargetTexture(const core::dimension2d<u32>& size, | ||
904 | const io::path& name, | ||
905 | const ECOLOR_FORMAT format) | ||
906 | { | ||
907 | IImage* img = createImage(video::ECF_A1R5G5B5, size); | ||
908 | ITexture* tex = new CSoftwareTexture(img, name, true); | ||
909 | img->drop(); | ||
910 | addTexture(tex); | ||
911 | tex->drop(); | ||
912 | return tex; | ||
913 | } | ||
914 | |||
915 | |||
916 | //! Clears the ZBuffer. | ||
917 | void CSoftwareDriver::clearZBuffer() | ||
918 | { | ||
919 | if (ZBuffer) | ||
920 | ZBuffer->clear(); | ||
921 | } | ||
922 | |||
923 | |||
924 | //! Returns an image created from the last rendered frame. | ||
925 | IImage* CSoftwareDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target) | ||
926 | { | ||
927 | if (target != video::ERT_FRAME_BUFFER) | ||
928 | return 0; | ||
929 | |||
930 | if (BackBuffer) | ||
931 | { | ||
932 | IImage* tmp = createImage(BackBuffer->getColorFormat(), BackBuffer->getDimension()); | ||
933 | BackBuffer->copyTo(tmp); | ||
934 | return tmp; | ||
935 | } | ||
936 | else | ||
937 | return 0; | ||
938 | } | ||
939 | |||
940 | |||
941 | //! Returns the maximum amount of primitives (mostly vertices) which | ||
942 | //! the device is able to render with one drawIndexedTriangleList | ||
943 | //! call. | ||
944 | u32 CSoftwareDriver::getMaximalPrimitiveCount() const | ||
945 | { | ||
946 | return 0x00800000; | ||
947 | } | ||
948 | |||
949 | } // end namespace video | ||
950 | } // end namespace irr | ||
951 | |||
952 | #endif // _IRR_COMPILE_WITH_SOFTWARE_ | ||
953 | |||
954 | namespace irr | ||
955 | { | ||
956 | namespace video | ||
957 | { | ||
958 | |||
959 | |||
960 | //! creates a video driver | ||
961 | IVideoDriver* createSoftwareDriver(const core::dimension2d<u32>& windowSize, bool fullscreen, io::IFileSystem* io, video::IImagePresenter* presenter) | ||
962 | { | ||
963 | #ifdef _IRR_COMPILE_WITH_SOFTWARE_ | ||
964 | return new CSoftwareDriver(windowSize, fullscreen, io, presenter); | ||
965 | #else | ||
966 | return 0; | ||
967 | #endif | ||
968 | } | ||
969 | |||
970 | |||
971 | } // end namespace video | ||
972 | } // end namespace irr | ||
973 | |||