aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CSoftwareDriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CSoftwareDriver.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CSoftwareDriver.cpp973
1 files changed, 973 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CSoftwareDriver.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CSoftwareDriver.cpp
new file mode 100644
index 0000000..e079b07
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CSoftwareDriver.cpp
@@ -0,0 +1,973 @@
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
15namespace irr
16{
17namespace video
18{
19
20
21//! constructor
22CSoftwareDriver::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
72CSoftwareDriver::~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
104void 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.
118void 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
164bool 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
178void CSoftwareDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)
179{
180 TransformationMatrix[state] = mat;
181}
182
183
184//! sets the current Texture
185bool 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
207void 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
222bool 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
240bool 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
250ITexture* 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
257bool 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
295void 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
320void 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
338void 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
360void 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
484template<class VERTEXTYPE>
485void 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.
720void 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
747void 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.
754void 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
788const 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.
795void 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.
820void 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
829void 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
836void 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.
861void 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".
872const wchar_t* CSoftwareDriver::getName() const
873{
874 return L"Irrlicht Software Driver 1.0";
875}
876
877
878//! Returns type of video driver
879E_DRIVER_TYPE CSoftwareDriver::getDriverType() const
880{
881 return EDT_SOFTWARE;
882}
883
884
885//! returns color format
886ECOLOR_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
896const core::matrix4& CSoftwareDriver::getTransform(E_TRANSFORMATION_STATE state) const
897{
898 return TransformationMatrix[state];
899}
900
901
902//! Creates a render target texture.
903ITexture* 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.
917void CSoftwareDriver::clearZBuffer()
918{
919 if (ZBuffer)
920 ZBuffer->clear();
921}
922
923
924//! Returns an image created from the last rendered frame.
925IImage* 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.
944u32 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
954namespace irr
955{
956namespace video
957{
958
959
960//! creates a video driver
961IVideoDriver* 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