1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail    : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include <math.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <cairo.h>
24 
25 #include "cairo-dock-draw-opengl.h"
26 #include "cairo-dock-particle-system.h"
27 
28 static GLfloat s_pCornerCoords[8] = {0.0, 0.0,
29 	0.0, 1.0,
30 	1.0, 1.0,
31 	1.0, 0.0};
32 
cairo_dock_render_particles_full(CairoParticleSystem * pParticleSystem,int iDepth)33 void cairo_dock_render_particles_full (CairoParticleSystem *pParticleSystem, int iDepth)
34 {
35 	_cairo_dock_enable_texture ();
36 
37 	if (pParticleSystem->bAddLuminance)
38 		_cairo_dock_set_blend_over ();
39 		//glBlendFunc (GL_SRC_ALPHA, GL_ONE);
40 	else
41 		_cairo_dock_set_blend_alpha ();
42 
43 	glBindTexture(GL_TEXTURE_2D, pParticleSystem->iTexture);
44 
45 	GLfloat *vertices = pParticleSystem->pVertices;
46 	///GLfloat *coords = pParticleSystem->pCoords;
47 	GLfloat *colors = pParticleSystem->pColors;
48 	GLfloat *vertices2 = &pParticleSystem->pVertices[pParticleSystem->iNbParticles * 4 * 3];
49 	///GLfloat *coords2 = &pParticleSystem->pCoords[pParticleSystem->iNbParticles * 4 * 2];
50 	GLfloat *colors2 = &pParticleSystem->pColors[pParticleSystem->iNbParticles * 4 * 4];
51 
52 	GLfloat x,y,z;
53 	GLfloat w, h;
54 	GLfloat fHeight = pParticleSystem->fHeight;
55 
56 	int numActive = 0;
57 	CairoParticle *p;
58 	int i;
59 	for (i = 0; i < pParticleSystem->iNbParticles; i ++)
60 	{
61 		p = &pParticleSystem->pParticles[i];
62 		if (p->iLife == 0 || iDepth * p->z < 0)
63 			continue;
64 
65 		numActive += 4;
66 		w = p->fWidth * p->fSizeFactor;
67 		h = p->fHeight * p->fSizeFactor;
68 		x = p->x * pParticleSystem->fWidth / 2;
69 		y = p->y * pParticleSystem->fHeight;
70 		z = p->z;
71 
72 		vertices[0] = x - w;
73 		vertices[2] = z;
74 		vertices[3] = x - w;
75 		vertices[5] = z;
76 		vertices[6] = x + w;
77 		vertices[8] = z;
78 		vertices[9] = x + w;
79 		vertices[11] = z;
80 		if (pParticleSystem->bDirectionUp)
81 		{
82 			vertices[1] = y + h;
83 			vertices[4] = y - h;
84 			vertices[7] = y - h;
85 			vertices[10] = y + h;
86 		}
87 		else
88 		{
89 			vertices[1] = fHeight - y + h;
90 			vertices[4] = fHeight - y - h;
91 			vertices[7] = fHeight - y - h;
92 			vertices[10] = fHeight - y + h;
93 		}
94 		vertices += 12;
95 
96 		///memcpy (coords, s_pCornerCoords, sizeof (s_pCornerCoords));
97 		///coords += 8;
98 
99 		colors[0] = p->color[0];
100 		colors[1] = p->color[1];
101 		colors[2] = p->color[2];
102 		colors[3] = p->color[3];
103 		memcpy (colors + 4, colors, 4*sizeof (GLfloat));
104 		memcpy (colors + 8, colors, 8*sizeof (GLfloat));
105 		colors += 16;
106 
107 		if (pParticleSystem->bAddLight)
108 		{
109 			w/=1.6;
110 			h/=1.6;
111 			vertices2[0] = x - w;
112 			vertices2[2] = z;
113 			vertices2[3] = x - w;
114 			vertices2[5] = z;
115 			vertices2[6] = x + w;
116 			vertices2[8] = z;
117 			vertices2[9] = x + w;
118 			vertices2[11] = z;
119 			if (pParticleSystem->bDirectionUp)
120 			{
121 				vertices2[1] = y + h;
122 				vertices2[4] = y - h;
123 				vertices2[7] = y - h;
124 				vertices2[10] = y + h;
125 			}
126 			else
127 			{
128 				vertices2[1] = fHeight - y + h;
129 				vertices2[4] = fHeight - y - h;
130 				vertices2[7] = fHeight - y - h;
131 				vertices2[10] = fHeight - y + h;
132 			}
133 			vertices2 += 12;
134 
135 			///memcpy (coords2, s_pCornerCoords, sizeof (s_pCornerCoords));
136 			///coords2 += 8;
137 
138 			colors2[0] = 1;
139 			colors2[1] = 1;
140 			colors2[2] = 1;
141 			colors2[3] = colors[3];
142 			memcpy (colors2 + 4, colors2, 4*sizeof (GLfloat));
143 			memcpy (colors2 + 8, colors2, 8*sizeof (GLfloat));
144 			colors2 += 16;
145 		}
146 	}
147 
148 	glEnableClientState(GL_COLOR_ARRAY);
149 	glEnableClientState (GL_TEXTURE_COORD_ARRAY);
150 	glEnableClientState (GL_VERTEX_ARRAY);
151 
152 	glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), pParticleSystem->pCoords);
153 	glVertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), pParticleSystem->pVertices);
154 	glColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), pParticleSystem->pColors);
155 
156 	glDrawArrays(GL_QUADS, 0, pParticleSystem->bAddLight ? numActive*2 : numActive);
157 
158 	glDisableClientState(GL_COLOR_ARRAY);
159 	glDisableClientState (GL_TEXTURE_COORD_ARRAY);
160 	glDisableClientState (GL_VERTEX_ARRAY);
161 
162 	_cairo_dock_disable_texture ();
163 }
164 
cairo_dock_create_particle_system(int iNbParticles,GLuint iTexture,double fWidth,double fHeight)165 CairoParticleSystem *cairo_dock_create_particle_system (int iNbParticles, GLuint iTexture, double fWidth, double fHeight)
166 {
167 	g_return_val_if_fail (iNbParticles > 0, NULL);
168 	CairoParticleSystem *pParticleSystem = g_new0 (CairoParticleSystem, 1);
169 	pParticleSystem->iNbParticles = iNbParticles;
170 	pParticleSystem->pParticles = g_new0 (CairoParticle, iNbParticles);
171 
172 	pParticleSystem->iTexture = iTexture;
173 
174 	pParticleSystem->fWidth = fWidth;
175 	pParticleSystem->fHeight = fHeight;
176 	pParticleSystem->bDirectionUp = TRUE;
177 
178 	pParticleSystem->pVertices = malloc(iNbParticles * 4 * 3 * sizeof(GLfloat)*2);
179 	pParticleSystem->pCoords = malloc(iNbParticles * 4 * 2 * sizeof(GLfloat)*2);
180 	pParticleSystem->pColors = malloc(iNbParticles * 4 * 4 * sizeof(GLfloat)*2);
181 
182 	GLfloat *coords = pParticleSystem->pCoords;  // on prerempli les coordonnees de la texture.
183 	// CairoParticle *p;
184 	int i;
185 	for (i = 0; i < 2*iNbParticles; i ++)
186 	{
187 		// p = &pParticleSystem->pParticles[i];
188 		memcpy (coords, s_pCornerCoords, sizeof (s_pCornerCoords));
189 		coords += 8;
190 	}
191 
192 	return pParticleSystem;
193 }
194 
195 
cairo_dock_free_particle_system(CairoParticleSystem * pParticleSystem)196 void cairo_dock_free_particle_system (CairoParticleSystem *pParticleSystem)
197 {
198 	if (pParticleSystem == NULL)
199 		return ;
200 
201 	g_free (pParticleSystem->pParticles);
202 
203 	free (pParticleSystem->pVertices);
204 	free (pParticleSystem->pCoords);
205 	free (pParticleSystem->pColors);
206 
207 	g_free (pParticleSystem);
208 }
209 
210 
cairo_dock_update_default_particle_system(CairoParticleSystem * pParticleSystem,CairoDockRewindParticleFunc pRewindParticle)211 gboolean cairo_dock_update_default_particle_system (CairoParticleSystem *pParticleSystem, CairoDockRewindParticleFunc pRewindParticle)
212 {
213 	gboolean bAllParticlesEnded = TRUE;
214 	CairoParticle *p;
215 	int i;
216 	for (i = 0; i < pParticleSystem->iNbParticles; i ++)
217 	{
218 		p = &(pParticleSystem->pParticles[i]);
219 
220 		p->fOscillation += p->fOmega;
221 		p->x += p->vx + (p->z + 2)/3. * .02 * sin (p->fOscillation);  // 3%
222 		p->y += p->vy;
223 		p->color[3] = 1.*p->iLife / p->iInitialLife;
224 		p->fSizeFactor += p->fResizeSpeed;
225 		if (p->iLife > 0)
226 		{
227 			p->iLife --;
228 			if (pRewindParticle && p->iLife == 0)
229 			{
230 				pRewindParticle (p, pParticleSystem->dt);
231 			}
232 			if (bAllParticlesEnded && p->iLife != 0)
233 				bAllParticlesEnded = FALSE;
234 		}
235 		else if (pRewindParticle)
236 			pRewindParticle (p, pParticleSystem->dt);
237 	}
238 	return ! bAllParticlesEnded;
239 }
240