void trail_render( trail * trailp ) { int sections[NUM_TRAIL_SECTIONS]; int num_sections = 0; int i; vec3d topv, botv, *fvec, last_pos, tmp_fvec; vertex top, bot; int nv = 0; float w; ubyte l; vec3d centerv; if (trailp->tail == trailp->head) return; // if this trail is on the player ship, and he's in any padlock view except rear view, don't draw if ( (Player_ship != NULL) && trail_is_on_ship(trailp, Player_ship) && (Viewer_mode & (VM_PADLOCK_UP | VM_PADLOCK_LEFT | VM_PADLOCK_RIGHT)) ) { return; } trail_info *ti = &trailp->info; int n = trailp->tail; do { n--; if (n < 0) n = NUM_TRAIL_SECTIONS-1; if (trailp->val[n] > 1.0f) break; sections[num_sections++] = n; } while ( n != trailp->head ); if (num_sections <= 0) return; Assertion(ti->texture.bitmap_id != -1, "Weapon trail %s could not be loaded", ti->texture.filename); // We can leave this as an assert, but tell them how to fix it. --Chief memset( &top, 0, sizeof(vertex) ); memset( &bot, 0, sizeof(vertex) ); // it's a tristrip, so allocate for 2+1 allocate_trail_verts((num_sections * 2) + 1); float w_size = (ti->w_end - ti->w_start); float a_size = (ti->a_end - ti->a_start); int num_faded_sections = ti->n_fade_out_sections; for (i = 0; i < num_sections; i++) { n = sections[i]; float init_fade_out = 1.0f; if ((num_faded_sections > 0) && (i < num_faded_sections)) { init_fade_out = ((float) i) / (float) num_faded_sections; } w = trailp->val[n] * w_size + ti->w_start; if (init_fade_out != 1.0f) { l = (ubyte)fl2i((trailp->val[n] * a_size + ti->a_start) * 255.0f * init_fade_out * init_fade_out); } else { l = (ubyte)fl2i((trailp->val[n] * a_size + ti->a_start) * 255.0f); } if ( i == 0 ) { if ( num_sections > 1 ) { vm_vec_sub(&tmp_fvec, &trailp->pos[n], &trailp->pos[sections[i+1]] ); vm_vec_normalize_safe(&tmp_fvec); fvec = &tmp_fvec; } else { fvec = &tmp_fvec; fvec->xyz.x = 0.0f; fvec->xyz.y = 0.0f; fvec->xyz.z = 1.0f; } } else { vm_vec_sub(&tmp_fvec, &last_pos, &trailp->pos[n] ); vm_vec_normalize_safe(&tmp_fvec); fvec = &tmp_fvec; } trail_calc_facing_pts( &topv, &botv, fvec, &trailp->pos[n], w ); if ( !Cmdline_nohtl ) { g3_transfer_vertex( &top, &topv ); g3_transfer_vertex( &bot, &botv ); } else { g3_rotate_vertex( &top, &topv ); g3_rotate_vertex( &bot, &botv ); } top.a = bot.a = l; if (i > 0) { float U = i2fl(i); if (i == num_sections-1) { // Last one... vm_vec_avg( ¢erv, &topv, &botv ); if ( !Cmdline_nohtl ) g3_transfer_vertex( &Trail_v_list[nv+2], ¢erv ); else g3_rotate_vertex( &Trail_v_list[nv+2], ¢erv ); Trail_v_list[nv].a = l; Trail_v_list[nv].texture_position.u = U; Trail_v_list[nv].texture_position.v = 1.0f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = l; nv++; Trail_v_list[nv].texture_position.u = U; Trail_v_list[nv].texture_position.v = 0.0f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = l; nv++; Trail_v_list[nv].texture_position.u = U + 1.0f; Trail_v_list[nv].texture_position.v = 0.5f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = 0; nv++; } else { Trail_v_list[nv].texture_position.u = U; Trail_v_list[nv].texture_position.v = 1.0f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = l; nv++; Trail_v_list[nv].texture_position.u = U; Trail_v_list[nv].texture_position.v = 0.0f; Trail_v_list[nv].r = Trail_v_list[nv].g = Trail_v_list[nv].b = l; nv++; } } last_pos = trailp->pos[n]; Trail_v_list[nv] = top; Trail_v_list[nv+1] = bot; } if ( !nv ) return; if (nv < 3) Error( LOCATION, "too few verts in trail render\n" ); // there should always be three verts in the last section and 2 everyware else, therefore there should always be an odd number of verts if ( (nv % 2) != 1 ) Warning( LOCATION, "even number of verts in trail render\n" ); profile_begin("Trail Draw"); gr_set_bitmap( ti->texture.bitmap_id, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f ); gr_render(nv, Trail_v_list, TMAP_FLAG_TEXTURED | TMAP_FLAG_ALPHA | TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB | TMAP_HTL_3D_UNLIT | TMAP_FLAG_TRISTRIP); profile_end("Trail Draw"); }
void particle_render_all() { ubyte flags; float pct_complete; float alpha; vertex pos; vec3d ts, te, temp; int rotate = 1; int framenum, cur_frame; bool render_batch = false; int tmap_flags = TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD; if ( !Particles_enabled ) return; MONITOR_INC( NumParticlesRend, Num_particles ); if ( Particles.empty() ) return; for (SCP_vector<particle*>::iterator p = Particles.begin(); p != Particles.end(); ++p) { particle* part = *p; // skip back-facing particles (ripped from fullneb code) // Wanderer - add support for attached particles vec3d p_pos; if (part->attached_objnum >= 0) { vm_vec_unrotate(&p_pos, &part->pos, &Objects[part->attached_objnum].orient); vm_vec_add2(&p_pos, &Objects[part->attached_objnum].pos); } else { p_pos = part->pos; } if ( vm_vec_dot_to_point(&Eye_matrix.vec.fvec, &Eye_position, &p_pos) <= 0.0f ) { continue; } // calculate the alpha to draw at alpha = get_current_alpha(&p_pos); // if it's transparent then just skip it if (alpha <= 0.0f) { continue; } // make sure "rotate" is enabled for this particle rotate = 1; // if this is a tracer style particle, calculate tracer vectors if (part->tracer_length > 0.0f) { ts = p_pos; temp = part->velocity; vm_vec_normalize_quick(&temp); vm_vec_scale_add(&te, &ts, &temp, part->tracer_length); // don't bother rotating rotate = 0; } // rotate the vertex if (rotate) { flags = g3_rotate_vertex( &pos, &p_pos ); if ( flags ) { continue; } if (!Cmdline_nohtl) g3_transfer_vertex(&pos, &p_pos); } // pct complete for the particle pct_complete = part->age / part->max_life; // figure out which frame we should be using if (part->nframes > 1) { framenum = fl2i(pct_complete * part->nframes + 0.5); CLAMP(framenum, 0, part->nframes-1); cur_frame = part->reverse ? (part->nframes - framenum - 1) : framenum; } else { cur_frame = 0; } if (part->type == PARTICLE_DEBUG) { gr_set_color( 255, 0, 0 ); g3_draw_sphere_ez( &p_pos, part->radius ); } else { framenum = part->optional_data; Assert( cur_frame < part->nframes ); // if this is a tracer style particle if (part->tracer_length > 0.0f) { batch_add_laser( framenum + cur_frame, &ts, part->radius, &te, part->radius ); } // draw as a regular bitmap else { batch_add_bitmap( framenum + cur_frame, tmap_flags, &pos, part->particle_index % 8, part->radius, alpha ); } render_batch = true; } } profile_begin("Batch Render"); if (render_batch) { batch_render_all(Particle_buffer_object); } profile_end("Batch Render"); }