Visual Servoing Platform  version 3.6.1 under development (2024-04-16)
vpD3DRenderer.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 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 https://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 = nullptr;
77  pd3dDevice = nullptr;
78  pSprite = nullptr;
79  pd3dText = nullptr;
80  pd3dVideoText = nullptr;
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, nullptr);
163 }
164 
169 vpD3DRenderer::~vpD3DRenderer()
170 {
171  DeleteObject(hFont);
172 
173  if (pd3dDevice != nullptr)
174  pd3dDevice->Release();
175  if (pD3D != nullptr)
176  pD3D->Release();
177  if (pd3dText != nullptr)
178  pd3dText->Release();
179  if (pd3dVideoText != nullptr)
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 (nullptr == (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  }
302  else {
303  for (unsigned int i = 0; i < m_rheight; ++i) {
304  unsigned int i_ = i * m_rscale;
305  unsigned int ii_ = i * pitch;
306  for (unsigned int j = 0; j < m_rwidth; ++j) {
307  vpRGBa val = I[i_][j * m_rscale];
308  unsigned int index_ = ii_ + j * 4;
309  imBuffer[index_] = val.B;
310  imBuffer[++index_] = val.G;
311  imBuffer[++index_] = val.R;
312  imBuffer[++index_] = val.A;
313  }
314  }
315  }
316 }
317 
324 void vpD3DRenderer::convert(const vpImage<unsigned char> &I, unsigned char *imBuffer, unsigned int pitch)
325 {
326  if (m_rscale == 1) {
327  for (unsigned int i = 0; i < m_rheight; ++i) {
328  unsigned int ii_ = i * pitch;
329  for (unsigned int j = 0; j < m_rwidth; ++j) {
330  unsigned char val = I[i][j];
331  unsigned int index_ = ii_ + j * 4;
332  imBuffer[index_] = val;
333  imBuffer[++index_] = val;
334  imBuffer[++index_] = val;
335  imBuffer[++index_] = vpRGBa::alpha_default;
336  }
337  }
338  }
339  else {
340  for (unsigned int i = 0; i < m_rheight; ++i) {
341  unsigned int i_ = i * m_rscale;
342  unsigned int ii_ = i * pitch;
343  for (unsigned int j = 0; j < m_rwidth; ++j) {
344  unsigned char val = I[i_][j * m_rscale];
345  unsigned int index_ = ii_ + j * 4;
346  imBuffer[index_] = val;
347  imBuffer[++index_] = val;
348  imBuffer[++index_] = val;
349  imBuffer[++index_] = vpRGBa::alpha_default;
350  }
351  }
352  }
353 }
354 
363 void vpD3DRenderer::convertROI(const vpImage<unsigned char> &I, unsigned char *imBuffer, unsigned int pitch, int i_min,
364  int j_min, int i_max, int j_max)
365 {
366  int h = i_max - i_min;
367  int w = j_max - j_min;
368 
369  if (m_rscale == 1) {
370  for (int i = 0; i < h; ++i) {
371  unsigned int i_ = i_min + i;
372  unsigned int ii_ = i * pitch;
373  for (int j = 0; j < w; ++j) {
374  unsigned char val = I[i_][j_min + j];
375  unsigned int index_ = ii_ + j * 4;
376  imBuffer[index_] = val;
377  imBuffer[++index_] = val;
378  imBuffer[++index_] = val;
379  imBuffer[++index_] = vpRGBa::alpha_default;
380  }
381  }
382  }
383  else {
384  for (int i = 0; i < h; ++i) {
385  unsigned int i_ = (i_min + i) * m_rscale;
386  unsigned int ii_ = i * pitch;
387  for (int j = 0; j < w; ++j) {
388  unsigned char val = I[i_][(j_min + j) * m_rscale];
389  unsigned int index_ = ii_ + j * 4;
390  imBuffer[index_] = val;
391  imBuffer[++index_] = val;
392  imBuffer[++index_] = val;
393  imBuffer[++index_] = vpRGBa::alpha_default;
394  }
395  }
396  }
397 }
398 
407 void vpD3DRenderer::convertROI(const vpImage<vpRGBa> &I, unsigned char *imBuffer, unsigned int pitch, int i_min,
408  int j_min, int i_max, int j_max)
409 {
410  int h = i_max - i_min;
411  int w = j_max - j_min;
412 
413  if (m_rscale == 1) {
414  for (int i = 0; i < h; ++i) {
415  unsigned int i_ = i_min + i;
416  unsigned int ii_ = i * pitch;
417  for (int j = 0; j < w; ++j) {
418  vpRGBa val = I[i_][j_min + j];
419  unsigned int index_ = ii_ + j * 4;
420  imBuffer[index_] = val.B;
421  imBuffer[++index_] = val.G;
422  imBuffer[++index_] = val.R;
423  imBuffer[++index_] = vpRGBa::alpha_default;
424  }
425  }
426  }
427  else {
428  for (int i = 0; i < h; ++i) {
429  unsigned int i_ = (i_min + i) * m_rscale;
430  unsigned int ii_ = i * pitch;
431  for (int j = 0; j < w; ++j) {
432  vpRGBa val = I[i_][(j_min + j) * m_rscale];
433  unsigned int index_ = ii_ + j * 4;
434  imBuffer[index_] = val.B;
435  imBuffer[++index_] = val.G;
436  imBuffer[++index_] = val.R;
437  imBuffer[++index_] = vpRGBa::alpha_default;
438  }
439  }
440  }
441 }
442 
447 void vpD3DRenderer::setImg(const vpImage<vpRGBa> &im)
448 {
449  // if the device has been initialized
450  if (pd3dDevice != nullptr) {
451  D3DLOCKED_RECT d3dLRect;
452 
453  RECT r;
454  r.top = 0;
455  r.left = 0;
456  r.bottom = static_cast<signed long>(m_rheight);
457  r.right = static_cast<signed long>(m_rwidth);
458 
459  // locks the texture to directly access it
460  if (pd3dText->LockRect(0, &d3dLRect, &r, 0) != D3D_OK) {
461  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
462  return;
463  }
464 
465  // gets the buffer and pitch of the texture
466  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
467  unsigned char *buf = (unsigned char *)d3dLRect.pBits;
468 
469  // fills this texture with the image data (converted to bgra)
470  convert(im, buf, pitch);
471 
472  // unlocks the texture
473  if (pd3dText->UnlockRect(0) != D3D_OK)
474  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
475  }
476 }
477 
482 void vpD3DRenderer::setImgROI(const vpImage<vpRGBa> &im, const vpImagePoint &iP, unsigned int width,
483  unsigned int height)
484 {
485  // if the device has been initialized
486  if (pd3dDevice != nullptr) {
487  D3DLOCKED_RECT d3dLRect;
488 
489  int i_min = std::max<int>((int)ceil(iP.get_i() / m_rscale), 0);
490  int j_min = std::max<int>((int)ceil(iP.get_j() / m_rscale), 0);
491  int i_max = std::min<int>((int)ceil((iP.get_i() + height) / m_rscale), (int)m_rheight);
492  int j_max = std::min<int>((int)ceil((iP.get_j() + width) / m_rscale), (int)m_rwidth);
493 
494  RECT r;
495  r.top = (LONG)i_min;
496  r.left = (LONG)j_min;
497  r.bottom = (LONG)i_max;
498  r.right = (LONG)j_max;
499 
500  // locks the texture to directly access it
501  if (pd3dText->LockRect(0, &d3dLRect, &r, 0) != D3D_OK) {
502  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
503  return;
504  }
505 
506  // gets the buffer and pitch of the texture
507  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
508  unsigned char *buf = (unsigned char *)d3dLRect.pBits;
509 
510  // fills this texture with the image data (converted to bgra)
511  convertROI(im, buf, pitch, i_min, j_min, i_max, j_max);
512 
513  // unlocks the texture
514  if (pd3dText->UnlockRect(0) != D3D_OK)
515  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
516  }
517 }
518 
523 void vpD3DRenderer::setImg(const vpImage<unsigned char> &im)
524 {
525  // if the device has been initialized
526  if (pd3dDevice != nullptr) {
527  D3DLOCKED_RECT d3dLRect;
528 
529  RECT r;
530  r.top = 0;
531  r.left = 0;
532  r.bottom = static_cast<LONG>(m_rheight);
533  r.right = static_cast<LONG>(m_rwidth);
534 
535  // locks the texture to directly access it
536  if (pd3dText->LockRect(0, &d3dLRect, &r, 0) != D3D_OK) {
537  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
538  return;
539  }
540 
541  // gets the buffer and pitch of the texture
542  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
543  unsigned char *buf = (unsigned char *)d3dLRect.pBits;
544 
545  // fills this texture with the image data (converted to bgra)
546  convert(im, buf, pitch);
547 
548  // unlocks the texture
549  if (pd3dText->UnlockRect(0) != D3D_OK)
550  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
551  }
552 }
553 
558 void vpD3DRenderer::setImgROI(const vpImage<unsigned char> &im, const vpImagePoint &iP, unsigned int width,
559  unsigned int height)
560 {
561  // if the device has been initialized
562  if (pd3dDevice != nullptr) {
563  D3DLOCKED_RECT d3dLRect;
564 
565  int i_min = std::max<int>((int)ceil(iP.get_i() / m_rscale), 0);
566  int j_min = std::max<int>((int)ceil(iP.get_j() / m_rscale), 0);
567  int i_max = std::min<int>((int)ceil((iP.get_i() + height) / m_rscale), (int)m_rheight);
568  int j_max = std::min<int>((int)ceil((iP.get_j() + width) / m_rscale), (int)m_rwidth);
569 
570  RECT r;
571  r.top = (LONG)i_min;
572  r.left = (LONG)j_min;
573  r.bottom = (LONG)i_max;
574  r.right = (LONG)j_max;
575 
576  // locks the texture to directly access it
577  if (pd3dText->LockRect(0, &d3dLRect, &r, 0) != D3D_OK) {
578  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
579  return;
580  }
581 
582  // gets the buffer and pitch of the texture
583  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
584  unsigned char *buf = (unsigned char *)d3dLRect.pBits;
585 
586  // fills this texture with the image data (converted to bgra)
587  convertROI(im, buf, pitch, i_min, j_min, i_max, j_max);
588 
589  // unlocks the texture
590  if (pd3dText->UnlockRect(0) != D3D_OK)
591  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
592  }
593 }
594 
600 bool vpD3DRenderer::render()
601 {
602  // Clears the back buffer to a blue color
603  // pd3dDevice->Clear( 0, nullptr, D3DCLEAR_TARGET,
604  // D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
605 
606  // Begins the scene.
607  pd3dDevice->BeginScene();
608 
609  // Texture rectangle to display
610  RECT r;
611  r.top = 0;
612  r.left = 0;
613  r.bottom = static_cast<LONG>(m_rheight);
614  r.right = static_cast<LONG>(m_rwidth);
615 
616  // Updates the video memory texture with the content of the system
617  // memory texture
618  pd3dDevice->UpdateTexture(pd3dText, pd3dVideoText);
619 
620  // Displays this texture as a sprite
621 
622 #if (D3DX_SDK_VERSION <= 9)
623  pSprite->Begin(); //
624  pSprite->Draw(pd3dVideoText, &r, nullptr, nullptr, nullptr, nullptr, 0xFFFFFFFF);
625 #else
626  pSprite->Begin(0);
627  pSprite->Draw(pd3dVideoText, &r, nullptr, nullptr, 0xFFFFFFFF);
628 #endif
629  pSprite->End();
630 
631  // Ends the scene.
632  pd3dDevice->EndScene();
633  // Presents the backbuffer
634  pd3dDevice->Present(nullptr, nullptr, nullptr, nullptr);
635 
636  return true;
637 }
638 
645 void vpD3DRenderer::setPixel(const vpImagePoint &iP, const vpColor &color)
646 {
647  vpImagePoint iPscaled = iP / m_rscale;
648  if (iPscaled.get_i() < 0 || iPscaled.get_j() < 0 || iPscaled.get_i() >= (int)m_rheight ||
649  iPscaled.get_j() >= (int)m_rwidth) {
650  return;
651  }
652 
653  // if the device has been initialized
654  if (pd3dDevice != nullptr) {
655  D3DLOCKED_RECT d3dLRect;
656 
657  RECT r;
658 
659  r.top = (LONG)iPscaled.get_i();
660  r.left = (LONG)iPscaled.get_j();
661  r.bottom = (LONG)iPscaled.get_i() + 1;
662  r.right = (LONG)iPscaled.get_j() + 1;
663 
664  // locks the texture to directly access it
665  if (pd3dText->LockRect(0, &d3dLRect, &r, 0) != D3D_OK) {
666  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
667  return;
668  }
669 
670  // gets the buffer and pitch of the texture
671  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
672  unsigned char *buf = (unsigned char *)d3dLRect.pBits;
673 
674  // the coordinates are in the locked area base
675  setBufferPixel(buf, pitch, 0, 0, color);
676 
677  // unlocks the texture
678  if (pd3dText->UnlockRect(0) != D3D_OK)
679  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
680  }
681 }
682 
690 void vpD3DRenderer::drawLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
691  unsigned int thickness, int style)
692 {
693  // if the device has been initialized
694  if (pd3dDevice != nullptr) {
695  // Will contain the texture's surface drawing context
696  HDC hDCMem;
697 
698  // The texture's surface
699  IDirect3DSurface9 *pd3dSurf;
700  pd3dText->GetSurfaceLevel(0, &pd3dSurf);
701 
702  // We get its DC
703  pd3dSurf->GetDC(&hDCMem);
704 
705  // create the pen
706  HPEN hPen;
707  if (color.id < vpColor::id_unknown)
708  hPen = CreatePen(style, static_cast<int>(thickness), colorsGDI[color.id]);
709  else {
710  COLORREF gdicolor = RGB(color.R, color.G, color.B);
711  hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
712  }
713 
714  // we don't use the bkColor
715  SetBkMode(hDCMem, TRANSPARENT);
716 
717  // select the pen
718  SelectObject(hDCMem, hPen);
719 
720  // Warning: When thickness > 1 and pen style is PS_DASHDOT, the drawing
721  // displays a solid line That's why in that case we implement the dashdot
722  // line manually drawing multiple small lines
723  if (thickness != 1 && style != PS_SOLID) {
724  vpImagePoint ip1_ = ip1;
725  vpImagePoint ip2_ = ip2;
726 
727  double size = 10. * m_rscale;
728  double length = sqrt(vpMath::sqr(ip2_.get_i() - ip1_.get_i()) + vpMath::sqr(ip2_.get_j() - ip1_.get_j()));
729  bool vertical_line = (int)ip2_.get_j() == (int)ip1_.get_j();
730  if (vertical_line) {
731  if (ip2_.get_i() < ip1_.get_i()) {
732  std::swap(ip1_, ip2_);
733  }
734  }
735  else if (ip2_.get_j() < ip1_.get_j()) {
736  std::swap(ip1_, ip2_);
737  }
738 
739  double diff_j = vertical_line ? 1 : ip2_.get_j() - ip1_.get_j();
740  double deltaj = size / length * diff_j;
741  double deltai = size / length * (ip2_.get_i() - ip1_.get_i());
742  double slope = (ip2_.get_i() - ip1_.get_i()) / diff_j;
743  double orig = ip1_.get_i() - slope * ip1_.get_j();
744 
745  if (vertical_line) {
746  for (unsigned int i = (unsigned int)ip1_.get_i(); i < ip2_.get_i(); i += (unsigned int)(2 * deltai)) {
747  double j = ip1_.get_j();
748 
749  // Move to the starting point
750  MoveToEx(hDCMem, vpMath::round(j / m_rscale), vpMath::round(i / m_rscale), nullptr);
751  // Draw the line
752  LineTo(hDCMem, vpMath::round(j / m_rscale), vpMath::round((i + deltai) / m_rscale));
753  }
754  }
755  else {
756  for (unsigned int j = (unsigned int)ip1_.get_j(); j < ip2_.get_j(); j += (unsigned int)(2 * deltaj)) {
757  double i = slope * j + orig;
758  // Move to the starting point
759  MoveToEx(hDCMem, vpMath::round(j / m_rscale), vpMath::round(i / m_rscale), nullptr);
760  // Draw the line
761  LineTo(hDCMem, vpMath::round((j + deltaj) / m_rscale), vpMath::round((i + deltai) / m_rscale));
762  }
763  }
764  }
765  else {
766  // move to the starting point
767  MoveToEx(hDCMem, vpMath::round(ip1.get_u() / m_rscale), vpMath::round(ip1.get_v() / m_rscale), nullptr);
768  // Draw the line
769  LineTo(hDCMem, vpMath::round(ip2.get_u() / m_rscale), vpMath::round(ip2.get_v() / m_rscale));
770  }
771 
772  // Releases the DC
773  pd3dSurf->ReleaseDC(hDCMem);
774  // Releases the surface's interface
775  pd3dSurf->Release();
776  // Deletes additional objects
777  DeleteObject(hPen);
778  }
779 }
780 
790 void vpD3DRenderer::drawRect(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color,
791  bool fill, unsigned int thickness)
792 {
793  // if the device has been initialized
794  if (pd3dDevice != nullptr) {
795  if (fill == false) {
796  drawLine(topLeft, topLeft + vpImagePoint(0, width), color, thickness);
797  drawLine(topLeft + vpImagePoint(0, width), topLeft + vpImagePoint(height, width), color, thickness);
798  drawLine(topLeft + vpImagePoint(height, width), topLeft + vpImagePoint(height, 0), color, thickness);
799  drawLine(topLeft + vpImagePoint(height, 0), topLeft, color, thickness);
800  }
801  else {
802  vpImagePoint topLeftScaled = topLeft / m_rscale;
803  unsigned int widthScaled = width / m_rscale;
804  unsigned int heightScaled = height / m_rscale;
805 
806  if (topLeftScaled.get_i() > (int)m_rheight - 1 || topLeftScaled.get_j() > (int)m_rwidth - 1 ||
807  topLeftScaled.get_i() + height < 0 || topLeftScaled.get_j() + width < 0) {
808  // vpCERROR<<"Invalid parameters!"<<std::endl;
809  return;
810  }
811 
812  D3DLOCKED_RECT d3dLRect;
813 
814  RECT r;
815  r.top = (LONG)((topLeftScaled.get_i() > 0) ? topLeftScaled.get_i() : 0);
816  r.left = (LONG)((topLeftScaled.get_j() > 0) ? topLeftScaled.get_j() : 0);
817  r.bottom = (LONG)((topLeftScaled.get_i() + heightScaled < (int)m_rheight) ? topLeftScaled.get_i() + heightScaled
818  : m_rheight - 1);
819  r.right = (LONG)((topLeftScaled.get_j() + widthScaled < (int)m_rwidth) ? topLeftScaled.get_j() + widthScaled
820  : m_rwidth - 1);
821 
822  /* unsigned */ int rectW = r.right - r.left;
823  /* unsigned */ int rectH = r.bottom - r.top;
824 
825  // locks the texture to directly access it
826  if (pd3dText->LockRect(0, &d3dLRect, &r, 0) != D3D_OK) {
827  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
828  return;
829  }
830 
831  // gets the buffer and pitch of the texture
832  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
833  unsigned char *buf = (unsigned char *)d3dLRect.pBits;
834 
835  if (topLeftScaled.get_i() >= 0 && topLeftScaled.get_j() + widthScaled < m_rwidth &&
836  topLeftScaled.get_i() + heightScaled < m_rheight && topLeftScaled.get_j() >= 0) {
837  for (int x = 0; x < rectW; ++x) {
838  for (int y = 0; y < rectH; ++y)
839  setBufferPixel(buf, pitch, x, y, color);
840  }
841  }
842 
843  // unlocks the texture
844  if (pd3dText->UnlockRect(0) != D3D_OK)
845  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
846  }
847  }
848 }
849 
854 void vpD3DRenderer::clear(const vpColor &color)
855 {
856  // if the device has been initialized
857  if (pd3dDevice != nullptr) {
858  D3DLOCKED_RECT d3dLRect;
859 
860  RECT r;
861  r.top = 0;
862  r.left = 0;
863  r.bottom = static_cast<LONG>(m_rheight);
864  r.right = static_cast<LONG>(m_rwidth);
865 
866  // locks the texture to directly access it
867  if (pd3dText->LockRect(0, &d3dLRect, &r, 0) != D3D_OK) {
868  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
869  return;
870  }
871 
872  // gets the buffer and pitch of the texture
873  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
874  long *buf = (long *)(d3dLRect.pBits);
875 
876  unsigned long c;
877  if (color.id < vpColor::id_unknown)
878  c = colors[color.id];
879  else {
880  c = D3DCOLOR_ARGB(0xFF, color.R, color.G, color.B);
881  }
882  long *end = (long *)(buf + (pitch * m_rheight));
883 
884  // fills the whole image
885  while (buf < end)
886  *buf++ = static_cast<long>(c);
887 
888  // unlocks the texture
889  if (pd3dText->UnlockRect(0) != D3D_OK)
890  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
891  }
892 }
893 
894 // writes current circle pixels using symetry to reduce the algorithm's
895 // complexity
896 void vpD3DRenderer::subDrawCircle(int i, int j, int x, int y, vpColor col, unsigned char *buf, unsigned int pitch,
897  unsigned int maxX, unsigned int maxY)
898 {
899  if (x == 0) {
900  setBufferPixel(buf, pitch, i, j + y, col, maxX, maxY);
901  setBufferPixel(buf, pitch, i, j - y, col, maxX, maxY);
902  setBufferPixel(buf, pitch, i + y, j, col, maxX, maxY);
903  setBufferPixel(buf, pitch, i - y, j, col, maxX, maxY);
904  }
905  else if (x == y) {
906  setBufferPixel(buf, pitch, i + x, j + y, col, maxX, maxY);
907  setBufferPixel(buf, pitch, i - x, j + y, col, maxX, maxY);
908  setBufferPixel(buf, pitch, i + x, j - y, col, maxX, maxY);
909  setBufferPixel(buf, pitch, i - x, j - y, col, maxX, maxY);
910  }
911  else if (x < y) {
912  setBufferPixel(buf, pitch, i + x, j + y, col, maxX, maxY);
913  setBufferPixel(buf, pitch, i - x, j + y, col, maxX, maxY);
914  setBufferPixel(buf, pitch, i + x, j - y, col, maxX, maxY);
915  setBufferPixel(buf, pitch, i - x, j - y, col, maxX, maxY);
916  setBufferPixel(buf, pitch, i + y, j + x, col, maxX, maxY);
917  setBufferPixel(buf, pitch, i - y, j + x, col, maxX, maxY);
918  setBufferPixel(buf, pitch, i + y, j - x, col, maxX, maxY);
919  setBufferPixel(buf, pitch, i - y, j - x, col, maxX, maxY);
920  }
921 }
922 
929 void vpD3DRenderer::drawCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool /*fill*/,
930  unsigned int /*thickness*/)
931 {
932  unsigned int radiusScaled = radius / m_rscale;
933  vpImagePoint centerScaled = center / m_rscale;
934  if (radiusScaled < 1 || vpMath::round(centerScaled.get_i() + radiusScaled) < 0 ||
935  vpMath::round(centerScaled.get_i() - radiusScaled) > (int)m_rheight ||
936  vpMath::round(centerScaled.get_j() + radiusScaled) < 0 ||
937  vpMath::round(centerScaled.get_j() - radiusScaled) > (int)m_rwidth)
938  return;
939 
940  // if the device has been initialized
941  if (pd3dDevice != nullptr) {
942  D3DLOCKED_RECT d3dLRect;
943 
944  RECT rec;
945  int radiusScaled_ = static_cast<int>(radiusScaled);
946  int rleft = (vpMath::round(centerScaled.get_j() - radiusScaled_) > 0)
947  ? vpMath::round(centerScaled.get_j()) - radiusScaled_
948  : 0;
949  int rtop = (vpMath::round(centerScaled.get_i() - radiusScaled_) > 0)
950  ? vpMath::round(centerScaled.get_i()) - radiusScaled_
951  : 0;
952 
953  rec.top = rtop;
954  rec.left = rleft;
955  rec.bottom = (LONG)((vpMath::round(centerScaled.get_i() + radiusScaled_) < (int)m_rheight)
956  ? centerScaled.get_i() + radiusScaled_
957  : m_rheight - 1);
958  rec.right = (LONG)((vpMath::round(centerScaled.get_j() + radiusScaled_) < (int)m_rwidth)
959  ? centerScaled.get_j() + radiusScaled_
960  : m_rwidth - 1);
961 
962  // used as maxX and maxY for setBufferPixel
963  unsigned int rectW = static_cast<unsigned int>(rec.right - rleft);
964  unsigned int rectH = static_cast<unsigned int>(rec.bottom - rtop);
965 
966  // locks the texture to directly access it
967  if (pd3dText->LockRect(0, &d3dLRect, &rec, 0) != D3D_OK) {
968  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
969  return;
970  }
971 
972  // gets the buffer and pitch of the texture
973  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
974  unsigned char *buf = (unsigned char *)d3dLRect.pBits;
975 
976  // Bresenham 's circle algorithm
977 
978  int x = 0;
979  int y = static_cast<int>(radiusScaled);
980  int p = (3 - (y << 1));
981 
982  vpImagePoint ip;
983  ip.set_i(centerScaled.get_i() - rtop);
984  ip.set_j(centerScaled.get_j() - rleft);
985 
986  subDrawCircle(vpMath::round(ip.get_i()), vpMath::round(ip.get_j()), x, y, color, buf, pitch, rectW, rectH);
987  while (x < y) {
988  x++;
989  if (p < 0) {
990  p += ((x << 1) + 1) << 1;
991  }
992  else {
993  y--;
994  p += (((x - y) << 1) + 1) << 1;
995  }
996  subDrawCircle(vpMath::round(ip.get_i()), vpMath::round(ip.get_j()), x, y, color, buf, pitch, rectW, rectH);
997  }
998 
999  // unlocks the texture
1000  if (pd3dText->UnlockRect(0) != D3D_OK)
1001  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
1002  }
1003 }
1004 
1011 void vpD3DRenderer::drawText(const vpImagePoint &ip, const char *text, const vpColor &color)
1012 {
1013  // Will contain the texture's surface drawing context
1014  HDC hDCMem;
1015 
1016  // The texture's surface
1017  IDirect3DSurface9 *pd3dSurf;
1018  pd3dText->GetSurfaceLevel(0, &pd3dSurf);
1019 
1020  // We get its DC
1021  pd3dSurf->GetDC(&hDCMem);
1022 
1023  // Select the font
1024  SelectObject(hDCMem, hFont);
1025 
1026  // set the text color
1027  if (color.id < vpColor::id_unknown)
1028  SetTextColor(hDCMem, colorsGDI[color.id]);
1029  else {
1030  COLORREF gdicolor = RGB(color.R, color.G, color.B);
1031  SetTextColor(hDCMem, gdicolor);
1032  }
1033 
1034  // we don't use the bkColor
1035  SetBkMode(hDCMem, TRANSPARENT);
1036 
1037  SIZE size;
1038  int length = (int)strlen(text);
1039 
1040  // get the displayed string dimensions
1041  GetTextExtentPoint32(hDCMem, text, length, &size);
1042 
1043  // displays the string
1044  TextOut(hDCMem, vpMath::round(ip.get_u() / m_rscale), vpMath::round(ip.get_v() / m_rscale), text, length);
1045 
1046  // Releases the DC
1047  pd3dSurf->ReleaseDC(hDCMem);
1048  // Releases the surface's interface
1049  pd3dSurf->Release();
1050  // Deletes additional objects
1051  DeleteObject(hFont);
1052 }
1053 
1061 void vpD3DRenderer::drawCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness)
1062 {
1063  double i = ip.get_i();
1064  double j = ip.get_j();
1065  vpImagePoint ip1, ip2;
1066 
1067  ip1.set_i(i - size / 2);
1068  ip1.set_j(j);
1069  ip2.set_i(i + size / 2);
1070  ip2.set_j(j);
1071  drawLine(ip1, ip2, color, thickness);
1072 
1073  ip1.set_i(i);
1074  ip1.set_j(j - size / 2);
1075  ip2.set_i(i);
1076  ip2.set_j(j + size / 2);
1077 
1078  drawLine(ip1, ip2, color, thickness);
1079 }
1080 
1088 void vpD3DRenderer::drawArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int w,
1089  unsigned int h, unsigned int thickness)
1090 {
1091  double a = ip2.get_i() - ip1.get_i();
1092  double b = ip2.get_j() - ip1.get_j();
1093  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
1094 
1095  // if ( ( a==0 ) && ( b==0 ) )
1096  if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
1097  (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
1098  // DisplayCrossLarge(i1,j1,3,col) ;
1099  }
1100  else {
1101  a /= lg;
1102  b /= lg;
1103 
1104  vpImagePoint ip3;
1105  ip3.set_i(ip2.get_i() - w * a);
1106  ip3.set_j(ip2.get_j() - w * b);
1107 
1108  vpImagePoint ip4;
1109  ip4.set_i(ip3.get_i() - b * h);
1110  ip4.set_j(ip3.get_j() + a * h);
1111 
1112  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1113  drawLine(ip2, ip4, color, thickness);
1114 
1115  ip4.set_i(ip3.get_i() + b * h);
1116  ip4.set_j(ip3.get_j() - a * h);
1117 
1118  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1119  drawLine(ip2, ip4, color, thickness);
1120 
1121  drawLine(ip1, ip2, color, thickness);
1122  }
1123 }
1124 
1131 void TextureToRGBa(vpImage<vpRGBa> &I, unsigned char *imBuffer, unsigned int pitch)
1132 {
1133  unsigned int j = I.getWidth();
1134 
1135  unsigned int k = 0;
1136  for (unsigned int i = 0; i < I.getHeight() * I.getWidth(); ++i) {
1137  // go to the next line
1138  if (j == 0) {
1139  k += pitch - (I.getWidth() * 4);
1140  j = I.getWidth();
1141  }
1142 
1143  // simple conversion from bgra to rgba
1144  I.bitmap[i].B = imBuffer[k + 0];
1145  I.bitmap[i].G = imBuffer[k + 1];
1146  I.bitmap[i].R = imBuffer[k + 2];
1147  I.bitmap[i].A = imBuffer[k + 3];
1148 
1149  k += 4;
1150  j--;
1151  }
1152 }
1153 
1158 void vpD3DRenderer::getImage(vpImage<vpRGBa> &I)
1159 {
1160  // if the device has been initialized
1161  if (pd3dDevice != nullptr) {
1162 
1163  // resize the destination image as needed
1164  I.resize(m_rheight, m_rwidth);
1165 
1166  D3DLOCKED_RECT d3dLRect;
1167 
1168  RECT r;
1169  r.top = 0;
1170  r.left = 0;
1171  r.bottom = static_cast<LONG>(m_rheight);
1172  r.right = static_cast<LONG>(m_rwidth);
1173 
1174  // locks the whole texture to directly access it
1175  if (pd3dText->LockRect(0, &d3dLRect, &r, 0) != D3D_OK) {
1176  vpCERROR << "D3D : Couldn't lock the texture!" << std::endl;
1177  return;
1178  }
1179 
1180  // gets the buffer and pitch of the texture
1181  unsigned int pitch = static_cast<unsigned int>(d3dLRect.Pitch);
1182  unsigned char *buf = (unsigned char *)d3dLRect.pBits;
1183 
1184  // fills this image with the texture's data
1185  TextureToRGBa(I, buf, pitch);
1186 
1187  // unlocks the texture
1188  if (pd3dText->UnlockRect(0) != D3D_OK)
1189  vpCERROR << "D3D : Couldn't unlock the texture!" << std::endl;
1190  }
1191 }
1192 
1193 #elif !defined(VISP_BUILD_SHARED_LIBS)
1194 // Work around to avoid warning: libvisp_core.a(vpD3DRenderer.cpp.o) has no symbols
1195 void dummy_vpD3DRenderer() { };
1196 #endif
1197 #endif
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:152
static const vpColor white
Definition: vpColor.h:206
vpColorIdentifier id
Definition: vpColor.h:200
static const vpColor red
Definition: vpColor.h:211
static const vpColor darkGray
Definition: vpColor.h:209
static const vpColor black
Definition: vpColor.h:205
static const vpColor cyan
Definition: vpColor.h:220
static const vpColor orange
Definition: vpColor.h:221
static const vpColor darkRed
Definition: vpColor.h:212
static const vpColor blue
Definition: vpColor.h:217
static const vpColor lightGray
Definition: vpColor.h:207
static const vpColor lightBlue
Definition: vpColor.h:216
static const vpColor darkGreen
Definition: vpColor.h:215
static const vpColor darkBlue
Definition: vpColor.h:218
static const vpColor purple
Definition: vpColor.h:222
static const vpColor lightGreen
Definition: vpColor.h:213
static const vpColor yellow
Definition: vpColor.h:219
@ id_lightBlue
Definition: vpColor.h:178
@ id_yellow
Definition: vpColor.h:184
@ id_darkGray
Definition: vpColor.h:164
@ id_green
Definition: vpColor.h:174
@ id_darkRed
Definition: vpColor.h:170
@ id_lightGray
Definition: vpColor.h:160
@ id_red
Definition: vpColor.h:168
@ id_lightRed
Definition: vpColor.h:166
@ id_white
Definition: vpColor.h:158
@ id_black
Definition: vpColor.h:156
@ id_blue
Definition: vpColor.h:180
@ id_darkGreen
Definition: vpColor.h:176
@ id_gray
Definition: vpColor.h:162
@ id_lightGreen
Definition: vpColor.h:172
@ id_purple
Definition: vpColor.h:190
@ id_orange
Definition: vpColor.h:188
@ id_cyan
Definition: vpColor.h:186
@ id_darkBlue
Definition: vpColor.h:182
@ id_unknown
Definition: vpColor.h:193
static const vpColor lightRed
Definition: vpColor.h:210
static const vpColor green
Definition: vpColor.h:214
static const vpColor gray
Definition: vpColor.h:208
Error that can be emitted by the vpDisplay class and its derivatives.
@ notInitializedError
Display not initialized.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:304
double get_j() const
Definition: vpImagePoint.h:125
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_i(double ii)
Definition: vpImagePoint.h:293
double get_u() const
Definition: vpImagePoint.h:136
double get_i() const
Definition: vpImagePoint.h:114
double get_v() const
Definition: vpImagePoint.h:147
unsigned int getWidth() const
Definition: vpImage.h:245
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:783
Type * bitmap
points toward the bitmap
Definition: vpImage.h:139
unsigned int getHeight() const
Definition: vpImage.h:184
static double sqr(double x)
Definition: vpMath.h:201
static int round(double x)
Definition: vpMath.h:403
Definition: vpRGBa.h:61
unsigned char B
Blue component.
Definition: vpRGBa.h:139
unsigned char R
Red component.
Definition: vpRGBa.h:137
unsigned char G
Green component.
Definition: vpRGBa.h:138
@ alpha_default
Definition: vpRGBa.h:63
unsigned char A
Additionnal component.
Definition: vpRGBa.h:140
#define vpCERROR
Definition: vpDebug.h:356