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