Index: code/model/model.h
===================================================================
--- code/model/model.h	(revision 9461)
+++ code/model/model.h	(working copy)
@@ -824,6 +824,7 @@
 #define MR_FULL_DETAIL				(1<<28)		// render all valid objects, particularly ones that are otherwise in/out of render boxes - taylor
 #define MR_FORCE_CLAMP				(1<<29)		// force clamp - Hery
 #define MR_ANIMATED_SHADER			(1<<30)		// Use a animated Shader - Valathil
+#define MR_ATTACHED_MODEL			(1<<31)		// Used for attached weapon model lodding
 
 // Renders a model and all it's submodels.
 // See MR_? defines for values for flags
Index: code/model/modelinterp.cpp
===================================================================
--- code/model/modelinterp.cpp	(revision 9461)
+++ code/model/modelinterp.cpp	(working copy)
@@ -1993,7 +1993,10 @@
 		cull = gr_set_cull(0);
 	}
 
-	Interp_objnum = objnum;
+	if (flags & MR_ATTACHED_MODEL)
+		Interp_objnum = -1;
+	else
+		Interp_objnum = objnum;
 
 	if ( flags & MR_NO_LIGHTING )	{
 		Interp_light = 1.0f;
@@ -2684,9 +2687,11 @@
 	bool draw_thrusters = false;
 
 	// just to be on the safe side
-	Assert( Interp_objnum == objnum );
+	// If we're dealing with an attached model (i.e. an external weapon model) we need the object number
+	// of the ship that the weapon is attached to, but nothing else
+	Assert((objnum == Interp_objnum && !(flags & MR_ATTACHED_MODEL)));
 
-	if (objnum >= 0) {
+	if (objnum >= 0 && !(flags & MR_ATTACHED_MODEL)) {
 		objp = &Objects[objnum];
 
 		if (objp->type == OBJ_SHIP) {
@@ -2774,34 +2779,40 @@
 
 	vec3d closest_pos;
 	float depth = model_find_closest_point( &closest_pos, model_num, -1, orient, pos, &Eye_position );
+
+	#if MAX_DETAIL_LEVEL != 4
+	#error Code in modelInterp.cpp assumes MAX_DETAIL_LEVEL == 4
+	#endif
+
+	switch( Detail.detail_distance )	{
+	case 0:		// lowest
+		depth /= The_mission.ai_profile->detail_distance_mult[0];
+		break;
+	case 1:		// lower than normal
+		depth /= The_mission.ai_profile->detail_distance_mult[1];
+		break;
+	case 2:		// default
+		depth /= The_mission.ai_profile->detail_distance_mult[2];
+		break;
+	case 3:		// above normal
+		depth /= The_mission.ai_profile->detail_distance_mult[3];
+		break;
+	case 4:		// even more normal
+		depth /= The_mission.ai_profile->detail_distance_mult[4];
+		break;
+	}
+
+	// If we're rendering attached weapon models, check against the ships' tabled Weapon Model Draw Distance (which defaults to 200)
+	if (Interp_flags & MR_ATTACHED_MODEL) {
+		if (depth > Ship_info[Ships[Objects[objnum].instance].ship_info_index].weapon_model_draw_distance)
+			return;
+	}
+
 	if ( pm->n_detail_levels > 1 )	{
 
 		if ( Interp_flags & MR_LOCK_DETAIL )	{
 			i = Interp_detail_level_locked+1;
 		} else {
-
-			#if MAX_DETAIL_LEVEL != 4
-			#error Code in modelInterp.cpp assumes MAX_DETAIL_LEVEL == 4
-			#endif
-
-			switch( Detail.detail_distance )	{
-			case 0:		// lowest
-				depth /= The_mission.ai_profile->detail_distance_mult[0];
-				break;
-			case 1:		// lower than normal
-				depth /= The_mission.ai_profile->detail_distance_mult[1];
-				break;
-			case 2:		// default
-				depth /= The_mission.ai_profile->detail_distance_mult[2];
-				break;
-			case 3:		// above normal
-				depth /= The_mission.ai_profile->detail_distance_mult[3];
-				break;
-			case 4:		// even more normal
-				depth /= The_mission.ai_profile->detail_distance_mult[4];
-				break;
-			}
-
 			// nebula ?
 			if(The_mission.flags & MISSION_FLAG_FULLNEB){
 				depth *= neb2_get_lod_scale(Interp_objnum);
Index: code/ship/ship.cpp
===================================================================
--- code/ship/ship.cpp	(revision 9461)
+++ code/ship/ship.cpp	(working copy)
@@ -6127,6 +6127,7 @@
 				int save_flags = render_flags;
 		
 				render_flags &= ~MR_SHOW_THRUSTERS;
+				render_flags |= MR_ATTACHED_MODEL;
 
 				//primary weapons
 				for (i = 0; i < swp->num_primary_banks; i++) {
@@ -6137,7 +6138,7 @@
 					for(k = 0; k < bank->num_slots; k++) {	
 						polymodel* pm = model_get(Weapon_info[swp->primary_bank_weapons[i]].external_model_num);
 						pm->gun_submodel_rotation = shipp->primary_rotate_ang[i];
-						model_render(Weapon_info[swp->primary_bank_weapons[i]].external_model_num, &vmd_identity_matrix, &bank->pnt[k], render_flags);
+						model_render(Weapon_info[swp->primary_bank_weapons[i]].external_model_num, &vmd_identity_matrix, &bank->pnt[k], render_flags, shipp->objnum);
 						pm->gun_submodel_rotation = 0.0f;
 					}
 				}
@@ -6155,7 +6156,7 @@
 					
 					if (Weapon_info[swp->secondary_bank_weapons[i]].wi_flags2 & WIF2_EXTERNAL_WEAPON_LNCH) {
 						for(k = 0; k < bank->num_slots; k++) {
-							model_render(Weapon_info[swp->secondary_bank_weapons[i]].external_model_num, &vmd_identity_matrix, &bank->pnt[k], render_flags);
+							model_render(Weapon_info[swp->secondary_bank_weapons[i]].external_model_num, &vmd_identity_matrix, &bank->pnt[k], render_flags, shipp->objnum);
 						}
 					} else {
 						num_secondaries_rendered = 0;
@@ -6174,7 +6175,7 @@
 			
 							vm_vec_scale_add2(&secondary_weapon_pos, &vmd_z_vector, -(1.0f-shipp->secondary_point_reload_pct[i][k]) * model_get(Weapon_info[swp->secondary_bank_weapons[i]].external_model_num)->rad);
 
-							model_render(Weapon_info[swp->secondary_bank_weapons[i]].external_model_num, &vmd_identity_matrix, &secondary_weapon_pos, render_flags);
+							model_render(Weapon_info[swp->secondary_bank_weapons[i]].external_model_num, &vmd_identity_matrix, &secondary_weapon_pos, render_flags, shipp->objnum);
 						}
 					}
 				}
