ViSP  2.8.0
vpD3DRenderer.cpp
1 /****************************************************************************
2  *
3  * $Id: vpD3DRenderer.cpp 4056 2013-01-05 13:04:42Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * D3D renderer for windows 32 display
36  *
37  * Authors:
38  * Bruno Renier
39  *
40  *****************************************************************************/
41 #ifndef DOXYGEN_SHOULD_SKIP_THIS
42 
43 #include <visp/vpConfig.h>
44 #if ( defined(WIN32) & defined(VISP_HAVE_D3D9) )
45 
46 #include <visp/vpD3DRenderer.h>
47 #include <visp/vpColor.h>
48 #include <visp/vpMath.h>
49 
50 /*
51  Be careful, when using :
52 
53  pd3dText->LockRect(0, &d3dLRect, &r, 0)
54  ...
55  pd3dText->UnlockRect(0, &d3dLRect, &r, 0)
56 
57  to write directly to the texture's surface,
58  the pointer returned in d3dLRect points to
59  the beginning of the locked suface and not
60  to the beginning of the texture's surface.
61  That's why setBufferPixel and other accesses
62  to this buffer are done in the locked surface
63  coordinates system.
64 
65  Moreover, when directly writing to a texture's surface,
66  you musn't forget to take the pitch of this texture
67  into account (see Direct3D documentation).
68 
69 */
70 
75 vpD3DRenderer::vpD3DRenderer()
76 {
77  pD3D=NULL;
78  pd3dDevice=NULL;
79  pd3dText=NULL;
80  pd3dVideoText=NULL;
81 
82  //D3D palette
83  vpColor pcolor; // Predefined colors
84  pcolor = vpColor::black;
85  colors[vpColor::id_black] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
86  pcolor = vpColor::lightBlue;
87  colors[vpColor::id_lightBlue] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
88  pcolor = vpColor::blue;
89  colors[vpColor::id_blue] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
90  pcolor = vpColor::darkBlue;
91  colors[vpColor::id_darkBlue] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
92  pcolor = vpColor::cyan;
93  colors[vpColor::id_cyan] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
94  pcolor = vpColor::lightGreen;
95  colors[vpColor::id_lightGreen] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
96  pcolor = vpColor::green;
97  colors[vpColor::id_green] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
98  pcolor = vpColor::darkGreen;
99  colors[vpColor::id_darkGreen] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
100  pcolor = vpColor::lightRed;
101  colors[vpColor::id_lightRed] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
102  pcolor = vpColor::red;
103  colors[vpColor::id_red] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
104  pcolor = vpColor::darkRed;
105  colors[vpColor::id_darkRed] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
106  pcolor = vpColor::white;
107  colors[vpColor::id_white] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
108  pcolor = vpColor::lightGray;
109  colors[vpColor::id_lightGray] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
110  pcolor = vpColor::gray;
111  colors[vpColor::id_gray] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
112  pcolor = vpColor::darkGray;
113  colors[vpColor::id_darkGray] = D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
114  pcolor = vpColor::yellow;
115  colors[vpColor::id_yellow]= D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
116  pcolor = vpColor::orange;
117  colors[vpColor::id_orange]= D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
118  pcolor = vpColor::purple;
119  colors[vpColor::id_purple]= D3DCOLOR_ARGB(0xFF,pcolor.R, pcolor.G, pcolor.B);
120 
121  //initialize the GDI palette
122  pcolor = vpColor::black;
123  colorsGDI[vpColor::id_black] = RGB(pcolor.R, pcolor.G, pcolor.B);
124  pcolor = vpColor::lightBlue;
125  colorsGDI[vpColor::id_lightBlue] = RGB(pcolor.R, pcolor.G, pcolor.B);
126  pcolor = vpColor::blue;
127  colorsGDI[vpColor::id_blue] = RGB(pcolor.R, pcolor.G, pcolor.B);
128  pcolor = vpColor::darkBlue;
129  colorsGDI[vpColor::id_darkBlue] = RGB(pcolor.R, pcolor.G, pcolor.B);
130  pcolor = vpColor::cyan;
131  colorsGDI[vpColor::id_cyan] = RGB(pcolor.R, pcolor.G, pcolor.B);
132  pcolor = vpColor::lightGreen;
133  colorsGDI[vpColor::id_lightGreen] = RGB(pcolor.R, pcolor.G, pcolor.B);
134  pcolor = vpColor::green;
135  colorsGDI[vpColor::id_green] = RGB(pcolor.R, pcolor.G, pcolor.B);
136  pcolor = vpColor::darkGreen;
137  colorsGDI[vpColor::id_darkGreen] = RGB(pcolor.R, pcolor.G, pcolor.B);
138  pcolor = vpColor::lightRed;
139  colorsGDI[vpColor::id_lightRed] = RGB(pcolor.R, pcolor.G, pcolor.B);
140  pcolor = vpColor::red;
141  colorsGDI[vpColor::id_red] = RGB(pcolor.R, pcolor.G, pcolor.B);
142  pcolor = vpColor::darkRed;
143  colorsGDI[vpColor::id_darkRed] = RGB(pcolor.R, pcolor.G, pcolor.B);
144  pcolor = vpColor::white;
145  colorsGDI[vpColor::id_white] = RGB(pcolor.R, pcolor.G, pcolor.B);
146  pcolor = vpColor::lightGray;
147  colorsGDI[vpColor::id_lightGray] = RGB(pcolor.R, pcolor.G, pcolor.B);
148  pcolor = vpColor::gray;
149  colorsGDI[vpColor::id_gray] = RGB(pcolor.R, pcolor.G, pcolor.B);
150  pcolor = vpColor::darkGray;
151  colorsGDI[vpColor::id_darkGray] = RGB(pcolor.R, pcolor.G, pcolor.B);
152  pcolor = vpColor::yellow;
153  colorsGDI[vpColor::id_yellow]= RGB(pcolor.R, pcolor.G, pcolor.B);
154  pcolor = vpColor::orange;
155  colorsGDI[vpColor::id_orange]= RGB(pcolor.R, pcolor.G, pcolor.B);
156  pcolor = vpColor::purple;
157  colorsGDI[vpColor::id_purple]= RGB(pcolor.R, pcolor.G, pcolor.B);
158 
159  //Creates a logical font
160  hFont = CreateFont(18, 0, 0, 0, FW_NORMAL, false, false, false,
161  DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
162  CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
163  DEFAULT_PITCH | FF_DONTCARE, NULL);
164 }
165 
170 vpD3DRenderer::~vpD3DRenderer()
171 {
172  DeleteObject(hFont);
173 
174  if(pd3dDevice != NULL)
175  pd3dDevice->Release();
176  if(pD3D != NULL)
177  pD3D->Release();
178  if(pd3dText != NULL)
179  pd3dText->Release();
180  if(pd3dVideoText != NULL)
181  pd3dVideoText->Release();
182 }
183 
189 unsigned int vpD3DRenderer::supPowerOf2(unsigned int n)
190 {
191  unsigned int i=0;
192  while(n>1)
193  {
194  n>>=1;
195  i++;
196  }
197  return static_cast<unsigned int>(1<<(i+1));
198 }
199 
207 bool vpD3DRenderer::init(HWND hwnd, unsigned int width, unsigned int height)
208 {
209  //simple stuff
210  nbCols = width;
211  nbRows = height;
212  hWnd = hwnd;
213 
214  //D3D initialize
215  if(NULL == (pD3D = Direct3DCreate9(D3D_SDK_VERSION)))
217  "Can't initialize D3D!");
218 
219  D3DDISPLAYMODE d3ddm;
220  if(FAILED(pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)))
222  "Can't get the adapter's display mode!");
223 
224 
225  D3DPRESENT_PARAMETERS d3dpp;
226  ZeroMemory(&d3dpp, sizeof(d3dpp));
227  d3dpp.BackBufferCount=1;
228  d3dpp.Windowed = TRUE;
229  d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
230  d3dpp.BackBufferFormat = d3ddm.Format;
231 
232  //creates a d3d device
233  if( FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL, hWnd,
234  D3DCREATE_SOFTWARE_VERTEXPROCESSING |
235  D3DCREATE_MULTITHREADED,
236  &d3dpp, &pd3dDevice )))
238  "Can't create the Direct3D device!");
239 
240 
241  //disables scene lightning
242  pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
243 
244 
245  //inits the direct3D view (for 2D rendering)
246  initView((float)nbCols,(float)nbRows);
247 
248 
249  //computes texture size (needs to be a power-of-2 large square)
250  textWidth = supPowerOf2( (nbCols>nbRows) ? nbCols : nbRows );
251 
252  //creates the system memory texture (the one we will directly modify)
253  //unfortunately, needs to be X8R8G8B8 in order to be able to use GDI drawing
254  //functions
255  if( D3DXCreateTexture(pd3dDevice, textWidth, textWidth, D3DX_DEFAULT, 0,
256  D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM , &pd3dText)
257  != D3D_OK)
258  {
260  "Can't create memory texture!");
261  }
262 
263  //creates the video memory texture (the one we will display) -
264  if( D3DXCreateTexture(pd3dDevice, textWidth, textWidth, D3DX_DEFAULT,
265  D3DUSAGE_DYNAMIC ,
266  D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &pd3dVideoText)
267  != D3D_OK)
268  {
270  "Can't create video texture!");
271  }
272 
273  //creates the sprite used to render the texture
274  if(D3DXCreateSprite(pd3dDevice, &pSprite) != S_OK)
276  "Can't create the texture's sprite!");
277 
278 
279 
280  return true;
281 }
282 
283 
284 
285 
291 void vpD3DRenderer::initView(float WindowWidth, float WindowHeight)
292 {
293  D3DXMATRIX Ortho2D;
294  D3DXMATRIX Identity;
295 
296  D3DXMatrixOrthoLH(&Ortho2D, WindowWidth, WindowHeight, 0.0f, 1.0f);
297  D3DXMatrixIdentity(&Identity);
298 
299  if( pd3dDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D) != D3D_OK
300  || pd3dDevice->SetTransform(D3DTS_WORLD, &Identity) != D3D_OK
301  || pd3dDevice->SetTransform(D3DTS_VIEW, &Identity) != D3D_OK)
303  "Can't set the view!");
304 }
305 
306 
313 void vpRGBaToTexture(const vpImage<vpRGBa>& I, unsigned char * imBuffer,
314  unsigned int pitch)
315 {
316  unsigned int j = I.getWidth();
317 
318  unsigned int k=0;
319  for(unsigned int i=0; i<I.getHeight()* I.getWidth(); i++)
320  {
321  if(j==0){
322  k += pitch - (I.getWidth() * 4);
323  j = I.getWidth();
324  }
325 
326  imBuffer[k+0] = I.bitmap[i].B;
327  imBuffer[k+1] = I.bitmap[i].G;
328  imBuffer[k+2] = I.bitmap[i].R;
329  imBuffer[k+3] = I.bitmap[i].A;// pb in vpimconvert? , 0xFF?
330  k+=4;
331  j--;
332  }
333 }
334 
341 void vpGreyToTexture(const vpImage<unsigned char>& I,
342  unsigned char * imBuffer,
343  unsigned int pitch)
344 {
345  unsigned int j = I.getWidth();
346 
347  unsigned int k=0;
348  for(unsigned int i=0; i<I.getHeight()* I.getWidth(); i++)
349  {
350  if(j==0){
351  k += pitch - (I.getWidth() * 4);
352  j = I.getWidth();
353  }
354 
355  imBuffer[k+0] = imBuffer[k+1] = imBuffer[k+2] = I.bitmap[i];
356  imBuffer[k+3] = 0xFF; //full opacity
357 
358  k+=4;
359  j--;
360  }
361 }
362 
367 void vpD3DRenderer::setImg(const vpImage<vpRGBa>& im)
368 {
369  //if the device has been initialized
370  if(pd3dDevice != NULL)
371  {
372  D3DLOCKED_RECT d3dLRect;
373 
374  RECT r;
375  r.top=0; r.left=0;
376  r.bottom=static_cast<signed long>(nbRows);
377  r.right=static_cast<signed long>(nbCols);
378 
379  //locks the texture to directly access it
380  if(pd3dText->LockRect(0, &d3dLRect, &r, 0)!= D3D_OK)
381  {
382  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
383  return;
384  }
385 
386  //gets the buffer and pitch of the texture
387  unsigned int pitch = static_cast<unsigned int>( d3dLRect.Pitch );
388  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
389 
390  //fills this texture with the image data (converted to bgra)
391  vpRGBaToTexture(im, buf, pitch);
392 
393  //unlocks the texture
394  if( pd3dText->UnlockRect(0) != D3D_OK)
395  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
396 
397  }
398 }
399 
404 void vpD3DRenderer::setImgROI(const vpImage<vpRGBa>& im, const vpImagePoint &iP, const unsigned int width, const unsigned int height )
405 {
406  //if the device has been initialized
407  if(pd3dDevice != NULL)
408  {
409  D3DLOCKED_RECT d3dLRect;
410 
411  RECT r;
412  r.top=(LONG)iP.get_v(); r.left=(LONG)iP.get_u();
413  r.bottom=(LONG)(iP.get_v()+height-1); r.right=(LONG)(iP.get_u()+width);
414 
415  //locks the texture to directly access it
416  if(pd3dText->LockRect(0, &d3dLRect, &r, 0)!= D3D_OK)
417  {
418  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
419  return;
420  }
421 
422  //gets the buffer and pitch of the texture
423  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
424  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
425 
426  //fills this texture with the image data (converted to bgra)
427  vpRGBaToTexture(im, buf, pitch);
428 
429  //unlocks the texture
430  if( pd3dText->UnlockRect(0) != D3D_OK)
431  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
432 
433  }
434 }
435 
436 
441 void vpD3DRenderer::setImg(const vpImage<unsigned char>& im)
442 {
443  //if the device has been initialized
444  if(pd3dDevice != NULL)
445  {
446  D3DLOCKED_RECT d3dLRect;
447 
448  RECT r;
449  r.top = 0;
450  r.left = 0;
451  r.bottom = static_cast<LONG>(nbRows);
452  r.right = static_cast<LONG>(nbCols);
453 
454  //locks the texture to directly access it
455  if(pd3dText->LockRect(0, &d3dLRect, &r, 0)!= D3D_OK)
456  {
457  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
458  return;
459  }
460 
461  //gets the buffer and pitch of the texture
462  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
463  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
464 
465  //fills this texture with the image data (converted to bgra)
466  vpGreyToTexture(im, buf, pitch);
467 
468  //unlocks the texture
469  if( pd3dText->UnlockRect(0) != D3D_OK)
470  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
471  }
472 
473 }
474 
475 
480 void vpD3DRenderer::setImgROI(const vpImage<unsigned char>& im, const vpImagePoint &iP, const unsigned int width, const unsigned int height )
481 {
482  //if the device has been initialized
483  if(pd3dDevice != NULL)
484  {
485  D3DLOCKED_RECT d3dLRect;
486 
487  RECT r;
488  r.top=(LONG)iP.get_v(); r.left=(LONG)iP.get_u();
489  r.bottom=(LONG)(iP.get_v()+height-1); r.right=(LONG)(iP.get_u()+width);
490 
491  //locks the texture to directly access it
492  if(pd3dText->LockRect(0, &d3dLRect, &r, 0)!= D3D_OK)
493  {
494  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
495  return;
496  }
497 
498  //gets the buffer and pitch of the texture
499  unsigned int pitch = static_cast<unsigned int>( d3dLRect.Pitch );
500  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
501 
502  //fills this texture with the image data (converted to bgra)
503  vpGreyToTexture(im, buf, pitch);
504 
505  //unlocks the texture
506  if( pd3dText->UnlockRect(0) != D3D_OK)
507  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
508  }
509 
510 }
511 
517 bool vpD3DRenderer::render()
518 {
519  // Clears the back buffer to a blue color
520  //pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
521 
522  //Begins the scene.
523  pd3dDevice->BeginScene();
524 
525  //Texture rectangle to display
526  RECT r;
527  r.top = 0;
528  r.left = 0;
529  r.bottom = static_cast<LONG>(nbRows);
530  r.right = static_cast<LONG>(nbCols);
531 
532  //Updates the video memory texture with the content of the system
533  //memory texture
534  pd3dDevice->UpdateTexture(pd3dText,pd3dVideoText);
535 
536  //Displays this texture as a sprite
537 
538 #if (D3DX_SDK_VERSION <= 9)
539  pSprite->Begin(); //
540  pSprite->Draw(pd3dVideoText, &r, NULL, NULL, NULL, NULL, 0xFFFFFFFF );
541 #else
542  pSprite->Begin(0);
543  pSprite->Draw(pd3dVideoText, &r, NULL, NULL, 0xFFFFFFFF );
544 #endif
545  pSprite->End();
546 
547  //Ends the scene.
548  pd3dDevice->EndScene();
549  //Presents the backbuffer
550  pd3dDevice->Present( NULL, NULL, NULL, NULL );
551 
552  return true;
553 }
554 
555 
562 void vpD3DRenderer::setPixel(const vpImagePoint &iP,
563  const vpColor &color)
564 {
565  if(iP.get_i()<0 || iP.get_j()<0 || iP.get_i()>=(int)nbRows || iP.get_j()>=(int)nbCols)
566  {
567  return;
568  }
569 
570  //if the device has been initialized
571  if(pd3dDevice != NULL)
572  {
573  D3DLOCKED_RECT d3dLRect;
574 
575  RECT r;
576 
577  r.top=(LONG)iP.get_i();
578  r.left=(LONG)iP.get_j();
579  r.bottom=(LONG)iP.get_i()+1;
580  r.right=(LONG)iP.get_j()+1;
581 
582  //locks the texture to directly access it
583  if(pd3dText->LockRect(0, &d3dLRect, &r, 0)!= D3D_OK)
584  {
585  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
586  return;
587  }
588 
589  //gets the buffer and pitch of the texture
590  unsigned int pitch = static_cast<unsigned int>( d3dLRect.Pitch );
591  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
592 
593  //the coordinates are in the locked area base
594  setBufferPixel(buf, pitch, 0, 0,color);
595 
596  //unlocks the texture
597  if( pd3dText->UnlockRect(0) != D3D_OK)
598  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
599  }
600 
601 }
602 
610 void vpD3DRenderer::drawLine(const vpImagePoint &ip1,
611  const vpImagePoint &ip2,
612  const vpColor &color,
613  unsigned int thickness, int style)
614 {
615 // if(i1<0 || j1<0 || i2<0 || j2<0 || e<0)
616 // {
617 // vpCERROR<<"Invalid parameters!"<<std::endl;
618 // return;
619 // }
620 
621  //if the device has been initialized
622  if(pd3dDevice != NULL)
623  {
624 
625  //Will contain the texture's surface drawing context
626  HDC hDCMem;
627 
628  //The texture's surface
629  IDirect3DSurface9 * pd3dSurf;
630  pd3dText->GetSurfaceLevel(0, &pd3dSurf);
631 
632  //We get its DC
633  pd3dSurf->GetDC(&hDCMem);
634 
635  //create the pen
636  HPEN hPen;
637  if (color.id < vpColor::id_unknown)
638  hPen = CreatePen(style, static_cast<int>(thickness), colorsGDI[color.id]);
639  else {
640  COLORREF gdicolor = RGB(color.R, color.G, color.B);
641  hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
642  }
643 
644  //we don't use the bkColor
645  SetBkMode(hDCMem, TRANSPARENT);
646 
647  //select the pen
648  SelectObject(hDCMem, hPen);
649 
650  //move to the starting point
651  MoveToEx(hDCMem, vpMath::round(ip1.get_u()), vpMath::round(ip1.get_v()), NULL);
652  //Draw the line
653  LineTo(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()));
654 
655 
656  //Releases the DC
657  pd3dSurf->ReleaseDC(hDCMem);
658  //Releases the surface's interface
659  pd3dSurf->Release();
660  //Deletes additional objects
661  DeleteObject(hPen);
662  }
663 }
664 
665 
675 void vpD3DRenderer::drawRect(const vpImagePoint &topLeft,
676  unsigned int width, unsigned int height,
677  const vpColor &color, bool fill ,
678  unsigned int /*thickness*/)
679 {
680  if(topLeft.get_i()>(int)nbRows-1 || topLeft.get_j()>(int)nbCols-1|| topLeft.get_i()+height<0 ||topLeft.get_j()+width<0)
681  {
682  // vpCERROR<<"Invalid parameters!"<<std::endl;
683  return;
684  }
685 
686  //if the device has been initialized
687  if(pd3dDevice != NULL)
688  {
689  D3DLOCKED_RECT d3dLRect;
690 
691  RECT r;
692  r.top= (LONG)((topLeft.get_i()>0)? topLeft.get_i() : 0 );
693  r.left=(LONG)((topLeft.get_j()>0)? topLeft.get_j() : 0 );
694  r.bottom=(LONG)((topLeft.get_i()+height < (int)nbRows) ? topLeft.get_i()+height : nbRows-1);
695  r.right=(LONG)((topLeft.get_j()+width < (int)nbCols) ? topLeft.get_j()+width : nbCols-1);
696 
697  /* unsigned */ int rectW = r.right - r.left;
698  /* unsigned */ int rectH = r.bottom - r.top;
699 
700  //locks the texture to directly access it
701  if(pd3dText->LockRect(0, &d3dLRect, &r, 0)!= D3D_OK)
702  {
703  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
704  return;
705  }
706 
707  //gets the buffer and pitch of the texture
708  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
709  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
710 
711  /* unsigned */ int x= 0;
712  /* unsigned */ int y= 0;
713 
714  if(fill == false)
715  {
716  //draws the top horizontal line
717  if(topLeft.get_i()>=0)
718  for(; x<rectW ; x++)
719  setBufferPixel(buf, pitch, x, y, color);
720 
721  //draws the right vertical line
722  if(topLeft.get_j()+width < nbCols)
723  for(; y<rectH ; y++)
724  setBufferPixel(buf, pitch, x, y, color);
725 
726  //draws the bottom horizontal line
727  if(topLeft.get_i()+height < nbRows)
728  for(; x>0 ; x--)
729  setBufferPixel(buf, pitch, x, y, color);
730 
731  //draws the left vertical line
732  if(topLeft.get_j()>=0)
733  for(; y>0 ; y--)
734  setBufferPixel(buf, pitch, x, y, color);
735  }
736 
737  else
738  {
739  if(topLeft.get_i()>=0 && topLeft.get_j()+width < nbCols && topLeft.get_i()+height < nbRows && topLeft.get_j()>=0)
740  {
741  for (x = 0; x<rectW; x++)
742  {
743  for (y = 0; y<rectH; y++)
744  setBufferPixel(buf, pitch, x, y, color);
745  }
746  }
747  }
748 
749  //unlocks the texture
750  if( pd3dText->UnlockRect(0) != D3D_OK)
751  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
752  }
753 }
754 
759 void vpD3DRenderer::clear(const vpColor &color)
760 {
761  //if the device has been initialized
762  if(pd3dDevice != NULL)
763  {
764  D3DLOCKED_RECT d3dLRect;
765 
766  RECT r;
767  r.top = 0;
768  r.left = 0;
769  r.bottom = static_cast<LONG>( nbRows );
770  r.right = static_cast<LONG>( nbCols );
771 
772  //locks the texture to directly access it
773  if(pd3dText->LockRect(0, &d3dLRect, &r, 0)!= D3D_OK)
774  {
775  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
776  return;
777  }
778 
779  //gets the buffer and pitch of the texture
780  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
781  long * buf = (long *) ( d3dLRect.pBits );
782 
783  unsigned long c;
784  if (color.id < vpColor::id_unknown)
785  c = colors[color.id];
786  else {
787  c = D3DCOLOR_ARGB(0xFF, color.R, color.G, color.B);
788  }
789  long * end = (long*)((long)buf + (pitch * nbRows));
790 
791  //fills the whole image
792  while (buf < end)
793  *buf++ = static_cast<long>( c );
794 
795  //unlocks the texture
796  if( pd3dText->UnlockRect(0) != D3D_OK)
797  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
798  }
799 }
800 
801 
802 
803 //writes current circle pixels using symetry to reduce the algorithm's complexity
804 void vpD3DRenderer::subDrawCircle(int i, int j,
805  int x, int y,
806  vpColor col,
807  unsigned char* buf, unsigned int pitch,
808  unsigned int maxX, unsigned int maxY)
809 {
810  if (x == 0) {
811  setBufferPixel(buf, pitch, i , j+y, col, maxX, maxY);
812  setBufferPixel(buf, pitch, i , j-y, col, maxX, maxY);
813  setBufferPixel(buf, pitch, i+y, j, col, maxX, maxY);
814  setBufferPixel(buf, pitch, i-y, j, col, maxX, maxY);
815  } else
816  if (x == y) {
817  setBufferPixel(buf, pitch, i+x,j+y,col, maxX, maxY);
818  setBufferPixel(buf, pitch, i-x,j+y,col, maxX, maxY);
819  setBufferPixel(buf, pitch, i+x,j-y,col, maxX, maxY);
820  setBufferPixel(buf, pitch, i-x,j-y,col, maxX, maxY);
821  } else
822  if (x < y) {
823  setBufferPixel(buf, pitch, i+x,j+y,col, maxX, maxY);
824  setBufferPixel(buf, pitch, i-x,j+y,col, maxX, maxY);
825  setBufferPixel(buf, pitch, i+x,j-y,col, maxX, maxY);
826  setBufferPixel(buf, pitch, i-x,j-y,col, maxX, maxY);
827  setBufferPixel(buf, pitch, i+y,j+x,col, maxX, maxY);
828  setBufferPixel(buf, pitch, i-y,j+x,col, maxX, maxY);
829  setBufferPixel(buf, pitch, i+y,j-x,col, maxX, maxY);
830  setBufferPixel(buf, pitch, i-y,j-x,col, maxX, maxY);
831  }
832 
833 }
834 
841 void vpD3DRenderer::drawCircle(const vpImagePoint &center, unsigned int radius,
842  const vpColor &color, bool /*fill*/, unsigned int /*thickness*/)
843 {
844  if(radius<1 || vpMath::round(center.get_i()+radius)<0 || vpMath::round(center.get_i()-radius) > (int)nbRows || vpMath::round(center.get_j()+radius)<0 || vpMath::round(center.get_j()-radius) > (int)nbCols)
845  return;
846 
847  //if the device has been initialized
848  if(pd3dDevice != NULL)
849  {
850  D3DLOCKED_RECT d3dLRect;
851 
852  RECT rec;
853  int radius_ = static_cast<int>( radius );
854  int rleft = (vpMath::round(center.get_j()-radius_) > 0) ? vpMath::round(center.get_j())-radius_ : 0;
855  int rtop = (vpMath::round(center.get_i()-radius_) > 0) ? vpMath::round(center.get_i())-radius_ : 0;
856 
857  rec.top= rtop;
858  rec.left= rleft;
859  rec.bottom=(LONG)((vpMath::round(center.get_i()+radius_) < (int)nbRows) ? center.get_i()+radius_ : nbRows-1);
860  rec.right=(LONG)((vpMath::round(center.get_j()+radius_) < (int)nbCols) ? center.get_j()+radius_ : nbCols-1);
861 
862  //used as maxX and maxY for setBufferPixel
863  unsigned int rectW = static_cast<unsigned int> ( rec.right - rleft );
864  unsigned int rectH = static_cast<unsigned int> ( rec.bottom - rtop );
865 
866  //locks the texture to directly access it
867  if(pd3dText->LockRect(0, &d3dLRect, &rec, 0)!= D3D_OK)
868  {
869  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
870  return;
871  }
872 
873  //gets the buffer and pitch of the texture
874  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
875  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
876 
877  // Bresenham 's circle algorithm
878 
879  int x = 0;
880  int y = static_cast<int>( radius );
881  int p = (3 - (y<<1));
882 
883  vpImagePoint ip;
884  ip.set_i(center.get_i()-rtop);
885  ip.set_j(center.get_j()-rleft);
886 
887  subDrawCircle(vpMath::round(ip.get_i()), vpMath::round(ip.get_j()), x, y, color, buf, pitch, rectW, rectH);
888  while(x < y){
889  x++;
890  if (p < 0)
891  {
892  p += ((x<<1)+1)<<1;
893  }
894  else
895  {
896  y--;
897  p += (((x-y)<<1)+1)<<1;
898  }
899  subDrawCircle(vpMath::round(ip.get_i()), vpMath::round(ip.get_j()), x, y, color, buf, pitch, rectW, rectH);
900  }
901 
902 
903 
904  //unlocks the texture
905  if( pd3dText->UnlockRect(0) != D3D_OK)
906  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
907  }
908 }
909 
910 
911 
918 void vpD3DRenderer::drawText(const vpImagePoint &ip, const char * text,
919  const vpColor &color)
920 {
921  //Will contain the texture's surface drawing context
922  HDC hDCMem;
923 
924  //The texture's surface
925  IDirect3DSurface9 * pd3dSurf;
926  pd3dText->GetSurfaceLevel(0, &pd3dSurf);
927 
928  //We get its DC
929  pd3dSurf->GetDC(&hDCMem);
930 
931  //Select the font
932  SelectObject(hDCMem, hFont);
933 
934  //set the text color
935  if (color.id < vpColor::id_unknown)
936  SetTextColor(hDCMem, colorsGDI[color.id]);
937  else {
938  COLORREF gdicolor = RGB(color.R, color.G, color.B);
939  SetTextColor(hDCMem, gdicolor);
940  }
941 
942  //we don't use the bkColor
943  SetBkMode(hDCMem, TRANSPARENT);
944 
945  SIZE size;
946  int length = (int) strlen(text);
947 
948  //get the displayed string dimensions
949  GetTextExtentPoint32(hDCMem, text, length, &size);
950 
951  //displays the string
952  TextOut(hDCMem, vpMath::round(ip.get_u()), vpMath::round(ip.get_v()), text, length);
953 
954  //Releases the DC
955  pd3dSurf->ReleaseDC(hDCMem);
956  //Releases the surface's interface
957  pd3dSurf->Release();
958  //Deletes additional objects
959  DeleteObject(hFont);
960 }
961 
962 
970 void vpD3DRenderer::drawCross(const vpImagePoint &ip,
971  unsigned int size,
972  const vpColor &color, unsigned int thickness)
973 {
974  if(ip.get_i()<0 || ip.get_j()<0 || ip.get_i()>(int)nbRows || ip.get_j()>(int)nbCols || thickness<=0)
975  return;
976 
977  //if the device has been initialized
978  if(pd3dDevice != NULL)
979  {
980  D3DLOCKED_RECT d3dLRect;
981 
982  RECT rec;
983  thickness = (thickness<size)? thickness : size;
984  int half_size_ = static_cast<int>( size/2 );
985  //if j-size/2 is inferior to 0, use 0
986  int rleft = ( (vpMath::round(ip.get_j()) - half_size_) < 0 ) ? 0 : vpMath::round(ip.get_j()) - half_size_;
987  //if j-size/2 is inferior to 0, use 0
988  int rtop = ( (vpMath::round(ip.get_i()) - half_size_) < 0 ) ? 0 : vpMath::round(ip.get_i()) - half_size_;
989 
990  rec.top = rtop;
991  rec.left = rleft;
992  rec.bottom= (LONG)(ip.get_i() + (size/2));
993  rec.right = (LONG)(ip.get_j() + (size/2));
994 
995  //locks the texture to directly access it
996  if( pd3dText->LockRect(0, &d3dLRect, &rec, 0) != D3D_OK)
997  {
998  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
999  return;
1000  }
1001 
1002  //gets the buffer and pitch of the texture
1003  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
1004  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
1005 
1006  /* unsigned */ int x; //xpos
1007 
1008  //y-coordinate of the line in the locked rectangle base
1009 
1010  /* unsigned */ int y =( vpMath::round(ip.get_i()) < half_size_ ) ? vpMath::round(ip.get_i()) : half_size_;
1011 
1012  /* unsigned */ int cpt = 0; //number of lines
1013  unsigned int re = thickness; //remaining "width"
1014 
1015  //horizontal lines
1016  //stops when there is enough line for e
1017  while(re!=0)
1018  {
1019  //draws a line
1020  for(x=0; x<(rec.right - rec.left); x++)
1021  setBufferPixel(buf, pitch, x, y, color);
1022 
1023  re--;
1024  cpt++;
1025 
1026  //write alternatively a line at the top and a line at the bottom
1027  //eg : y=4 -> y=5 -> y=3 -> y=6
1028  y += ( (re&1) != 0u) ? cpt : -cpt;
1029  }
1030 
1031  cpt = 0;
1032  re = thickness;
1033 
1034  //x-coordinate of the line in the locked rectangle base
1035  x = ( vpMath::round(ip.get_j()) < half_size_ ) ? vpMath::round(ip.get_j()) : half_size_;
1036 
1037  //vertical lines
1038  while(re!=0)
1039  {
1040  //draws a vertical line
1041  for(y=0; y<rec.bottom - rec.top; y++)
1042  setBufferPixel(buf, pitch, x, y, color);
1043 
1044  re--;
1045  cpt++;
1046 
1047  //write alternatively a line on the left and a line on the right
1048  x += ( (re&1) != 0) ? cpt : -cpt;
1049  }
1050 
1051  //unlocks the texture
1052  if( pd3dText->UnlockRect(0) != D3D_OK)
1053  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
1054  }
1055 }
1056 
1057 
1065 void vpD3DRenderer::drawArrow(const vpImagePoint &ip1,
1066  const vpImagePoint &ip2,
1067  const vpColor &color,
1068  unsigned int w,unsigned int h, unsigned int thickness)
1069 {
1070  double a = ip2.get_i() - ip1.get_i();
1071  double b = ip2.get_j() - ip1.get_j();
1072  double lg = sqrt(vpMath::sqr(a)+vpMath::sqr(b)) ;
1073  int _h = static_cast<int>( h );
1074 
1075  //Will contain the texture's surface drawing context
1076  HDC hDCMem;
1077 
1078  //The texture's surface
1079  IDirect3DSurface9 * pd3dSurf;
1080  pd3dText->GetSurfaceLevel(0, &pd3dSurf);
1081 
1082  //We get its DC
1083  pd3dSurf->GetDC(&hDCMem);
1084 
1085  //create the pen
1086  HPEN hPen;
1087  if (color.id < vpColor::id_unknown)
1088  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colorsGDI[color.id]);
1089  else {
1090  COLORREF gdicolor = RGB(color.R, color.G, color.B);
1091  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
1092  }
1093 
1094  //select the pen
1095  SelectObject(hDCMem, hPen);
1096 
1097  //based on code from other displays
1098  if ((a==0)&&(b==0))
1099  {
1100  // DisplayCrossLarge(i1,j1,3,col) ;
1101  }
1102  else
1103  {
1104  a /= lg ;
1105  b /= lg ;
1106 
1107  vpImagePoint ip3;
1108  ip3.set_i( ip2.get_i() - w*a );
1109  ip3.set_j( ip2.get_j() - w*b );
1110 
1111 
1112  vpImagePoint ip4 ;
1113 
1114  ip4.set_i( ip3.get_i() + b*_h );
1115  ip4.set_j( ip3.get_j() - a*_h );
1116 
1117  MoveToEx(hDCMem, vpMath::round(ip2.get_j()), vpMath::round(ip2.get_i()), NULL);
1118  LineTo(hDCMem, vpMath::round(ip4.get_j()), vpMath::round(ip4.get_i()));
1119 
1120  ip4.set_i( ip3.get_i() - b*h );
1121  ip4.set_j( ip3.get_j() + a*h );
1122 
1123  MoveToEx(hDCMem, vpMath::round(ip2.get_j()), vpMath::round(ip2.get_i()), NULL);
1124  LineTo(hDCMem, vpMath::round(ip4.get_j()), vpMath::round(ip4.get_i()));
1125 
1126  MoveToEx(hDCMem, vpMath::round(ip1.get_j()), vpMath::round(ip1.get_i()), NULL);
1127  LineTo(hDCMem, vpMath::round(ip2.get_j()), vpMath::round(ip2.get_i()));
1128 
1129  }
1130  //Deletes the pen
1131  DeleteObject(hPen);
1132  //Releases the DC
1133  pd3dSurf->ReleaseDC(hDCMem);
1134  //Releases the surface's interface
1135  pd3dSurf->Release();
1136 
1137 
1138 }
1139 
1146 void TextureToRGBa(vpImage<vpRGBa>& I, unsigned char * imBuffer,
1147  unsigned int pitch)
1148 {
1149  unsigned int j = I.getWidth();
1150 
1151  unsigned int k=0;
1152  for(unsigned int i=0; i<I.getHeight()* I.getWidth(); i++)
1153  {
1154  //go to the next line
1155  if(j==0){
1156  k += pitch - (I.getWidth() * 4);
1157  j = I.getWidth();
1158  }
1159 
1160  //simple conversion from bgra to rgba
1161  I.bitmap[i].B = imBuffer[k+0];
1162  I.bitmap[i].G = imBuffer[k+1];
1163  I.bitmap[i].R = imBuffer[k+2];
1164  I.bitmap[i].A = imBuffer[k+3];
1165 
1166  k+=4;
1167  j--;
1168  }
1169 }
1170 
1175 void vpD3DRenderer::getImage(vpImage<vpRGBa> &I)
1176 {
1177  //if the device has been initialized
1178  if(pd3dDevice != NULL)
1179  {
1180 
1181  //resize the destination image as needed
1182  I.resize(nbRows, nbCols);
1183 
1184  D3DLOCKED_RECT d3dLRect;
1185 
1186  RECT r;
1187  r.top = 0;
1188  r.left = 0;
1189  r.bottom = static_cast<LONG>( nbRows );
1190  r.right = static_cast<LONG>( nbCols );
1191 
1192  //locks the whole texture to directly access it
1193  if(pd3dText->LockRect(0, &d3dLRect, &r, 0)!= D3D_OK)
1194  {
1195  vpCERROR<<"D3D : Couldn't lock the texture!"<<std::endl;
1196  return;
1197  }
1198 
1199  //gets the buffer and pitch of the texture
1200  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
1201  unsigned char * buf = (unsigned char *) d3dLRect.pBits;
1202 
1203  //fills this image with the texture's data
1204  TextureToRGBa(I,buf, pitch);
1205 
1206  //unlocks the texture
1207  if( pd3dText->UnlockRect(0) != D3D_OK)
1208  vpCERROR<<"D3D : Couldn't unlock the texture!"<<std::endl;
1209  }
1210 }
1211 
1212 #endif
1213 #endif
void set_j(const double j)
Definition: vpImagePoint.h:156
double get_v() const
Definition: vpImagePoint.h:250
double get_i() const
Definition: vpImagePoint.h:181
unsigned int getWidth() const
Definition: vpImage.h:159
unsigned char B
Blue component.
Definition: vpRGBa.h:155
Type * bitmap
points toward the bitmap
Definition: vpImage.h:120
static const vpColor black
Definition: vpColor.h:161
static const vpColor darkRed
Definition: vpColor.h:168
#define vpCERROR
Definition: vpDebug.h:354
Class to define colors available for display functionnalities.
Definition: vpColor.h:125
double get_u() const
Definition: vpImagePoint.h:239
void resize(const unsigned int height, const unsigned int width)
set the size of the image
Definition: vpImage.h:535
void set_i(const double i)
Definition: vpImagePoint.h:145
static const vpColor lightGray
Definition: vpColor.h:163
static const vpColor darkBlue
Definition: vpColor.h:174
unsigned char G
Green component.
Definition: vpRGBa.h:154
static const vpColor green
Definition: vpColor.h:170
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:192
static const vpColor lightRed
Definition: vpColor.h:166
static const vpColor red
Definition: vpColor.h:167
static const vpColor orange
Definition: vpColor.h:177
vpColorIdentifier id
Definition: vpColor.h:156
static const vpColor cyan
Definition: vpColor.h:176
static const vpColor lightGreen
Definition: vpColor.h:169
static double sqr(double x)
Definition: vpMath.h:106
unsigned char A
Additionnal component.
Definition: vpRGBa.h:156
static const vpColor gray
Definition: vpColor.h:164
static const vpColor darkGray
Definition: vpColor.h:165
Error that can be emited by the vpDisplay class and its derivates.
unsigned char R
Red component.
Definition: vpRGBa.h:153
unsigned int getHeight() const
Definition: vpImage.h:150
static const vpColor darkGreen
Definition: vpColor.h:171
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
static const vpColor yellow
Definition: vpColor.h:175
static const vpColor lightBlue
Definition: vpColor.h:172
static const vpColor purple
Definition: vpColor.h:178
static const vpColor white
Definition: vpColor.h:162
static const vpColor blue
Definition: vpColor.h:173