Exemple #1
0
void view_draw_model_transparent(int tick)
{
	int					n;
	obj_type			*obj;
	proj_type			*proj;

		// setup draw
		
	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();

		// render the models
		// draw backwards to sort back to front

	for (n=(view.render->draw_list.count-1);n>=0;n--) {

		switch (view.render->draw_list.items[n].type) {

			case view_render_type_object:
				obj=&server.objs[view.render->draw_list.items[n].idx];
				if ((view.render->draw_list.items[n].flag&view_list_item_flag_model_in_view)!=0x0) render_model_transparent(&obj->draw);
				break;

			case view_render_type_projectile:
				proj=&server.projs[view.render->draw_list.items[n].idx];
				render_model_transparent(&proj->draw);
				break;

		}
	}
}
Exemple #2
0
void render_map_liquid_transparent(int tick)
{
	int					n;
	map_liquid_type		*liq;

		// setup view

	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();
	
		// setup drawing

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	glEnable(GL_ALPHA_TEST);
	glAlphaFunc(GL_NOTEQUAL,0);
						
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glDepthMask(GL_FALSE);
	
		// draw transparent liquids
		
	for (n=0;n!=view.render->draw_list.count;n++) {
		if (view.render->draw_list.items[n].type==view_render_type_liquid) {
			liq=&map.liquid.liquids[view.render->draw_list.items[n].idx];
			if (liquid_is_transparent(liq)) {
				liquid_render_liquid(tick,liq);
			}
		}
	}
}
Exemple #3
0
void view_draw_model_opaque(int tick)
{
	int					n;
	obj_type			*obj;
	proj_type			*proj;

		// setup draw
		
	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();

		// render the models

	for (n=0;n!=view.render->draw_list.count;n++) {

		switch (view.render->draw_list.items[n].type) {

			case view_render_type_object:
				obj=&server.objs[view.render->draw_list.items[n].idx];
				render_model_setup(tick,&obj->draw);
				if ((view.render->draw_list.items[n].flag&view_list_item_flag_model_in_view)!=0x0) render_model_opaque(&obj->draw);
				break;

			case view_render_type_projectile:
				proj=&server.projs[view.render->draw_list.items[n].idx];
				render_model_setup(tick,&proj->draw);
				render_model_opaque(&proj->draw);
				break;

		}
	}
}
Exemple #4
0
void view_draw_models_final(void)
{
	int					n;
	bool				shadow_on;
	d3col				col;
	obj_type			*obj;
	proj_type			*proj;

		// setup draw
		
	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();

		// shadow overrides

	shadow_on=(setup.shadow_on) && (!view.render->no_shadow);

		// render the shadows, remote names,
		// and any debugging information

	for (n=0;n!=view.render->draw_list.count;n++) {

		switch (view.render->draw_list.items[n].type) {

			case view_render_type_object:
				obj=&server.objs[view.render->draw_list.items[n].idx];
				
				if ((shadow_on) && (obj->draw.shadow.on)) {
					if ((view.render->draw_list.items[n].flag&view_list_item_flag_shadow_in_view)!=0x0) shadow_render_model(&obj->draw);
				}
				
				if ((view.render->draw_list.items[n].flag&view_list_item_flag_model_in_view)!=0x0) {
					if (obj->remote.on) remote_draw_status(obj);
					if (object_is_targetted(obj,&col)) render_model_target(&obj->draw,&col);
					if (dim3_debug) {
						view_draw_debug_bounding_box(obj);
						view_draw_object_path(obj);
					}
				}
				break;

			case view_render_type_projectile:
				proj=&server.projs[view.render->draw_list.items[n].idx];
				if ((shadow_on) && (proj->draw.shadow.on)) {
					if ((view.render->draw_list.items[n].flag&view_list_item_flag_shadow_in_view)!=0x0) shadow_render_model(&proj->draw);
				}
				break;

		}
	}
}
Exemple #5
0
void gl_project_fix_rotation(int *x,int *y,int *z)
{
	double			dx,dy,dz,dx2,dy2,dz2;

		// remember current settings

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();

		// translate from non-rotated 3D space
		// to rotated 3D space
		
	dx=(double)(*x);
	dy=(double)(*y);
	dz=(double)(*z);

	gl_3D_view();
	gl_setup_project();
	gluProject(dx,dy,dz,mod_matrix,proj_matrix,(GLint*)vport,&dx2,&dy2,&dz2);

	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();
	gluUnProject(dx2,dy2,dz2,mod_matrix,proj_matrix,(GLint*)vport,&dx,&dy,&dz);

	*x=((int)dx);
	*y=((int)dy);
	*z=((int)dz);

		// restore settings

	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	gl_setup_project();
}
Exemple #6
0
void view_draw_mesh_shadows(void)
{
	int					n;

		// shadows on?
	
	if ((!setup.shadow_on) || (view.render->no_shadow)) return;

		// setup draw
		
	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();

		// render the shadows

	for (n=0;n!=view.render->draw_list.count;n++) {
		if (view.render->draw_list.items[n].type!=view_render_type_mesh) continue;
		if (map.mesh.meshes[view.render->draw_list.items[n].idx].flag.shadow) shadow_render_mesh(view.render->draw_list.items[n].idx);
	}
}
Exemple #7
0
void view_draw_scene_build(int tick)
{
		// setup projection

	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();
	
		// compile all lights in map
		
	gl_lights_compile(tick);

		// setup draw lists

	view_create_area_mask();
	view_start_draw_list();

		// add mesh and liquids to draw list

	view_add_mesh_draw_list();
	view_add_liquid_draw_list();
	
		// setup objects and projectiles
		// and add to draw list
		
	view_setup_objects(tick);
	view_setup_projectiles(tick);

		// add scene effects

	view_add_effect_draw_list(tick);

		// add scene halos
		
	halo_draw_clear();
	view_add_halos();
}
Exemple #8
0
void remote_draw_names_setup(void)
{
	int						n,x,y,z,dist;
	bool					hit,has_tag;
	d3pnt					spt,ept,hpt;
	obj_type				*obj;
	model_type				*mdl;
	ray_trace_contact_type	contact;
	
	if (!net_setup.client.joined) return;
	if (!setup.network.show_names) return;
	
		// clear all name draws
	
	obj=server.objs;
	
	for (n=0;n!=server.count.obj;n++) {
		obj->draw.remote_name.on=FALSE;
		obj++;
	}

		// remove names behind z or off-screen
		// ignore console as it won't matter for projection
		
	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();
	
	for (n=0;n!=view.render->draw_list.count;n++) {
		if (view.render->draw_list.items[n].type!=view_render_type_object) continue;
		obj=&server.objs[view.render->draw_list.items[n].idx];
		
		if (!obj->player) continue;
		if (obj->hidden) continue;
		
			// get name point
		
		has_tag=FALSE;

		mdl=NULL;
		if ((obj->draw.uid!=-1) && (obj->draw.on)) mdl=model_find_uid(obj->draw.uid);

		if (mdl!=NULL) {
			x=obj->pnt.x;
			y=obj->pnt.y;
			z=obj->pnt.z;
			has_tag=model_get_name_position(mdl,&obj->draw.setup,&x,&y,&z);
		}

		if (!has_tag) {
			x=obj->pnt.x;
			y=(obj->pnt.y-obj->size.y)-map_enlarge;
			z=obj->pnt.z;
		}
		
			// translate and rotate point
			
		dist=distance_get(x,y,z,view.render->camera.pnt.x,view.render->camera.pnt.y,view.render->camera.pnt.z);
		if (dist>=remote_name_max_distance) continue;

		obj->draw.remote_name.pnt.x=x;
		obj->draw.remote_name.pnt.y=y;
		obj->draw.remote_name.pnt.z=z;
		
			// is it behind the z?

		if (!gl_project_in_view_z(x,y,z)) continue;
				
			// project names

		gl_project_point(&x,&y,&z);

		obj->draw.remote_name.proj_pnt.x=x;
		obj->draw.remote_name.proj_pnt.y=y;
		obj->draw.remote_name.proj_pnt.z=z;
		
			// calculate the fade
			
		if (dist<remote_name_min_distance) {
			obj->draw.remote_name.fade=1.0f;
		}
		else {
			obj->draw.remote_name.fade=1.0f-((float)(dist-remote_name_min_distance)/(float)(remote_name_max_distance-remote_name_min_distance));
		}
		
		obj->draw.remote_name.size=hud.font.text_size_medium-(int)((float)(hud.font.text_size_medium*dist)/(float)(remote_name_max_distance-remote_name_min_distance));
		if (obj->draw.remote_name.size<10) obj->draw.remote_name.size=10;
		
		obj->draw.remote_name.on=TRUE;
	}

		// ray trace remote name to camera's eye level
		// to check for visibility

	ept.x=view.render->camera.pnt.x;
	ept.y=view.render->camera.pnt.y;
	ept.z=view.render->camera.pnt.z;

	contact.obj.on=TRUE;
	contact.proj.on=FALSE;

	contact.hit_mode=poly_ray_trace_hit_mode_all;
	contact.origin=poly_ray_trace_origin_object;

	for (n=0;n!=server.count.obj;n++) {
		obj=&server.objs[n];
		if (!obj->draw.remote_name.on) continue;

		spt.x=obj->draw.remote_name.pnt.x;
		spt.y=obj->draw.remote_name.pnt.y;
		spt.z=obj->draw.remote_name.pnt.z;

		contact.obj.ignore_uid=obj->uid;
		
		hit=ray_trace_map_by_point(&spt,&ept,&hpt,&contact);
		
		if (camera.mode==cv_fpp) {
			if (hit) {
				if (contact.obj.uid!=server.player_obj_uid) {
					obj->draw.remote_name.on=FALSE;
					continue;
				}
			}
			else {
				obj->draw.remote_name.on=FALSE;
				continue;
			}
		}
		else {
			if (hit) {
				obj->draw.remote_name.on=FALSE;
				continue;
			}
		}
	}
}
Exemple #9
0
void view_draw_debug_info(d3pnt *pnt,d3pnt *size,int count,char *strs)
{
	int						n,x,y,dist;
	d3col					col;
	d3pnt					spt,ept,win_pnt;
	ray_trace_contact_type	contact;

		// only show closer objects

	dist=distance_get(pnt->x,pnt->y,pnt->z,view.render->camera.pnt.x,view.render->camera.pnt.y,view.render->camera.pnt.z);
	if (dist>25000) return;

		// ray trace check

	spt.x=pnt->x;
	spt.y=pnt->y-size->y;
	spt.z=pnt->z;

	ept.x=view.render->camera.pnt.x;
	ept.y=view.render->camera.pnt.y;
	ept.z=view.render->camera.pnt.z;

	contact.obj.on=FALSE;
	contact.proj.on=FALSE;

	contact.origin=poly_ray_trace_origin_object;

	if (ray_trace_map_by_point(&spt,&ept,&contact)) return;

		// project the mid point

	win_pnt.x=pnt->x;
	win_pnt.y=pnt->y-size->y;
	win_pnt.z=pnt->z;

	gl_project_point(&win_pnt);

		// draw the info

	gl_2D_view_interface();
	
	glDisable(GL_DEPTH_TEST);
	
		// covert to interface resolution

	x=(win_pnt.x*iface.scale_x)/view.screen.x_sz;
	y=((view.screen.y_sz-win_pnt.y)*iface.scale_y)/view.screen.y_sz;

	y-=(iface.font.text_size_small*count);

		// draw text

	col.r=col.b=1.0f;
	col.g=0.0f;
	
	gl_text_start(font_hud_index,iface.font.text_size_small,FALSE);

	for (n=0;n!=count;n++) {
		y+=iface.font.text_size_small;
		gl_text_draw(x,y,(char*)&strs[n*128],tx_center,FALSE,&col,1.0f);
	}

	gl_text_end();

	glEnable(GL_DEPTH_TEST);

		// restore original projection

	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
}
Exemple #10
0
void draw_sky_cube(int tick)
{
    int					k,txt_id,offset;
    float				txt_fact,txt_x_shift,txt_y_shift;
	texture_type		*texture;
					
		// texture sizes
		
	txt_fact=map.sky.txt_fact;
	
	txt_x_shift=((float)tick*0.0005f)*map.sky.txt_x_shift;
	k=(int)txt_x_shift;
	txt_x_shift=txt_x_shift-(float)k;
	
	txt_y_shift=((float)tick*0.0005f)*map.sky.txt_y_shift;
	k=(int)txt_y_shift;
	txt_y_shift=txt_y_shift-(float)k;

		// setup view

	gl_3D_view();
	gl_3D_rotate(NULL,&view.render->camera.ang);
	gl_setup_project();

		// setup texture
		
	gl_texture_simple_start();

	glDisable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_DEPTH_TEST);

	glMatrixMode(GL_TEXTURE);
	glTranslatef(txt_x_shift,txt_y_shift,0.0f);
	glScalef(txt_fact,txt_fact,1.0f);

		// bind VBO

	view_bind_sky_vertex_object();

		// draw cube sides

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3,GL_FLOAT,0,(void*)0);
		
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(2,GL_FLOAT,0,(void*)(((6*4)*3)*sizeof(float)));

	offset=0;

	if (map.sky.fill!=-1) {
		texture=&map.textures[map.sky.fill];
		txt_id=texture->frames[texture->animate.current_frame].bitmap.gl_id;

		gl_texture_simple_set(txt_id,FALSE,1,1,1,1);
		glDrawArrays(GL_QUADS,0,4);
		
		offset+=4;
	}
	
		// bottom
		
	if (map.sky.bottom_fill!=-1) {
		texture=&map.textures[map.sky.bottom_fill];
		txt_id=texture->frames[texture->animate.current_frame].bitmap.gl_id;

		gl_texture_simple_set(txt_id,FALSE,1,1,1,1);
		glDrawArrays(GL_QUADS,offset,4);
		
		offset+=4;
	}
	
		// north
		
	if (map.sky.north_fill!=-1) {
		texture=&map.textures[map.sky.north_fill];
		txt_id=texture->frames[texture->animate.current_frame].bitmap.gl_id;

		gl_texture_simple_set(txt_id,FALSE,1,1,1,1);
		glDrawArrays(GL_QUADS,offset,4);
		
		offset+=4;
	}
	
		// east

	if (map.sky.east_fill!=-1) {
		texture=&map.textures[map.sky.east_fill];
		txt_id=texture->frames[texture->animate.current_frame].bitmap.gl_id;

		gl_texture_simple_set(txt_id,FALSE,1,1,1,1);
		glDrawArrays(GL_QUADS,offset,4);
		
		offset+=4;
	}
	
		// south

	if (map.sky.south_fill!=-1) {
		texture=&map.textures[map.sky.south_fill];
		txt_id=texture->frames[texture->animate.current_frame].bitmap.gl_id;

		gl_texture_simple_set(txt_id,FALSE,1,1,1,1);
		glDrawArrays(GL_QUADS,offset,4);
		
		offset+=4;
	}
	
		// west

	if (map.sky.west_fill!=-1) {
		texture=&map.textures[map.sky.west_fill];
		txt_id=texture->frames[texture->animate.current_frame].bitmap.gl_id;

		gl_texture_simple_set(txt_id,FALSE,1,1,1,1);
		glDrawArrays(GL_QUADS,offset,4);
	}

	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);

		// end texture
		
	glLoadIdentity();
	gl_texture_simple_end();

		// unbind the vbo

	view_unbind_sky_vertex_object();
}
Exemple #11
0
void draw_sky_dome_hemisphere(int tick)
{
    int					k,txt_id,dome_cnt,trig_cnt;
	float				txt_x_shift,txt_y_shift;
	texture_type		*texture;

		// texture sizes
		
	txt_x_shift=((float)tick*0.0005f)*map.sky.txt_x_shift;
	k=(int)txt_x_shift;
	txt_x_shift=txt_x_shift-(float)k;
	
	txt_y_shift=((float)tick*0.0005f)*map.sky.txt_y_shift;
	k=(int)txt_y_shift;
	txt_y_shift=txt_y_shift-(float)k;

		// setup view

	gl_3D_view();
	gl_3D_rotate(NULL,&view.render->camera.ang);
	gl_setup_project();
	
		// setup texture
		
	gl_texture_simple_start();

	glDisable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_DEPTH_TEST);
	
	glMatrixMode(GL_TEXTURE);
	glTranslatef(txt_x_shift,txt_y_shift,0.0f);

	texture=&map.textures[map.sky.fill];
	txt_id=texture->frames[texture->animate.current_frame].bitmap.gl_id;
	
	gl_texture_simple_set(txt_id,FALSE,1,1,1,1);

		// bind the vbo

	view_bind_sky_vertex_object();

		// quad and trig counts

	dome_cnt=(20*4)*4;
	trig_cnt=20*3;

		// draw the dome
	
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3,GL_FLOAT,0,(void*)0);
		
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(2,GL_FLOAT,0,(void*)(((200*4)*3)*sizeof(float)));

	glDrawArrays(GL_QUADS,0,dome_cnt);
	glDrawArrays(GL_TRIANGLES,dome_cnt,trig_cnt);

	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);

		// end textures
		
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
		
	gl_texture_simple_end();

		// unbind the vbo

	view_unbind_sky_vertex_object();
}
Exemple #12
0
void draw_sky_dome_panoramic(int tick)
{
    int					k,txt_id;
	float				txt_x_shift,txt_y_shift;
	texture_type		*texture;
	
		// texture sizes
		
	txt_x_shift=((float)tick*0.0005f)*map.sky.txt_x_shift;
	k=(int)txt_x_shift;
	txt_x_shift=txt_x_shift-(float)k;
	
	txt_y_shift=((float)tick*0.0005f)*map.sky.txt_y_shift;
	k=(int)txt_y_shift;
	txt_y_shift=txt_y_shift-(float)k;
					
		// setup view

	gl_3D_view();
	gl_3D_rotate(NULL,&view.render->camera.ang);
	gl_setup_project();
	
		// construct VBO

	view_bind_sky_vertex_object();

		// both outside and cap need vertex list

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3,GL_FLOAT,0,(void*)0);

		// draw textured dome
		
	gl_texture_simple_start();

	glDisable(GL_BLEND);
	glDisable(GL_ALPHA_TEST);
	glDisable(GL_DEPTH_TEST);
	
	glMatrixMode(GL_TEXTURE);
	glTranslatef(txt_x_shift,txt_y_shift,0.0f);

	texture=&map.textures[map.sky.fill];
	txt_id=texture->frames[texture->animate.current_frame].bitmap.gl_id;
	
	gl_texture_simple_set(txt_id,FALSE,1,1,1,1);

	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	glTexCoordPointer(2,GL_FLOAT,0,(void*)(((120*4)*3)*sizeof(float)));

	glDrawArrays(GL_QUADS,0,(100*4));

	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
		
	gl_texture_simple_end();

		// draw colored cap

	glColor4f(texture->col.r,texture->col.g,texture->col.b,1.0f);
	glDrawArrays(GL_TRIANGLES,(100*4),(20*3));

		// disable vertex array

	glDisableClientState(GL_VERTEX_ARRAY);

		// unbind the vbo

	view_unbind_sky_vertex_object();
}
Exemple #13
0
void view_draw_scene_render(int tick,obj_type *obj,weapon_type *weap)
{
		// setup projection

	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();

		// draw background and sky
		// unless obscured by fog
	
	if (!fog_solid_on()) {
		draw_background();
		draw_sky(tick);
	}
	else {
		fog_solid_start();
	}

		// setup per-scene shader variables

	gl_shader_draw_scene_initialize();

		// compile meshes for drawing
	
	if (!view_compile_mesh_gl_lists(tick)) return;

		// setup some map polygon drawing flags

	render_map_setup();

		// draw opaque scene items

	render_map_mesh_opaque();
	render_map_liquid_opaque(tick);
	view_draw_model_opaque(tick);
	
		// additional mesh and model drawing
		// shadows, remote names, etc

	view_draw_mesh_shadows();
	view_draw_models_final();
	
		// draw transparent scene items

	render_map_mesh_transparent();
	view_draw_model_transparent(tick);
	render_map_liquid_transparent(tick);

		// draw decals

	decal_render();

		// effects

	effect_draw(tick);
	
		// draw rain
		
	rain_draw(tick);

		// draw fog

	fog_draw_textured(tick);
	
	if (fog_solid_on()) fog_solid_end();
	
		// setup halos, crosshairs, zoom masks
		
	remote_draw_names_setup();
	halo_draw_setup();
	
	if ((obj!=NULL) && (weap!=NULL)) {
		crosshair_setup(tick,obj,weap);
		zoom_setup(tick,obj,weap);
	
			// draw the weapons in hand

		if (camera.mode==cv_fpp) draw_weapon_hand(tick,obj,weap);
	}

		// draw the remote names, halos, crosshairs, and zoom masks
	
	remote_draw_names_render();
	halo_draw_render();
	
	if ((obj!=NULL) && (weap!=NULL)) {
		crosshair_draw(obj,weap);
		zoom_draw(obj,weap);
	}
}
Exemple #14
0
void rain_draw(int tick)
{
	int				n,xadd,yadd,zadd,density,
					slant_add,slant_mult,slant_div;
	float			slant_ang_y;
	float			*vertex_ptr,*col_ptr;
	rain_draw_type	*rain_draw;

		// is rain on and not under liquid?

	if (!map.rain.on) return;
	if (view.render->camera.under_liquid_idx!=-1) return;
	
		// reset on?
		
	if (map.rain.reset) {
		map.rain.reset=FALSE;
		rain_setup(tick,view.render->camera.pnt.x,view.render->camera.pnt.y,view.render->camera.pnt.z);
	}
	
		// rain slant
		
	slant_add=rain_slant_add;
	slant_ang_y=rain_slant_ang_y;
		
	if (map.rain.slant_time_msec!=0) {
		
			// time to change slant?
			
		if (tick>rain_slant_next_end_tick) {
			rain_slant_add=slant_add=rain_slant_next_add;
			rain_slant_ang_y=slant_ang_y=rain_slant_next_ang_y;
			rain_setup_next_slant(tick);
		}
		else {
		
				// slant in the middle of changing
				
			if (tick>rain_slant_next_start_tick) {
				slant_mult=tick-rain_slant_next_start_tick;
				slant_div=(rain_slant_next_end_tick-rain_slant_next_start_tick);
				
				slant_add=rain_slant_add+(((rain_slant_next_add-rain_slant_add)*slant_mult)/slant_div);
				slant_ang_y=rain_slant_ang_y+((rain_slant_next_ang_y-rain_slant_ang_y)*((float)slant_mult/(float)slant_div));
			}
			
		}
	}

	angle_get_movement(slant_ang_y,slant_add,&xadd,&zadd);

		// rain change

	xadd=(tick-rain_last_tick)*xadd;
	yadd=(tick-rain_last_tick)*map.rain.speed;
	zadd=(tick-rain_last_tick)*zadd;
	
	rain_last_tick=tick;

		// rain density

	density=map.rain.density;
	if (density>max_rain_density) density=max_rain_density;

		// construct VBO

	vertex_ptr=view_bind_map_next_vertex_object(((density*2)*(3+4)));
	if (vertex_ptr==NULL) return;

	col_ptr=vertex_ptr+((density*2)*3);

		// create vertexes

	rain_draw=view.rain_draws;

	for (n=0;n!=density;n++) {

			// move rain

		rain_draw->x+=xadd;
		rain_draw->y+=yadd;
		rain_draw->z+=zadd;
		
		if (rain_draw->y>rain_draw->by) rain_setup_single_reset(rain_draw,view.render->camera.pnt.x,view.render->camera.pnt.y,view.render->camera.pnt.z);

			// draw rain

		*vertex_ptr++=(float)rain_draw->x;
		*vertex_ptr++=(float)rain_draw->y;
		*vertex_ptr++=(float)rain_draw->z;

		*col_ptr++=map.rain.start_color.r;
		*col_ptr++=map.rain.start_color.g;
		*col_ptr++=map.rain.start_color.b;
		*col_ptr++=map.rain.alpha;

		*vertex_ptr++=(float)(rain_draw->x+xadd);
		*vertex_ptr++=(float)(rain_draw->y+map.rain.line_length);
		*vertex_ptr++=(float)(rain_draw->z+zadd);

		*col_ptr++=map.rain.end_color.r;
		*col_ptr++=map.rain.end_color.g;
		*col_ptr++=map.rain.end_color.b;
		*col_ptr++=map.rain.alpha;

		rain_draw++;
	}

  	view_unmap_current_vertex_object();

		// setup view

	gl_3D_view();
	gl_3D_rotate(&view.render->camera.pnt,&view.render->camera.ang);
	gl_setup_project();
	
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	glDisable(GL_ALPHA_TEST);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glDepthMask(GL_FALSE);

		// draw the rain

	glLineWidth((float)map.rain.line_width);

	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3,GL_FLOAT,0,(void*)0);
		
	glEnableClientState(GL_COLOR_ARRAY);
	glColorPointer(4,GL_FLOAT,0,(void*)(((density*2)*3)*sizeof(float)));

	glDrawArrays(GL_LINES,0,(density*2));

	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);

	glLineWidth(1);

		// unbind the vbo

	view_unbind_current_vertex_object();
}