OpenGL Tag Cloud

Source: Internet
Author: User

Tag Cloud was first recognized at the end of last year. I was particularly interested in seeing this application. I still remember thinking when I was working on a mobile app in Beijing in, is it possible to expand the interface in some way so that the relatively small mobile phone screen can only display the valid part, the extended part can be moved out of the screen in some way to the screen. Later, it was confirmed that the people who thought about this kind of thinking were not just myself, because the screen selection application is now the basic application mode of mobile terminals. At that time, I also wondered if I could extend the interface vertically so that the interface could go deep into the screen. I wanted to know that it was an infinite space, but I didn't think of any good way. When I saw the tag cloud, I knew this was what I wanted. So I decided to use OpenGL to simulate it and discuss it with everyone, see if it is possible to make a more mature application. However, the work was busy when I came back from the Chinese New Year, so I put it on hold. A project has just been completed in the past two days, so you can write this blog.
To implement the function, we need to analyze the principle first. Through the use and observation, I think every label in the tag cloud is distributed on a sphere, and the projection of the ball on the video plane is a circle, the whole ball rotates Based on the positional relationship between the mouse and the projection circle. The farther the mouse is from the center, the slower the speed. The sphere is rotated around a rotating shaft that passes through the ball center and is parallel to the video plane. The relationship between the mouse and the position of the projected circle center also controls the direction of the rotating shaft, that is, the link between the pivot axis and the projection circle center and the mouse. Finally, the rotation always starts with the mouse.
Now that we know the basic principles, we need to start analyzing the algorithm. We don't have to say that we can use OpenGL to implement 3D space, I have written an article titled OpenGL control, which introduces a custom control with built-in OpenGL basic framework. This is an extension application based on this control. I also introduced a Vector class cvector I wrote in my article "3D vector class". Of course, this modeling still depends on it. The only problem is that OpenGL does not support Chinese. Is there any way to conveniently display Chinese? The method I used here is to generate a text texture in the memory, and then assign a plan in Alpha hybrid mode, in this way, you can use the system font library to display various types of text in OpenGL. All right, the main problem is solved, and the code is written.
First, define a struct to represent a tag in the tag element:

