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