Beispiel #1
0
void HudGaugeRadarOrb::drawOutlines()
{
    int i;
    vertex center;
//	vertex extents[6];
    vertex proj_orb_lines_xy[NUM_ORB_RING_SLICES];
    vertex proj_orb_lines_xz[NUM_ORB_RING_SLICES];
    vertex proj_orb_lines_yz[NUM_ORB_RING_SLICES];

    g3_start_instance_matrix(&vmd_zero_vector, &view_perturb, false);
    g3_start_instance_matrix(&vmd_zero_vector, &Player_obj->orient, false);

    g3_rotate_vertex(&center, &vmd_zero_vector);
    g3_rotate_vertex(&proj_orb_lines_xy[0], &orb_ring_xy[0]);
    g3_rotate_vertex(&proj_orb_lines_yz[0], &orb_ring_yz[0]);
    g3_rotate_vertex(&proj_orb_lines_xz[0], &orb_ring_xz[0]);

    g3_project_vertex(&center);
    gr_set_color(255,255,255);
    g3_draw_sphere(&center, .05f);

    g3_project_vertex(&proj_orb_lines_xy[0]);
    g3_project_vertex(&proj_orb_lines_yz[0]);
    g3_project_vertex(&proj_orb_lines_xz[0]);

    for (i=1; i < NUM_ORB_RING_SLICES; i++)
    {
        g3_rotate_vertex(&proj_orb_lines_xy[i], &orb_ring_xy[i]);
        g3_rotate_vertex(&proj_orb_lines_yz[i], &orb_ring_yz[i]);
        g3_rotate_vertex(&proj_orb_lines_xz[i], &orb_ring_xz[i]);

        g3_project_vertex(&proj_orb_lines_xy[i]);
        g3_project_vertex(&proj_orb_lines_yz[i]);
        g3_project_vertex(&proj_orb_lines_xz[i]);

        gr_set_color(192,96,32);
        g3_draw_sphere(&proj_orb_lines_xy[i-1], .01f);
        g3_draw_sphere(&proj_orb_lines_xz[i-1], .01f);
        g3_draw_line(&proj_orb_lines_xy[i-1],&proj_orb_lines_xy[i]);
        g3_draw_line(&proj_orb_lines_xz[i-1],&proj_orb_lines_xz[i]);

        gr_set_color(112,16,192);

        g3_draw_sphere(&proj_orb_lines_yz[i-1], .01f);
        g3_draw_line(&proj_orb_lines_yz[i-1],&proj_orb_lines_yz[i]);
    }

    g3_done_instance(false);
}
/**
 * Render jump node
 *
 * @param pos		World position
 * @param view_pos	Viewer's world position, can be NULL
 */
