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