Typedef structtagtagnode {cvectorm_vtrpos; // tag position floatm_fwidth, // Tag Length m_fheight; // tag width uintm_utexture; // texture number} cloudtag, * lpcloudtag;

Then, maintain a cloudtag array in copenglctrl to manage all labels, that is, the entire cloud. The addcloud function is used to add a tag. The Code is as follows:

Void copenglctrl: addcloud (cstring strname, colorref clrtext, cstring strfontname, int npointsize, int nweight, uint ucharset) {intnmode; plaintext; crectrecttag; tags, * poldbitmap; plaintext, * poldfont; colorrefclrold; logfontlf; CDC * PDC = getdc (); CDC * pmemdc = new CDC; lpcloudtagpcloudtag = new cloudtag; intnextend = 5; floatftemp; // set the font memset (& lf, 0, sizeof (logfont); // set the font style wcscpy_s (LF. lffa CENAME, strfontname); LF. lfheight = npointsize; LF. lfweight = nweight; LF. lfcharset = ucharset; fonttag. createfontindirect (& lf); // create a bitmap memory pmemdc-> createcompatibledc (PDC); poldfont = pmemdc-> SelectObject (& fonttag); nmode = pmemdc-> setbkmode (transparent ); clrold = pmemdc-> settextcolor (clrtext); sizetext = pmemdc-> gettextextent (strname, strname. getlength (); pcloudtag-> m_fwidth = float (sizetext. cx + nextend)/40; pcloud Tag-> m_fheight = float (sizetext. cy + nextend)/40; recttag. setrect (0, 0, sizetext. cx + nextend, sizetext. cy + nextend); bitmaptemp. createcompatiblebitmap (PDC, recttag. width (), recttag. height (); poldbitmap = pmemdc-> SelectObject (& bitmaptemp); // fill the pmemdc-> drawtext (strname, strname. getlength (), recttag, dt_singleline | dt_center | dt_vcenter); pmemdc-> setbkmode (nmode); pmemdc-> SelectObject (poldfont); pmemdc-> selecto Bject (poldbitmap); pmemdc-> settextcolor (clrold); deletepmemdc; bitmapbmdata; bitmaptemp. getbitmap (& bmdata); unsigned char * pdata = new unsigned char [bmdata. bmwidthbytes * bmdata. bmheight]; bitmaptemp. getbitmapbits (bmdata. bmwidthbytes * bmdata. bmheight, pdata); For (INT I = 0; I <bmdata. bmwidth; I ++) {for (Int J = 0; j <bmdata. bmheight; j ++) {If (pdata [I * 4 + J * bmdata. bmwidthbytes]! = 0 | pdata [I * 4 + J * bmdata. bmwidthbytes + 1]! = 0 | pdata [I * 4 + J * bmdata. bmwidthbytes + 2]! = 0) pdata [I * 4 + J * bmdata. bmwidthbytes + 3] = 255 ;}} glgentextures (1, & pcloudtag-> m_utexture); glbindtexture (dependencies, pcloudtag-> m_utexture); glubuild2dmipmaps (outputs, 4, bmdata. bmwidth, bmdata. bmheight, gl_rgba, gl_unsigned_byte, pdata); deletepdata; ftemp = (RAND () % 50)/10.0f + 3; pcloudtag-> m_vtrpos = cvector (0, 0, ftemp ); ftemp = (RAND () % 360-180)/360.0f; pcloudtag-> m_vtrpos.rotate (ftemp, cvector (1, 0, 0); ftemp = (RAND () % 360-180)/360.0f; pcloudtag-> m_vtrpos.rotate (ftemp, cvector (0, 1, 0); ftemp = (RAND () % 360-180)/360.0f; pcloudtag-> m_vtrpos.rotate (ftemp, cvector (0, 0, 1); m_tcdemo.add (pcloudtag );}

This function is the core function used to generate tags. In a program, tags are represented in text. Therefore, functions support almost all customization of text, this includes content, color, Font, font size, and style. The function first creates a font, and then creates a memory bitmap based on the size required by the text content to draw the text on the bitmap. Prepare a text bitmap and use it to make materials. The problem is that there is no alpha channel in the bitmap. What should I do? Is there a relatively simple way to deal with it? Here, my processing method is like this. Look at the code, get bitmap information through getbitmap, and then observe the values of bmdata. bmwidth and bmdata. bmwidthbytes. We can find that bmwidthbytes is four times that of bmwidth. Previously, bitmap is stored as rgba in the memory, so the data obtained through getbitmapbits is 4 bits. As we all know, the memory bitmap is black when it is created. Here I believe that the label text cannot be black. Therefore, if the detection data is black, set Alpha to transparent. If not, set it to opaque, then create a texture. Finally, we set the vector and randomly generate a length in a range to make a vector pointing to the outside of the screen. Then, we randomly rotate an angle on the X, Y, and Z axes, this completes the modeling of a tag.
The rendering part is simple, that is, the general OpenGL rendering, but the material is added with Alpha transparency. In fact, this demo is rough, and there is a black edge around the text. However, this example is not especially intended for performance, so it is not specially processed. The Code is as follows:

Void copenglctrl: onpaint () {cpaintdcdc (this); // paint the background color colorrefclrbkgnd = getsyscolor (color_btnface); glclearcolor (float (getrvalue (clrbkgnd)/255, float (getgvalue (clrbkgnd)/255, float (getbvalue (clrbkgnd)/255, 0.0f); glclear (gl_color_buffer_bit | percent); // you can specify the scenario coordinate system glloadidentity (); // set the observation point glulookat (0, 0, 30, 0, 0, 0, 0, 1, 0); int_ptrncount = m_tcdemo.getcount (); For (INT I = 0; I <ncount; I ++) {records = records (I); glbindtexture (records, pcloudtag-> m_utexture); glable (gl_blend); glable (gl_alpha_test); glalphafunc (gl_greater, 0.1f); glbegin (gl_quads); gltexcoord2i (0, 0), glvertex3f (pcloudtag-> m_vtrPos.m_fVectorX-pCloudTag-> m_fwidth/2, pcloudtag-> signature + pcloudtag-> m_fheight/2, pcloudtag-> signature); gltexcoord2i (1, 0), glvertex3f (pcloudtag-> signature + pcloudtag-> m_fwidth/2, pcloudtag-> signature + pcloudtag-> m_fheight/2, pcloudtag-> signature); gltexcoord2i (1, 1), glvertex3f (pcloudtag-> signature + pcloudtag-> m_fwidth/2, pcloudtag-> m_vtrPos.m_fVectorY-pCloudTag-> m_fheight/2, pcloudtag-> m_vtrpos.m_fvectorz); gltexcoord2i (0, 1), glvertex3f (pcloudtag-> m_vtrPos.m_fVectorX-pCloudTag-> m_fwidth/2, pcloudtag-> m_vtrPos.m_fVectorY-pCloudTag-> m_fheight/2, pcloudtag-> m_vtrpos.m_fvectorz); glend (); gldisable (gl_alpha_test); gldisable (gl_blend);} // flip swapbuffers (m_pdc-> m_hdc );}

The rest is the implementation of mouse control and animation. Because my Vector class supports the rotation function, and tag cloud modeling is implemented through vectors, this step is easy to say. All labels are located by the vector starting from the origin, so the axis is also the vector on the XOZ surface through the origin. Calculate the state and speed in onmousehover, and then rotate the vector of each label in ontimer. The Code is as follows:

LRESULT COpenGLCtrl::OnMouseHover(WPARAM wParam, LPARAM lParam){CRectrectView;CPointpoint;GetWindowRect(rectView);GetCursorPos(&point);m_vtrRotate.SetVector(float(-point.x), float(point.y), 0, -float(rectView.right+rectView.left)/2, float(rectView.bottom+rectView.top)/2, 0);m_vtrRotate.Rotate(-PI/2, CVector(0, 0, 1));m_fAngle= m_vtrRotate.GetMod()/2000;return 1;}

void COpenGLCtrl::OnTimer(UINT_PTR nIDEvent){switch(nIDEvent){case TIMER_MOVE:{if(m_fAngle==0)return;INT_PTRnCount= m_tcDemo.GetCount();for(int i=0; i<nCount; i++){lpCloudTagpCloudTag= m_tcDemo.GetAt(i);pCloudTag->m_vtrPos.Rotate(m_fAngle, m_vtrRotate);Invalidate();}}break;}CWnd::OnTimer(nIDEvent);}

All the basic functions have been implemented by now. If you are interested in uploading this demo to my resources, you can download the demo and study it. If you have any good ideas, please contact me further. To write this article, I hope to give you some inspiration and create a better user experience Interface Design from a three-dimensional perspective. The last one is a smile.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.