void CJumpNode::RenderDEPRECATED(vec3d *pos, vec3d *view_pos)
{
	Assert(pos != NULL);
    // Assert(view_pos != NULL); - view_pos can be NULL
	
	if(m_flags & JN_HIDE)
		return;
	
	if(m_modelnum < 0)
		return;
	
	matrix node_orient = IDENTITY_MATRIX;
	
	int mr_flags = MR_NO_LIGHTING;
	if(!(m_flags & JN_SHOW_POLYS)) {
		mr_flags |= MR_NO_CULL | MR_NO_POLYS | MR_SHOW_OUTLINE_PRESET;
	}
	
	if ( Fred_running ) {
		gr_set_color_fast(&m_display_color);		
		model_render_DEPRECATED(m_modelnum, &node_orient, pos, mr_flags );
	} else {
		if (m_flags & JN_USE_DISPLAY_COLOR) {
			gr_set_color_fast(&m_display_color);
		}
		else if ( view_pos != NULL) {
			int alpha_index = HUD_color_alpha;
			
			// generate alpha index based on distance to jump this
			float dist;
			
			dist = vm_vec_dist_quick(view_pos, pos);
			
			// linearly interpolate alpha.  At 1000m or less, full intensity.  At 10000m or more 1/2 intensity.
			if ( dist < 1000 ) {
				alpha_index = HUD_COLOR_ALPHA_USER_MAX - 2;
			} else if ( dist > 10000 ) {
				alpha_index = HUD_COLOR_ALPHA_USER_MIN;
			} else {
				alpha_index = fl2i( HUD_COLOR_ALPHA_USER_MAX - 2 + (dist-1000) * (HUD_COLOR_ALPHA_USER_MIN-HUD_COLOR_ALPHA_USER_MAX-2) / (9000) + 0.5f);
				if ( alpha_index < HUD_COLOR_ALPHA_USER_MIN ) {
					alpha_index = HUD_COLOR_ALPHA_USER_MIN;
				}
			}
			
			gr_set_color_fast(&HUD_color_defaults[alpha_index]);
			
		} else {
			gr_set_color(HUD_color_red, HUD_color_green, HUD_color_blue);
		}
		
		model_render_DEPRECATED(m_modelnum, &node_orient, pos, mr_flags );
	}
	
}
Beispiel #3
0
void grid_render_elevation_line(vector *pos, grid* gridp)
{
	vector	gpos;	//	Location of point on grid.
	vector	tpos;
	float		dxz;
	plane		tplane;
	vector	*gv;
	
	tplane.A = gridp->gmatrix.v.uvec.xyz.x;
	tplane.B = gridp->gmatrix.v.uvec.xyz.y;
	tplane.C = gridp->gmatrix.v.uvec.xyz.z;
	tplane.D = gridp->planeD;

	compute_point_on_plane(&gpos, &tplane, pos);

	dxz = vm_vec_dist(pos, &gpos)/8.0f;

	gv = &gridp->gmatrix.v.uvec;
	if (gv->xyz.x * pos->xyz.x + gv->xyz.y * pos->xyz.y + gv->xyz.z * pos->xyz.z < -gridp->planeD)
		gr_set_color(127, 127, 127);
	else
		gr_set_color(255, 255, 255);   // white

	rpd_line(&gpos, pos);	//	Line from grid to object center.

	tpos = gpos;

	vm_vec_scale_add2(&gpos, &gridp->gmatrix.v.rvec, -dxz/2);
	vm_vec_scale_add2(&gpos, &gridp->gmatrix.v.fvec, -dxz/2);
	
	vm_vec_scale_add2(&tpos, &gridp->gmatrix.v.rvec, dxz/2);
	vm_vec_scale_add2(&tpos, &gridp->gmatrix.v.fvec, dxz/2);
	
	rpd_line(&gpos, &tpos);

	vm_vec_scale_add2(&gpos, &gridp->gmatrix.v.rvec, dxz);
	vm_vec_scale_add2(&tpos, &gridp->gmatrix.v.rvec, -dxz);

	rpd_line(&gpos, &tpos);
}
Beispiel #4
0
void training_menu_do_frame(float frametime)
{
	int training_menu_choice;

	if (!training_menu_inited)
	{
		training_menu_init();
		training_menu_inited = 1;
	}

	gr_reset_clip();
	gr_set_color(0, 0, 0);
	GR_MAYBE_CLEAR_RES(trainingMenuBitmap);
	// set the background
	if (trainingMenuBitmap != -1)
	{
		gr_set_bitmap(trainingMenuBitmap);
		gr_bitmap(0, 0);
	}

	int snazzy_action = -1;
	training_menu_choice = snazzy_menu_do(mask_data, Training_mask_w, Training_mask_h, num_training,
		region, &snazzy_action);
	if (snazzy_action != SNAZZY_CLICKED)
	{
		training_menu_choice = -1;
	}

	switch (training_menu_choice)
	{

	case TRAINING_MENU_TRAINING_MISSIONS_MASK:
		break;
	case TRAINING_MENU_REPLAY_MISSIONS_MASK:
		// TODO: load the mission and start the briefing
		break;
	case TRAINING_MENU_RETURN_MASK:
	case ESC_PRESSED:
		gameseq_post_event(GS_EVENT_MAIN_MENU);
		break;
	case -1:
		// nothing selected
		break;
	default:
		Error(LOCATION, "Unknown option %d in training menu screen", training_menu_choice);
		break;

	} // end switch

	gr_flip();
}
Beispiel #5
0
// draw overlay on the screen
void help_overlay_blit(int overlay_id)
{
	int idx, width, height;
	int plinecount = help_overlaylist[overlay_id].plinecount;
	int textcount = help_overlaylist[overlay_id].textcount;
	int rbracketcount = help_overlaylist[overlay_id].rbracketcount;
	int lbracketcount = help_overlaylist[overlay_id].lbracketcount;

	Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);

	// this draws each line of help text with white on black text (use the GR_640 index for the string)
	for (idx = 0; idx < textcount; idx++)
	{
		gr_set_color_fast(&Color_black);
		gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist[GR_640][idx].string,
			strlen(help_overlaylist[overlay_id].textlist[GR_640][idx].string));
		gr_rect(help_overlaylist[overlay_id].textlist[gr_screen.res][idx].x_coord - 2 * HELP_PADDING,
			help_overlaylist[overlay_id].textlist[gr_screen.res][idx].y_coord - 3 * HELP_PADDING,
			width + 4 * HELP_PADDING, height + 4 * HELP_PADDING);
		gr_set_color_fast(&Color_bright_white);
		gr_printf(help_overlaylist[overlay_id].textlist[gr_screen.res][idx].x_coord,
			help_overlaylist[overlay_id].textlist[gr_screen.res][idx].y_coord,
			help_overlaylist[overlay_id].textlist[GR_640][idx].string);
	}

	// this draws each right bracket
	for (idx = 0; idx < rbracketcount; idx++)
	{
		gr_set_bitmap(help_right_bracket_bitmap);
		gr_bitmap(help_overlaylist[overlay_id].rbracketlist[gr_screen.res][idx].x_coord,
			help_overlaylist[overlay_id].rbracketlist[gr_screen.res][idx].y_coord);
	}

	// this draws each left bracket
	for (idx = 0; idx < lbracketcount; idx++)
	{
		gr_set_bitmap(help_left_bracket_bitmap);
		gr_bitmap(help_overlaylist[overlay_id].lbracketlist[gr_screen.res][idx].x_coord,
			help_overlaylist[overlay_id].lbracketlist[gr_screen.res][idx].y_coord);
	}

	// this draws each 2d line for the help screen
	//gr_set_color_fast(&Color_yellow);
	gr_set_color(255, 255, 0);
	for (idx = 0; idx < plinecount; idx++)
	{
		gr_pline_special(help_overlaylist[overlay_id].plinelist[gr_screen.res][idx].pvtx,
			help_overlaylist[overlay_id].plinelist[GR_640][idx].vtxcount, HELP_PLINE_THICKNESS);
	}
}
// draw overlay on the screen
void help_overlay_blit(int overlay_id, int resolution_index)
{
	int idx, width, height;
	int plinecount = help_overlaylist[overlay_id].plinecount;
	int textcount = help_overlaylist[overlay_id].textcount;
	int rbracketcount = help_overlaylist[overlay_id].rbracketcount;
	int lbracketcount = help_overlaylist[overlay_id].lbracketcount;

	Assert(overlay_id >= 0 && overlay_id < MAX_HELP_OVERLAYS);

	// this draws each line of help text with white on black text (use the first resolution index for the string)
	gr_set_font(help_overlaylist[overlay_id].fontlist.at(resolution_index));
	for (idx = 0; idx < textcount; idx++) {
		gr_set_color_fast(&Color_black);
		gr_get_string_size(&width, &height, help_overlaylist[overlay_id].textlist.at(0).at(idx).string, strlen(help_overlaylist[overlay_id].textlist.at(0).at(idx).string));
		gr_rect(help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).x_coord-2*HELP_PADDING, help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).y_coord-3*HELP_PADDING, width+4*HELP_PADDING, height+4*HELP_PADDING, GR_RESIZE_MENU);
		gr_set_color_fast(&Color_bright_white);
		gr_printf_menu(help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).x_coord, help_overlaylist[overlay_id].textlist.at(resolution_index).at(idx).y_coord, help_overlaylist[overlay_id].textlist.at(0).at(idx).string);
	}
	gr_set_font(FONT1);

	// this draws each right bracket
	for (idx = 0; idx < rbracketcount; idx++) {
		gr_set_bitmap(help_right_bracket_bitmap);
		gr_bitmap(help_overlaylist[overlay_id].rbracketlist.at(resolution_index).at(idx).x_coord, help_overlaylist[overlay_id].rbracketlist.at(resolution_index).at(idx).y_coord, GR_RESIZE_MENU);
	}

	// this draws each left bracket
	for (idx = 0; idx < lbracketcount; idx++) {
		gr_set_bitmap(help_left_bracket_bitmap);
		gr_bitmap(help_overlaylist[overlay_id].lbracketlist.at(resolution_index).at(idx).x_coord, help_overlaylist[overlay_id].lbracketlist.at(resolution_index).at(idx).y_coord, GR_RESIZE_MENU);
	}	

	// this draws each 2d line for the help screen
	//gr_set_color_fast(&Color_yellow);
	gr_set_color(255, 255, 0);
	for (idx = 0; idx<plinecount; idx++) {
		gr_pline_special(&help_overlaylist[overlay_id].plinelist.at(resolution_index).at(idx).vtx, HELP_PLINE_THICKNESS, GR_RESIZE_MENU);
	}
}
Beispiel #7
0
void HudGaugeRadarOrb::drawOutlinesHtl()
{
    int i, last = NUM_ORB_RING_SLICES - 1;

    g3_start_instance_matrix(&vmd_zero_vector, &view_perturb, true);
    g3_start_instance_matrix(&vmd_zero_vector, &Player_obj->orient, true);

    gr_set_color(255, 255, 255);
    g3_render_sphere(&vmd_zero_vector, .05f);

    gr_set_line_width(2.0f);

    for (i = 0; i < NUM_ORB_RING_SLICES; i++)
    {
        gr_init_alphacolor(&Orb_color_orange, 192, 96, 32, calcAlpha(&orb_ring_xy[last]));
        gr_set_color_fast(&Orb_color_orange);
        //g3_draw_htl_line(&orb_ring_xy[last],&orb_ring_xy[i]);
        g3_render_line_3d(false, &orb_ring_xy[last],&orb_ring_xy[i]);

        gr_init_alphacolor(&Orb_color_teal, 48, 160, 96, calcAlpha(&orb_ring_xz[last]));
        gr_set_color_fast(&Orb_color_teal);
        //g3_draw_htl_line(&orb_ring_xz[last],&orb_ring_xz[i]);
        g3_render_line_3d(false, &orb_ring_xz[last],&orb_ring_xz[i]);

        gr_init_alphacolor(&Orb_color_purple, 112, 16, 192, calcAlpha(&orb_ring_yz[last]));
        gr_set_color_fast(&Orb_color_purple);
        //g3_draw_htl_line(&orb_ring_yz[last],&orb_ring_yz[i]);
        g3_render_line_3d(false, &orb_ring_yz[last],&orb_ring_yz[i]);

        last = i;
    }

    gr_set_line_width(1.0f);

    g3_done_instance(true);
    g3_done_instance(true);
}
// Play one movie
bool movie_play(char *name)
{
	// mark the movie as viewable to the player when in a campaign
	// do this before anything else so that we're sure the movie is available
	// to the player even if it's not going to play right now
	if (Game_mode & GM_CAMPAIGN_MODE) {
		cutscene_mark_viewable(name);
	}

	extern int Mouse_hidden;
	extern int Is_standalone;

	if (Cmdline_nomovies || Is_standalone)
		return false;


	char full_name[MAX_PATH];
	int rc = 0;

	memset(full_name, 0, sizeof(full_name));

	rc = movie_find(name, full_name);

	if (rc == MOVIE_NONE) {
		strcpy_s(full_name, name);
		char *p = strrchr(full_name, '.');
		if ( p ) *p = 0;

		mprintf(("Movie Error:  Unable to open '%s' movie in any supported format.\n", full_name));
		return false;
	}

	// clear the screen and hide the mouse cursor
	Mouse_hidden++;
	gr_reset_clip();
	gr_set_color(255, 255, 255);
	gr_set_clear_color(0, 0, 0);
	gr_zbuffer_clear(0);
	// clear first buffer
	gr_clear();
	gr_flip();
	// clear second buffer (may not be one, but that's ok)
	gr_clear();
	gr_flip();
	// clear third buffer (may not be one, but that's ok)
	gr_clear();

	if (rc == MOVIE_OGG) {
		THEORAFILE *movie_ogg = theora_open(name);

		if (movie_ogg) {
			// start playing ...
			theora_play(movie_ogg);

			// ... done playing, close the movie
			theora_close(movie_ogg);
		} else {
			// uh-oh, movie is invalid... Abory, Retry, Fail?
			mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
			Mouse_hidden--;	// show the mouse cursor!
			return false;
		}
	} else if (rc == MOVIE_MVE) {
		MVESTREAM *movie_mve = mve_open(name);

		if (movie_mve) {
			// start playing ...
			mve_init(movie_mve);
			mve_play(movie_mve);

			// ... done playing, close the movie
			mve_shutdown();
			mve_close(movie_mve);
		} else {
			// uh-oh, movie is invalid... Abory, Retry, Fail?
			mprintf(("MOVIE ERROR: Found invalid movie! (%s)\n", name));
			Mouse_hidden--;	// show the mouse cursor!
			return false;
		}
	}

	// show the mouse cursor again
	Mouse_hidden--;

	return true;
}
void shadows_debug_show_frustum(matrix* orient, vec3d *pos, float fov, float aspect, float z_near, float z_far)
{
	// find the widths and heights of the near plane and far plane to determine the points of this frustum
	float near_height = (float)tan((double)fov * 0.5) * z_near;
	float near_width = near_height * aspect;

	float far_height = (float)tan((double)fov * 0.5) * z_far;
	float far_width = far_height * aspect;

	vec3d up_scale = ZERO_VECTOR;
	vec3d right_scale = ZERO_VECTOR;
	vec3d forward_scale_near = orient->vec.fvec;
	vec3d forward_scale_far = orient->vec.fvec;

	vm_vec_scale(&forward_scale_near, z_near);
	vm_vec_scale(&forward_scale_far, z_far);

	// find the eight points using eye orientation and position
	vec3d near_top_left = ZERO_VECTOR;
	vec3d near_top_right = ZERO_VECTOR;
	vec3d near_bottom_left = ZERO_VECTOR;
	vec3d near_bottom_right = ZERO_VECTOR;

	// near top left
	up_scale = orient->vec.uvec;
	vm_vec_scale(&up_scale, -near_height);

	right_scale = orient->vec.rvec;
	vm_vec_scale(&right_scale, -near_width);

	vm_vec_add(&near_top_left, &up_scale, &right_scale);
	vm_vec_add2(&near_top_left, &forward_scale_near);

	// near top right
	up_scale = orient->vec.uvec;
	vm_vec_scale(&up_scale, -near_height);

	right_scale = orient->vec.rvec;
	vm_vec_scale(&right_scale, near_width);

	vm_vec_add(&near_top_right, &up_scale, &right_scale);
	vm_vec_add2(&near_top_right, &forward_scale_near);

	// near bottom left
	up_scale = orient->vec.uvec;
	vm_vec_scale(&up_scale, near_height);

	right_scale = orient->vec.rvec;
	vm_vec_scale(&right_scale, -near_width);

	vm_vec_add(&near_bottom_left, &up_scale, &right_scale);
	vm_vec_add2(&near_bottom_left, &forward_scale_near);

	// near bottom right
	up_scale = orient->vec.uvec;
	vm_vec_scale(&up_scale, near_height);

	right_scale = orient->vec.rvec;
	vm_vec_scale(&right_scale, near_width);

	vm_vec_add(&near_bottom_right, &up_scale, &right_scale);
	vm_vec_add2(&near_bottom_right, &forward_scale_near);

	vec3d far_top_left = ZERO_VECTOR;
	vec3d far_top_right = ZERO_VECTOR;
	vec3d far_bottom_left = ZERO_VECTOR;
	vec3d far_bottom_right = ZERO_VECTOR;

	// far top left
	up_scale = orient->vec.uvec;
	vm_vec_scale(&up_scale, -far_height);

	right_scale = orient->vec.rvec;
	vm_vec_scale(&right_scale, -far_width);

	vm_vec_add(&far_top_left, &up_scale, &right_scale);
	vm_vec_add2(&far_top_left, &forward_scale_far);

	// far top right
	up_scale = orient->vec.uvec;
	vm_vec_scale(&up_scale, -far_height);

	right_scale = orient->vec.rvec;
	vm_vec_scale(&right_scale, far_width);

	vm_vec_add(&far_top_right, &up_scale, &right_scale);
	vm_vec_add2(&far_top_right, &forward_scale_far);

	// far bottom left
	up_scale = orient->vec.uvec;
	vm_vec_scale(&up_scale, far_height);

	right_scale = orient->vec.rvec;
	vm_vec_scale(&right_scale, -far_width);

	vm_vec_add(&far_bottom_left, &up_scale, &right_scale);
	vm_vec_add2(&far_bottom_left, &forward_scale_far);

	// far bottom right
	up_scale = orient->vec.uvec;
	vm_vec_scale(&up_scale, far_height);

	right_scale = orient->vec.rvec;
	vm_vec_scale(&right_scale, far_width);

	vm_vec_add(&far_bottom_right, &up_scale, &right_scale);
	vm_vec_add2(&far_bottom_right, &forward_scale_far);

	// translate frustum
	vm_vec_add2(&near_bottom_left, pos);
	vm_vec_add2(&near_bottom_right, pos);
	vm_vec_add2(&near_top_right, pos);
	vm_vec_add2(&near_top_left, pos);
	vm_vec_add2(&far_top_left, pos);
	vm_vec_add2(&far_top_right, pos);
	vm_vec_add2(&far_bottom_right, pos);
	vm_vec_add2(&far_bottom_left, pos);

	gr_set_color(0, 255, 255);
	g3_draw_htl_line(&near_bottom_left, &near_bottom_right);
	g3_draw_htl_line(&near_bottom_right, &near_top_right);
	g3_draw_htl_line(&near_bottom_right, &near_top_left);
	g3_draw_htl_line(&near_top_right, &near_top_left);
	g3_draw_htl_line(&far_top_left, &far_top_right);
	g3_draw_htl_line(&far_top_right, &far_bottom_right);
	g3_draw_htl_line(&far_bottom_right, &far_bottom_left);
	g3_draw_htl_line(&far_bottom_left, &far_top_left);
}
Beispiel #10
0
void ship_draw_shield( object *objp)
{
    int		model_num;
    int		i;
    vec3d	pnt;
    polymodel * pm;

    if (objp->flags & OF_NO_SHIELDS)
        return;

    Assert(objp->instance >= 0);

    model_num = Ship_info[Ships[objp->instance].ship_info_index].model_num;

    if ( Fred_running ) return;

    pm = model_get(model_num);

    if (pm->shield.ntris<1) return;

    //	Scan all the triangles in the mesh.
    for (i=0; i<pm->shield.ntris; i++ )	{
        int		j;
        vec3d	gnorm, v2f, tri_point;
        vertex prev_pnt, pnt0;
        shield_tri *tri;

        tri = &pm->shield.tris[i];

        if (i == Break_value)
            Int3();

        //	Hack! Only works for object in identity orientation.
        //	Need to rotate eye position into object's reference frame.
        //	Only draw facing triangles.
        vm_vec_rotate(&tri_point, &pm->shield.verts[tri->verts[0]].pos, &Eye_matrix);
        vm_vec_add2(&tri_point, &objp->pos);

        vm_vec_sub(&v2f, &tri_point, &Eye_position);
        vm_vec_unrotate(&gnorm, &tri->norm, &objp->orient);

        if (vm_vec_dot(&gnorm, &v2f) < 0.0f) {
            int	intensity;

            intensity = (int) (Ships[objp->instance].shield_integrity[i] * 255);

            if (intensity < 0)
                intensity = 0;
            else if (intensity > 255)
                intensity = 255;

            gr_set_color(0, 0, intensity);

            //	Process the vertices.
            //	Note this rotates each vertex each time it's needed, very dumb.
            for (j=0; j<3; j++ )	{
                vertex tmp;

                // Rotate point into world coordinates
                vm_vec_unrotate(&pnt, &pm->shield.verts[tri->verts[j]].pos, &objp->orient);
                vm_vec_add2(&pnt, &objp->pos);

                // Pnt is now the x,y,z world coordinates of this vert.
                // For this example, I am just drawing a sphere at that
                // point.
                g3_rotate_vertex(&tmp, &pnt);

                if (j)
                    g3_draw_line(&prev_pnt, &tmp);
                else
                    pnt0 = tmp;
                prev_pnt = tmp;
            }

            g3_draw_line(&pnt0, &prev_pnt);
        }
    }
}
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");
}