00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "r_local.h"
00026 #include "r_particle.h"
00027
00028 ptlArt_t r_particlesArt[MAX_PTL_ART];
00029 int r_numParticlesArt;
00030
00031 ptl_t r_particles[MAX_PTLS];
00032 int r_numParticles;
00033
00034
00035
00036
00037
00038
00039
00047 static void R_GetSpriteVectors (const ptl_t *p, vec3_t right, vec3_t up)
00048 {
00049
00050 switch (p->style) {
00051 case STYLE_FACING:
00052 VectorScale(r_locals.right, p->size[0], right);
00053 VectorScale(r_locals.up, p->size[1], up);
00054 break;
00055
00056 case STYLE_ROTATED:
00057 AngleVectors(p->angles, NULL, right, up);
00058 VectorScale(right, p->size[0], right);
00059 VectorScale(up, p->size[1], up);
00060 break;
00061
00062 case STYLE_BEAM:
00063 case STYLE_AXIS:
00064 AngleVectors(p->angles, right, NULL, NULL);
00065 CrossProduct(right, r_locals.forward, up);
00066 VectorNormalize(up);
00067 VectorScale(right, p->size[0], right);
00068 VectorScale(up, p->size[1], up);
00069 break;
00070
00071 default:
00072 Com_Error(ERR_FATAL, "R_GetSpriteVectors: unknown style");
00073 }
00074 }
00075
00080 static inline void R_SpriteTexcoords (const ptl_t *p, float out[8])
00081 {
00082 const float s = p->scrollS * refdef.time;
00083 const float t = p->scrollT * refdef.time;
00084
00085 out[0] = 0.0 + s;
00086 out[1] = 0.0 + t;
00087
00088 out[2] = 0.0 + s;
00089 out[3] = 1.0 + t;
00090
00091 out[4] = 1.0 + s;
00092 out[5] = 1.0 + t;
00093
00094 out[6] = 1.0 + s;
00095 out[7] = 0.0 + t;
00096 }
00097
00101 static void R_DrawSprite (const ptl_t * p)
00102 {
00103 const ptl_t *q;
00104 vec3_t up, right;
00105 vec3_t nup, nright;
00106 vec3_t pos;
00107 float texcoords[8];
00108
00109
00110 assert(p->pic);
00111 R_BindTexture(p->pic->art.image->texnum);
00112
00113
00114 q = p->parent ? p->parent : p;
00115 R_GetSpriteVectors(q, right, up);
00116
00117
00118 VectorCopy(up, nup);
00119 VectorCopy(right, nright);
00120 VectorNormalize(nup);
00121 VectorNormalize(nright);
00122
00123
00124 VectorCopy(q->s, pos);
00125 VectorMA(pos, q->offset[0], nup, pos);
00126 VectorMA(pos, q->offset[1], nright, pos);
00127
00128 if (p->parent) {
00129
00130 R_GetSpriteVectors(p, right, up);
00131
00132
00133 VectorMA(pos, p->offset[0], nup, pos);
00134 VectorMA(pos, p->offset[1], nright, pos);
00135 }
00136
00137
00138 VectorMA(pos, -0.5, up, pos);
00139 VectorMA(pos, -0.5, right, pos);
00140
00141 R_SpriteTexcoords(p, texcoords);
00142
00143 R_Color(p->color);
00144
00145 glBegin(GL_TRIANGLE_FAN);
00146
00147 glTexCoord2f(texcoords[0], texcoords[1]);
00148 glVertex3fv(pos);
00149
00150 VectorAdd(pos, up, pos);
00151 glTexCoord2f(texcoords[2], texcoords[3]);
00152 glVertex3fv(pos);
00153
00154 VectorAdd(pos, right, pos);
00155 glTexCoord2f(texcoords[4], texcoords[5]);
00156 glVertex3fv(pos);
00157
00158 VectorSubtract(pos, up, pos);
00159 glTexCoord2f(texcoords[6], texcoords[7]);
00160 glVertex3fv(pos);
00161
00162 glEnd();
00163 }
00164
00165
00169 static void R_DrawParticleModel (ptl_t * p)
00170 {
00171 modelInfo_t mi;
00172
00173
00174 memset(&mi, 0, sizeof(mi));
00175 mi.color = p->color;
00176 mi.origin = p->s;
00177 mi.angles = p->angles;
00178 assert(p->model);
00179 mi.model = p->model->art.model;
00180 mi.skin = p->skin;
00181
00182
00183 R_DrawModelParticle(&mi);
00184 }
00185
00191 static void R_DrawPtlCircle (const ptl_t* p)
00192 {
00193 const float radius = p->size[0];
00194 const int thickness = (int)p->size[1];
00195 float theta;
00196 const float accuracy = 5.0f;
00197
00198 R_EnableTexture(&texunit_diffuse, qfalse);
00199
00200 R_Color(p->color);
00201
00202 glEnable(GL_LINE_SMOOTH);
00203
00204 assert(radius > thickness);
00205 if (thickness <= 1) {
00206 glBegin(GL_LINE_LOOP);
00207 for (theta = 0.0f; theta < 2.0f * M_PI; theta += M_PI / (radius * accuracy)) {
00208 glVertex3f(p->s[0] + radius * cos(theta), p->s[1] + radius * sin(theta), p->s[2]);
00209 }
00210 glEnd();
00211 } else {
00212 const float delta = M_PI / (radius * accuracy);
00213 glBegin(GL_TRIANGLE_STRIP);
00214 for (theta = 0; theta <= 2 * M_PI; theta += delta) {
00215 const float f = theta - M_PI / (radius * accuracy);
00216 glVertex3f(p->s[0] + radius * cos(theta), p->s[1] + radius * sin(theta), p->s[2]);
00217 glVertex3f(p->s[0] + radius * cos(f), p->s[1] + radius * sin(f), p->s[2]);
00218 glVertex3f(p->s[0] + (radius - thickness) * cos(f), p->s[1] + (radius - thickness) * sin(f), p->s[2]);
00219 glVertex3f(p->s[0] + (radius - thickness) * cos(theta), p->s[1] + (radius - thickness) * sin(theta), p->s[2]);
00220 }
00221 glEnd();
00222 }
00223
00224 glDisable(GL_LINE_SMOOTH);
00225
00226 R_EnableTexture(&texunit_diffuse, qtrue);
00227 }
00228
00232 static void R_DrawPtlLine (const ptl_t * p)
00233 {
00234 R_EnableTexture(&texunit_diffuse, qfalse);
00235
00236 glEnable(GL_LINE_SMOOTH);
00237
00238 R_Color(p->color);
00239
00240
00241 glBegin(GL_LINE_STRIP);
00242 glVertex3fv(p->s);
00243 glVertex3fv(p->v);
00244 glEnd();
00245
00246 glDisable(GL_LINE_SMOOTH);
00247
00248 R_EnableTexture(&texunit_diffuse, qtrue);
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00261 static void R_SetBlendMode (int mode)
00262 {
00263 switch (mode) {
00264 case BLEND_REPLACE:
00265 R_TexEnv(GL_REPLACE);
00266 break;
00267 case BLEND_ONE:
00268 R_BlendFunc(GL_SRC_ALPHA, GL_ONE);
00269 break;
00270 case BLEND_BLEND:
00271 R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00272 break;
00273 case BLEND_ADD:
00274 R_BlendFunc(GL_ONE, GL_ONE);
00275 break;
00276 case BLEND_FILTER:
00277 R_BlendFunc(GL_ZERO, GL_SRC_COLOR);
00278 break;
00279 case BLEND_INVFILTER:
00280 R_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
00281 break;
00282 default:
00283 Com_Error(ERR_DROP, "unknown blend mode");
00284 break;
00285 }
00286 }
00287
00292 void R_DrawParticles (void)
00293 {
00294 ptl_t *p;
00295 int i;
00296
00297 for (i = 0, p = r_particles; i < r_numParticles; i++, p++)
00298 if (p->inuse && !p->invis) {
00299
00300 if (p->levelFlags && !((1 << refdef.worldlevel) & p->levelFlags))
00301 continue;
00302
00303 if (p->program != NULL)
00304 R_UseProgram(p->program);
00305
00306
00307 R_SetBlendMode(p->blend);
00308 switch (p->style) {
00309 case STYLE_LINE:
00310 R_DrawPtlLine(p);
00311 break;
00312 case STYLE_CIRCLE:
00313 R_DrawPtlCircle(p);
00314 break;
00315 default:
00316 break;
00317 }
00318 if (p->pic)
00319 R_DrawSprite(p);
00320 if (p->model)
00321 R_DrawParticleModel(p);
00322 R_TexEnv(GL_MODULATE);
00323
00324 R_UseProgram(NULL);
00325 }
00326
00327 R_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00328
00329 R_Color(NULL);
00330 }