Merge branch 'ryzom/ark-features' into main/gingo-test
[ryzomcore.git] / nel / src / 3d / dru.cpp
blob1749eda8e66e9ade2455ecbc6defc0367f988868
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014-2016 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std3d.h"
22 #include "nel/misc/types_nl.h"
23 #include "nel/misc/dynloadlib.h"
25 #include "nel/3d/dru.h"
26 #include "nel/3d/driver.h"
27 #include "nel/3d/material.h"
28 #include "nel/3d/vertex_buffer.h"
29 #include "nel/3d/index_buffer.h"
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #else
34 # define NL_OPENGL_AVAILABLE
35 # ifdef NL_OS_WINDOWS
36 # define NL_DIRECT3D_AVAILABLE
37 # endif
38 #endif // HAVE_CONFIG_H
40 #ifdef NL_OS_WINDOWS
41 # ifndef NL_COMP_MINGW
42 # define NOMINMAX
43 # endif
44 # include <windows.h>
45 #else // NL_OS_WINDOWS
46 # include <dlfcn.h>
47 #endif // NL_OS_WINDOWS
49 using namespace NLMISC;
50 using namespace std;
52 #ifdef DEBUG_NEW
53 #define new DEBUG_NEW
54 #endif
56 namespace NL3D
60 typedef IDriver* (*IDRV_CREATE_PROC)(void);
61 const char *IDRV_CREATE_PROC_NAME = "NL3D_createIDriverInstance";
63 typedef uint32 (*IDRV_VERSION_PROC)(void);
64 const char *IDRV_VERSION_PROC_NAME = "NL3D_interfaceVersion";
66 #ifdef NL_STATIC
68 #ifdef NL_OPENGL_AVAILABLE
69 extern IDriver* createGlDriverInstance ();
70 #endif
72 #if defined(NL_OS_WINDOWS) && defined(NL_DIRECT3D_AVAILABLE)
73 extern IDriver* createD3DDriverInstance ();
74 #endif
76 #ifdef NL_OPENGLES_AVAILABLE
77 extern IDriver* createGlEsDriverInstance ();
78 #endif
80 #endif
82 // ***************************************************************************
83 IDriver *CDRU::createGlDriver()
85 #ifdef NL_STATIC
87 #ifdef NL_OPENGL_AVAILABLE
88 return createGlDriverInstance ();
89 #else
90 return NULL;
91 #endif // NL_OPENGL_AVAILABLE
93 #else
95 IDRV_CREATE_PROC createDriver = NULL;
96 IDRV_VERSION_PROC versionDriver = NULL;
98 CLibrary driverLib;
100 #if defined(NL_OS_UNIX) && defined(NL_DRIVER_PREFIX)
101 driverLib.addLibPath(NL_DRIVER_PREFIX);
102 #endif
104 if (!driverLib.loadLibrary(NL3D_GL_DLL_NAME, true, true, false))
106 throw EDruOpenglDriverNotFound();
109 nlinfo ("Using the library '" NL3D_GL_DLL_NAME "' that is in the directory: '%s'", driverLib.getLibFileName().c_str());
111 createDriver = (IDRV_CREATE_PROC) driverLib.getSymbolAddress(IDRV_CREATE_PROC_NAME);
112 if (createDriver == NULL)
114 throw EDruOpenglDriverCorrupted();
117 versionDriver = (IDRV_VERSION_PROC) driverLib.getSymbolAddress(IDRV_VERSION_PROC_NAME);
118 if (versionDriver != NULL)
120 if (versionDriver()<IDriver::InterfaceVersion)
121 throw EDruOpenglDriverOldVersion();
122 else if (versionDriver()>IDriver::InterfaceVersion)
123 throw EDruOpenglDriverUnknownVersion();
126 IDriver *ret= createDriver();
127 if (ret == NULL)
129 throw EDruOpenglDriverCantCreateDriver();
132 return ret;
133 #endif
136 // ***************************************************************************
137 IDriver *CDRU::createGlEsDriver()
139 #ifdef NL_STATIC
141 #ifdef NL_OPENGLES_AVAILABLE
142 return createGlEsDriverInstance ();
143 #else
144 return NULL;
145 #endif // NL_OPENGLES_AVAILABLE
147 #else
149 IDRV_CREATE_PROC createDriver = NULL;
150 IDRV_VERSION_PROC versionDriver = NULL;
152 CLibrary driverLib;
154 #if defined(NL_OS_UNIX) && defined(NL_DRIVER_PREFIX)
155 driverLib.addLibPath(NL_DRIVER_PREFIX);
156 #endif
158 if (!driverLib.loadLibrary(NL3D_GLES_DLL_NAME, true, true, false))
160 throw EDruOpenglEsDriverNotFound();
163 nlinfo ("Using the library '" NL3D_GLES_DLL_NAME "' that is in the directory: '%s'", driverLib.getLibFileName().c_str());
165 createDriver = (IDRV_CREATE_PROC) driverLib.getSymbolAddress(IDRV_CREATE_PROC_NAME);
166 if (createDriver == NULL)
168 throw EDruOpenglDriverCorrupted();
171 versionDriver = (IDRV_VERSION_PROC) driverLib.getSymbolAddress(IDRV_VERSION_PROC_NAME);
172 if (versionDriver != NULL)
174 if (versionDriver()<IDriver::InterfaceVersion)
175 throw EDruOpenglDriverOldVersion();
176 else if (versionDriver()>IDriver::InterfaceVersion)
177 throw EDruOpenglDriverUnknownVersion();
180 IDriver *ret= createDriver();
181 if (ret == NULL)
183 throw EDruOpenglEsDriverCantCreateDriver();
186 return ret;
187 #endif
190 // ***************************************************************************
192 #ifdef NL_OS_WINDOWS
194 IDriver *CDRU::createD3DDriver()
196 #ifdef NL_STATIC
198 #ifdef NL_DIRECT3D_AVAILABLE
199 return createD3DDriverInstance ();
200 #else
201 return NULL;
202 #endif // NL_DIRECT3D_AVAILABLE
204 #else
206 IDRV_CREATE_PROC createDriver = NULL;
207 IDRV_VERSION_PROC versionDriver = NULL;
209 CLibrary driverLib;
211 if (!driverLib.loadLibrary(NL3D_D3D_DLL_NAME, true, true, false))
213 throw EDruDirect3dDriverNotFound();
216 nlinfo ("Using the library '" NL3D_D3D_DLL_NAME "' that is in the directory: '%s'", driverLib.getLibFileName().c_str());
218 createDriver = (IDRV_CREATE_PROC) driverLib.getSymbolAddress(IDRV_CREATE_PROC_NAME);
219 if (createDriver == NULL)
221 throw EDruDirect3dDriverCorrupted();
224 versionDriver = (IDRV_VERSION_PROC) driverLib.getSymbolAddress(IDRV_VERSION_PROC_NAME);
225 if (versionDriver != NULL)
227 if (versionDriver()<IDriver::InterfaceVersion)
228 throw EDruDirect3dDriverOldVersion();
229 else if (versionDriver()>IDriver::InterfaceVersion)
230 throw EDruDirect3dDriverUnknownVersion();
233 IDriver *ret= createDriver();
234 if (ret == NULL)
236 throw EDruDirect3dDriverCantCreateDriver();
239 return ret;
240 #endif
242 #endif // NL_OS_WINDOWS
244 // ***************************************************************************
246 void CDRU::drawBitmap (float x, float y, float width, float height, ITexture& texture, IDriver& driver, CViewport viewport, bool blend)
248 CMatrix mtx;
249 mtx.identity();
250 driver.setupViewport (viewport);
251 driver.setupViewMatrix (mtx);
252 driver.setupModelMatrix (mtx);
253 driver.setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false);
255 static CMaterial mat;
256 mat.initUnlit ();
257 mat.setTexture (0, &texture);
258 mat.setBlend(blend);
259 mat.setZFunc(CMaterial::always);
261 static CVertexBuffer vb;
262 if (vb.getName().empty()) vb.setName("CDRU::drawBitmap");
263 vb.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag);
264 vb.setNumVertices (4);
265 vb.setPreferredMemory (CVertexBuffer::RAMVolatile, false);
267 CVertexBufferReadWrite vba;
268 vb.lock (vba);
269 vba.setVertexCoord (0, CVector (x, 0, y));
270 vba.setVertexCoord (1, CVector (x+width, 0, y));
271 vba.setVertexCoord (2, CVector (x+width, 0, y+height));
272 vba.setVertexCoord (3, CVector (x, 0, y+height));
273 vba.setTexCoord (0, 0, 0.f, 1.f);
274 vba.setTexCoord (1, 0, 1.f, 1.f);
275 vba.setTexCoord (2, 0, 1.f, 0.f);
276 vba.setTexCoord (3, 0, 0.f, 0.f);
278 driver.activeVertexBuffer(vb);
280 static CIndexBuffer pb;
281 if (pb.getName().empty()) NL_SET_IB_NAME(pb, "CDRU::drawBitmap");
282 pb.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
283 pb.setNumIndexes (6);
284 pb.setPreferredMemory (CIndexBuffer::RAMVolatile, false);
286 CIndexBufferReadWrite iba;
287 pb.lock (iba);
288 iba.setTri (0, 0, 1, 2);
289 iba.setTri (3, 2, 3, 0);
292 driver.activeIndexBuffer(pb);
293 driver.renderTriangles(mat, 0, 2);
297 // ***************************************************************************
298 void CDRU::drawLine (float x0, float y0, float x1, float y1, IDriver& driver, CRGBA col, CViewport viewport)
300 CMatrix mtx;
301 mtx.identity();
302 driver.setupViewport (viewport);
303 driver.setupViewMatrix (mtx);
304 driver.setupModelMatrix (mtx);
305 driver.setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false);
307 static CMaterial mat;
308 mat.initUnlit ();
309 mat.setSrcBlend(CMaterial::srcalpha);
310 mat.setDstBlend(CMaterial::invsrcalpha);
311 mat.setBlend(true);
312 mat.setColor(col);
313 mat.setZFunc (CMaterial::always);
315 static CVertexBuffer vb;
316 if (vb.getName().empty()) vb.setName("CDRU::drawLine");
317 vb.setVertexFormat (CVertexBuffer::PositionFlag);
318 vb.setNumVertices (2);
319 vb.setPreferredMemory (CVertexBuffer::RAMVolatile, false);
321 CVertexBufferReadWrite vba;
322 vb.lock (vba);
323 vba.setVertexCoord (0, CVector (x0, 0, y0));
324 vba.setVertexCoord (1, CVector (x1, 0, y1));
326 driver.activeVertexBuffer(vb);
328 static CIndexBuffer pb;
329 if (pb.getName().empty()) NL_SET_IB_NAME(pb, "CDRU::drawLine");
330 pb.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
331 pb.setNumIndexes (2);
332 pb.setPreferredMemory (CIndexBuffer::RAMVolatile, false);
334 CIndexBufferReadWrite iba;
335 pb.lock (iba);
336 iba.setLine (0, 0, 1);
339 driver.activeIndexBuffer(pb);
340 driver.renderLines(mat, 0, 1);
344 // ***************************************************************************
345 void CDRU::drawTriangle (float x0, float y0, float x1, float y1, float x2, float y2, IDriver& driver, CRGBA col, CViewport viewport)
347 CMatrix mtx;
348 mtx.identity();
349 driver.setupViewport (viewport);
350 driver.setupViewMatrix (mtx);
351 driver.setupModelMatrix (mtx);
352 driver.setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false);
354 static CMaterial mat;
355 mat.initUnlit();
356 mat.setSrcBlend(CMaterial::srcalpha);
357 mat.setDstBlend(CMaterial::invsrcalpha);
358 mat.setBlend(true);
359 mat.setColor(col);
360 mat.setZFunc (CMaterial::always);
362 static CVertexBuffer vb;
363 if (vb.getName().empty()) vb.setName("CDRU::drawTriangle");
364 vb.setVertexFormat (CVertexBuffer::PositionFlag);
365 vb.setNumVertices (3);
366 vb.setPreferredMemory (CVertexBuffer::RAMVolatile, false);
368 CVertexBufferReadWrite vba;
369 vb.lock (vba);
370 vba.setVertexCoord (0, CVector (x0, 0, y0));
371 vba.setVertexCoord (1, CVector (x1, 0, y1));
372 vba.setVertexCoord (2, CVector (x2, 0, y2));
374 driver.activeVertexBuffer(vb);
376 static CIndexBuffer pb;
377 if (pb.getName().empty()) NL_SET_IB_NAME(pb, "CDRU::drawTriangle");
378 pb.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
379 pb.setNumIndexes (3);
380 pb.setPreferredMemory (CIndexBuffer::RAMVolatile, false);
382 CIndexBufferReadWrite iba;
383 pb.lock (iba);
384 iba.setTri (0, 0, 1, 2);
387 driver.activeIndexBuffer(pb);
388 driver.renderTriangles(mat, 0, 1);
393 // ***************************************************************************
394 void CDRU::drawQuad (float x0, float y0, float x1, float y1, IDriver& driver, CRGBA col, CViewport viewport)
396 CMatrix mtx;
397 mtx.identity();
398 driver.setupViewport (viewport);
399 driver.setupViewMatrix (mtx);
400 driver.setupModelMatrix (mtx);
401 driver.setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false);
403 static CMaterial mat;
404 mat.initUnlit();
405 mat.setSrcBlend(CMaterial::srcalpha);
406 mat.setDstBlend(CMaterial::invsrcalpha);
407 mat.setBlend(true);
408 mat.setColor(col);
409 mat.setZFunc (CMaterial::always);
411 static CVertexBuffer vb;
412 if (vb.getName().empty()) vb.setName("CDRU::drawQuad");
413 vb.setVertexFormat (CVertexBuffer::PositionFlag);
414 vb.setNumVertices (4);
415 vb.setPreferredMemory (CVertexBuffer::RAMVolatile, false);
417 CVertexBufferReadWrite vba;
418 vb.lock (vba);
419 vba.setVertexCoord (0, CVector (x0, 0, y0));
420 vba.setVertexCoord (1, CVector (x1, 0, y0));
421 vba.setVertexCoord (2, CVector (x1, 0, y1));
422 vba.setVertexCoord (3, CVector (x0, 0, y1));
425 driver.activeVertexBuffer(vb);
426 driver.renderRawQuads(mat, 0, 1);
430 // ***************************************************************************
431 void CDRU::drawQuad (float xcenter, float ycenter, float radius, IDriver& driver, CRGBA col, CViewport viewport)
433 CMatrix mtx;
434 mtx.identity();
435 driver.setupViewport (viewport);
436 driver.setupViewMatrix (mtx);
437 driver.setupModelMatrix (mtx);
438 driver.setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false);
440 static CMaterial mat;
441 mat.initUnlit();
442 mat.setSrcBlend(CMaterial::srcalpha);
443 mat.setDstBlend(CMaterial::invsrcalpha);
444 mat.setBlend(true);
445 mat.setColor(col);
446 mat.setZFunc (CMaterial::always);
448 static CVertexBuffer vb;
449 if (vb.getName().empty()) vb.setName("CDRU::drawQuad");
450 vb.setVertexFormat (CVertexBuffer::PositionFlag);
451 vb.setNumVertices (4);
452 vb.setPreferredMemory (CVertexBuffer::RAMVolatile, false);
454 CVertexBufferReadWrite vba;
455 vb.lock (vba);
456 vba.setVertexCoord (0, CVector (xcenter-radius, 0, ycenter-radius));
457 vba.setVertexCoord (1, CVector (xcenter+radius, 0, ycenter-radius));
458 vba.setVertexCoord (2, CVector (xcenter+radius, 0, ycenter+radius));
459 vba.setVertexCoord (3, CVector (xcenter-radius, 0, ycenter+radius));
462 driver.activeVertexBuffer(vb);
463 driver.renderRawQuads(mat, 0, 1);
467 // ***************************************************************************
468 void CDRU::drawWiredQuad (float x0, float y0, float x1, float y1, IDriver& driver, CRGBA col, CViewport viewport)
470 // v-left
471 CDRU::drawLine(x0,y0,x0,y1 ,driver,col,viewport);
472 // v-right
473 CDRU::drawLine(x1,y0,x1,y1 ,driver,col,viewport);
474 // h-up
475 CDRU::drawLine(x0,y1,x1,y1,driver,col,viewport);
476 // h-bottom
477 CDRU::drawLine(x0,y0,x1,y0,driver,col,viewport);
481 // ***************************************************************************
482 void CDRU::drawWiredQuad (float xcenter, float ycenter, float radius, IDriver& driver, CRGBA col, CViewport viewport)
484 // v-left
485 CDRU::drawLine(xcenter-radius,ycenter-radius,xcenter-radius,ycenter+radius,driver,col,viewport);
486 // v-right
487 CDRU::drawLine(xcenter+radius,ycenter-radius,xcenter+radius,ycenter+radius,driver,col,viewport);
488 // h-up
489 CDRU::drawLine(xcenter-radius,ycenter+radius,xcenter+radius,ycenter+radius,driver,col,viewport);
490 // h-bottom
491 CDRU::drawLine(xcenter-radius,ycenter-radius,xcenter+radius,ycenter-radius,driver,col,viewport);
495 // ***************************************************************************
496 void CDRU::drawTrianglesUnlit(const NLMISC::CTriangleUV *trilist, sint ntris, CMaterial &mat, IDriver& driver)
498 static CVertexBuffer vb;
499 if (vb.getName().empty()) vb.setName("CDRU::drawTrianglesUnlit");
500 vb.setVertexFormat (CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag);
501 vb.setNumVertices (ntris*3);
502 vb.setPreferredMemory (CVertexBuffer::RAMVolatile, false);
504 static CIndexBuffer pb;
505 pb.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
506 pb.setNumIndexes(ntris*3);
507 pb.setPreferredMemory (CIndexBuffer::RAMVolatile, false);
508 if (pb.getFormat() == CIndexBuffer::Indices16)
510 nlassert(ntris * 3 <= 0xffff);
513 CVertexBufferReadWrite vba;
514 vb.lock (vba);
515 CIndexBufferReadWrite iba;
516 pb.lock (iba);
517 for(sint i=0;i<ntris;i++)
519 vba.setVertexCoord (i*3+0, trilist[i].V0);
520 vba.setVertexCoord (i*3+1, trilist[i].V1);
521 vba.setVertexCoord (i*3+2, trilist[i].V2);
522 vba.setTexCoord (i*3+0, 0, trilist[i].Uv0);
523 vba.setTexCoord (i*3+1, 0, trilist[i].Uv1);
524 vba.setTexCoord (i*3+2, 0, trilist[i].Uv2);
525 iba.setTri(i*3, i*3+0, i*3+1, i*3+2);
529 driver.activeVertexBuffer(vb);
530 driver.activeIndexBuffer(pb);
531 driver.renderTriangles(mat, 0, ntris);
535 // ***************************************************************************
536 void CDRU::drawTrianglesUnlit(const std::vector<NLMISC::CTriangleUV> &trilist, CMaterial &mat, IDriver& driver)
538 if(trilist.empty())
539 return;
541 CDRU::drawTrianglesUnlit( &(*trilist.begin()), (uint)trilist.size(), mat, driver);
545 // ***************************************************************************
546 void CDRU::drawLinesUnlit(const NLMISC::CLine *linelist, sint nlines, CMaterial &mat, IDriver& driver)
548 static CVertexBuffer vb;
549 if (vb.getName().empty()) vb.setName("CDRU::drawLinesUnlit");
550 vb.setVertexFormat (CVertexBuffer::PositionFlag);
551 vb.setNumVertices (nlines*2);
552 vb.setPreferredMemory (CVertexBuffer::RAMVolatile, false);
554 static CIndexBuffer pb;
555 pb.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT);
556 pb.setNumIndexes(nlines*2);
557 pb.setPreferredMemory (CIndexBuffer::RAMVolatile, false);
561 CVertexBufferReadWrite vba;
562 vb.lock (vba);
563 CIndexBufferReadWrite iba;
564 pb.lock (iba);
565 for(sint i=0;i<nlines;i++)
567 vba.setVertexCoord (i*2+0, linelist[i].V0);
568 vba.setVertexCoord (i*2+1, linelist[i].V1);
569 iba.setLine(i*2, i*2+0, i*2+1);
573 driver.activeVertexBuffer(vb);
574 driver.activeIndexBuffer(pb);
575 driver.renderLines(mat, 0, nlines);
577 // ***************************************************************************
578 void CDRU::drawLinesUnlit(const std::vector<NLMISC::CLine> &linelist, CMaterial &mat, IDriver& driver)
580 if(linelist.empty())
581 return;
582 CDRU::drawLinesUnlit( &(*linelist.begin()), (sint)linelist.size(), mat, driver);
584 // ***************************************************************************
585 void CDRU::drawLine(const CVector &a, const CVector &b, CRGBA color, IDriver& driver)
587 static NLMISC::CLine line;
588 static CMaterial mat;
589 static bool inited= false;
591 // Setup material.
592 if(!inited)
594 inited= true;
595 mat.initUnlit();
597 mat.setColor(color);
600 line.V0= a;
601 line.V1= b;
602 CDRU::drawLinesUnlit(&line, 1, mat, driver);
604 // ***************************************************************************
605 void CDRU::drawQuad (float x0, float y0, float x1, float y1, CRGBA col0, CRGBA col1, CRGBA col2, CRGBA col3, IDriver& driver, CViewport viewport)
607 CMatrix mtx;
608 mtx.identity();
609 driver.setupViewport (viewport);
610 driver.setupViewMatrix (mtx);
611 driver.setupModelMatrix (mtx);
612 driver.setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false);
614 static CMaterial mat;
615 mat.initUnlit();
616 mat.setSrcBlend(CMaterial::srcalpha);
617 mat.setDstBlend(CMaterial::invsrcalpha);
618 mat.setBlend(true);
619 mat.setZFunc (CMaterial::always);
621 static CVertexBuffer vb;
622 if (vb.getName().empty()) vb.setName("CDRU::drawQuad");
623 vb.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::PrimaryColorFlag);
624 vb.setNumVertices (4);
625 vb.setPreferredMemory (CVertexBuffer::RAMVolatile, false);
627 CVertexBufferReadWrite vba;
628 vb.lock (vba);
629 vba.setVertexCoord (0, CVector (x0, 0, y0));
630 vba.setColor (0, col0);
631 vba.setVertexCoord (1, CVector (x1, 0, y0));
632 vba.setColor (1, col1);
633 vba.setVertexCoord (2, CVector (x1, 0, y1));
634 vba.setColor (2, col2);
635 vba.setVertexCoord (3, CVector (x0, 0, y1));
636 vba.setColor (3, col3);
639 driver.activeVertexBuffer(vb);
640 driver.renderRawQuads(mat, 0, 1);
643 // ***************************************************************************
644 void CDRU::drawWiredBox(const CVector &corner, const CVector &vi, const CVector &vj, const CVector &vk, CRGBA color, IDriver& drv)
646 CVector p0= corner;
647 CVector p1= p0 + vi + vj + vk;
648 drawLine(p0, p0+vi, color, drv);
649 drawLine(p0, p0+vj, color, drv);
650 drawLine(p0, p0+vk, color, drv);
651 drawLine(p1, p1-vi, color, drv);
652 drawLine(p1, p1-vj, color, drv);
653 drawLine(p1, p1-vk, color, drv);
654 drawLine(p0+vi, p0+vi+vj, color, drv);
655 drawLine(p0+vi, p0+vi+vk, color, drv);
656 drawLine(p0+vj, p0+vj+vi, color, drv);
657 drawLine(p0+vj, p0+vj+vk, color, drv);
658 drawLine(p0+vk, p0+vk+vi, color, drv);
659 drawLine(p0+vk, p0+vk+vj, color, drv);
663 } // NL3D