Skip to content

Commit 47025a7

Browse files
committed
electrical arc upgrade, stage 3: add support for customizing segment depth and using persistent arc points
1 parent 305af2a commit 47025a7

File tree

10 files changed

+114
-38
lines changed

10 files changed

+114
-38
lines changed

code/debris/debris.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,7 @@ void debris_render(object * obj, model_draw_list *scene)
12011201
if ( vm_vec_dist_quick( &obj->pos, &Eye_position ) < obj->radius*50.0f ) {
12021202
for (auto &arc: db->electrical_arcs) {
12031203
if ( arc.timestamp.isValid() ) {
1204-
model_instance_add_arc( pm, pmi, db->submodel_num, &arc.endpoint_1, &arc.endpoint_2, MARC_TYPE_DAMAGED );
1204+
model_instance_add_arc( pm, pmi, db->submodel_num, &arc.endpoint_1, &arc.endpoint_2, nullptr, MARC_TYPE_DAMAGED );
12051205
}
12061206
}
12071207
}

code/model/model.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,12 @@ struct electrical_arc
107107
vec3d endpoint_1;
108108
vec3d endpoint_2;
109109
ubyte type; // see MARC_TYPE_* defines
110+
ubyte segment_depth; // number of times to divide the arc into segments
110111
};
111112

112113
struct model_electrical_arc : electrical_arc
113114
{
115+
const SCP_vector<vec3d> *persistent_arc_points;
114116
};
115117

116118
// Data specific to a particular instance of a submodel.
@@ -1217,8 +1219,8 @@ extern void model_set_up_techroom_instance(ship_info *sip, int model_instance_nu
12171219
void model_replicate_submodel_instance(polymodel *pm, polymodel_instance *pmi, int submodel_num, flagset<Ship::Subsystem_Flags>& flags);
12181220

12191221
// Adds an electrical arcing effect to a submodel
1220-
void model_instance_clear_arcs(polymodel *pm, polymodel_instance *pmi);
1221-
void model_instance_add_arc(polymodel *pm, polymodel_instance *pmi, int sub_model_num, vec3d *v1, vec3d *v2, int arc_type, color *primary_color_1 = nullptr, color *primary_color_2 = nullptr, color *secondary_color = nullptr, float width = 0.0f);
1222+
void model_instance_clear_arcs(const polymodel *pm, polymodel_instance *pmi);
1223+
void model_instance_add_arc(const polymodel *pm, polymodel_instance *pmi, int sub_model_num, const vec3d *v1, const vec3d *v2, const SCP_vector<vec3d> *persistent_arc_points, ubyte arc_type, const color *primary_color_1 = nullptr, const color *primary_color_2 = nullptr, const color *secondary_color = nullptr, float width = 0.0f, ubyte segment_depth = 4);
12221224

12231225
// Gets two random points on the surface of a submodel
12241226
extern vec3d submodel_get_random_point(int model_num, int submodel_num, int seed = -1);

code/model/modelinterp.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -785,15 +785,13 @@ void model_draw_bay_paths_htl(int model_num)
785785
gr_set_cull(cull);
786786
}
787787

788-
SCP_vector<vec3d> Arc_segment_points;
789-
790-
void interp_render_arc_segment(const vec3d *v1, const vec3d *v2, int depth )
788+
void interp_generate_arc_segment(SCP_vector<vec3d> &arc_segment_points, const vec3d *v1, const vec3d *v2, ubyte depth_limit, ubyte depth)
791789
{
792790
float d = vm_vec_dist_quick( v1, v2 );
793-
const float scaler = 0.30f;
791+
constexpr float scaler = 0.30f;
794792

795-
if ( (d < scaler) || (depth > 4) ) {
796-
Arc_segment_points.push_back(*v2);
793+
if ( (d < scaler) || (depth > depth_limit) ) {
794+
arc_segment_points.push_back(*v2);
797795
} else {
798796
// divide in half
799797
vec3d tmp;
@@ -804,8 +802,8 @@ void interp_render_arc_segment(const vec3d *v1, const vec3d *v2, int depth )
804802
tmp.xyz.z += (frand() - 0.5f) * d * scaler;
805803

806804
// add additional point
807-
interp_render_arc_segment( v1, &tmp, depth+1 );
808-
interp_render_arc_segment( &tmp, v2, depth+1 );
805+
interp_generate_arc_segment( arc_segment_points, v1, &tmp, depth_limit, depth+1 );
806+
interp_generate_arc_segment( arc_segment_points, &tmp, v2, depth_limit, depth+1 );
809807
}
810808
}
811809

code/model/modelread.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5195,7 +5195,7 @@ void model_do_intrinsic_motions(object *objp)
51955195
}
51965196
}
51975197

5198-
void model_instance_clear_arcs(polymodel *pm, polymodel_instance *pmi)
5198+
void model_instance_clear_arcs(const polymodel *pm, polymodel_instance *pmi)
51995199
{
52005200
Assert(pm->id == pmi->model_num);
52015201

@@ -5205,7 +5205,7 @@ void model_instance_clear_arcs(polymodel *pm, polymodel_instance *pmi)
52055205
}
52065206

52075207
// Adds an electrical arcing effect to a submodel
5208-
void model_instance_add_arc(polymodel *pm, polymodel_instance *pmi, int sub_model_num, vec3d *v1, vec3d *v2, int arc_type, color *primary_color_1, color *primary_color_2, color *secondary_color, float width )
5208+
void model_instance_add_arc(const polymodel *pm, polymodel_instance *pmi, int sub_model_num, const vec3d *v1, const vec3d *v2, const SCP_vector<vec3d> *persistent_arc_points, ubyte arc_type, const color *primary_color_1, const color *primary_color_2, const color *secondary_color, float width, ubyte segment_depth)
52095209
{
52105210
Assert(pm->id == pmi->model_num);
52115211

@@ -5223,9 +5223,11 @@ void model_instance_add_arc(polymodel *pm, polymodel_instance *pmi, int sub_mode
52235223
smi->electrical_arcs.emplace_back();
52245224
auto &new_arc = smi->electrical_arcs.back();
52255225

5226-
new_arc.type = static_cast<ubyte>(arc_type);
5226+
new_arc.type = arc_type;
52275227
new_arc.endpoint_1 = *v1;
52285228
new_arc.endpoint_2 = *v2;
5229+
new_arc.persistent_arc_points = persistent_arc_points;
5230+
new_arc.segment_depth = segment_depth;
52295231

52305232
if (arc_type == MARC_TYPE_SHIP || arc_type == MARC_TYPE_SCRIPTED) {
52315233
new_arc.primary_color_1 = *primary_color_1;

code/model/modelrender.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@ extern int Model_polys;
4040
extern int tiling;
4141
extern float model_radius;
4242

43-
extern SCP_vector<vec3d> Arc_segment_points;
44-
4543
extern bool Scene_framebuffer_in_frame;
4644
color Wireframe_color;
4745

48-
extern void interp_render_arc_segment(const vec3d *v1, const vec3d *v2, int depth);
46+
extern void interp_generate_arc_segment(SCP_vector<vec3d> &arc_segment_points, const vec3d *v1, const vec3d *v2, ubyte depth_limit, ubyte depth);
4947

5048
int model_render_determine_elapsed_time(int objnum, uint64_t flags);
5149

@@ -444,7 +442,7 @@ void model_draw_list::add_submodel_to_batch(int model_num)
444442
TransformBufferHandler.set_model_transform(transform, model_num);
445443
}
446444

447-
void model_draw_list::add_arc(const vec3d *v1, const vec3d *v2, const color *primary, const color *secondary, float arc_width)
445+
void model_draw_list::add_arc(const vec3d *v1, const vec3d *v2, const SCP_vector<vec3d> *persistent_arc_points, const color *primary, const color *secondary, float arc_width, ubyte segment_depth)
448446
{
449447
arc_effect new_arc;
450448

@@ -454,6 +452,8 @@ void model_draw_list::add_arc(const vec3d *v1, const vec3d *v2, const color *pri
454452
new_arc.primary = *primary;
455453
new_arc.secondary = *secondary;
456454
new_arc.width = arc_width;
455+
new_arc.segment_depth = segment_depth;
456+
new_arc.persistent_arc_points = persistent_arc_points;
457457

458458
Arcs.push_back(new_arc);
459459
}
@@ -623,7 +623,7 @@ void model_draw_list::render_arc(const arc_effect &arc)
623623
{
624624
g3_start_instance_matrix(&arc.transform);
625625

626-
model_render_arc(&arc.v1, &arc.v2, &arc.primary, &arc.secondary, arc.width);
626+
model_render_arc(&arc.v1, &arc.v2, arc.persistent_arc_points, &arc.primary, &arc.secondary, arc.width, arc.segment_depth);
627627

628628
g3_done_instance(true);
629629
}
@@ -887,7 +887,7 @@ void model_render_add_lightning(model_draw_list *scene, const model_render_param
887887

888888
// render the actual arc segment
889889
if (width > 0.0f)
890-
scene->add_arc(&arc.endpoint_1, &arc.endpoint_2, &primary, &secondary, width);
890+
scene->add_arc(&arc.endpoint_1, &arc.endpoint_2, arc.persistent_arc_points, &primary, &secondary, width, arc.segment_depth);
891891
}
892892
}
893893

@@ -2493,23 +2493,36 @@ void model_render_insignias(const insignia_draw_data *insignia_data)
24932493
}
24942494
}
24952495

2496-
void model_render_arc(const vec3d *v1, const vec3d *v2, const color *primary, const color *secondary, float arc_width)
2496+
SCP_vector<vec3d> Arc_segment_points;
2497+
2498+
void model_render_arc(const vec3d *v1, const vec3d *v2, const SCP_vector<vec3d> *persistent_arc_points, const color *primary, const color *secondary, float arc_width, ubyte depth_limit)
24972499
{
2498-
Arc_segment_points.clear();
2500+
int size;
2501+
const vec3d *pvecs;
2502+
2503+
if (persistent_arc_points) {
2504+
size = static_cast<int>(persistent_arc_points->size());
2505+
pvecs = persistent_arc_points->data();
2506+
} else {
2507+
Arc_segment_points.clear();
2508+
2509+
// need to add the first point
2510+
Arc_segment_points.push_back(*v1);
24992511

2500-
// need to add the first point
2501-
Arc_segment_points.push_back(*v1);
2512+
// this should fill in all of the middle, and the last, points
2513+
interp_generate_arc_segment(Arc_segment_points, v1, v2, depth_limit, 0);
25022514

2503-
// this should fill in all of the middle, and the last, points
2504-
interp_render_arc_segment(v1, v2, 0);
2515+
size = static_cast<int>(Arc_segment_points.size());
2516+
pvecs = Arc_segment_points.data();
2517+
}
25052518

25062519
// use primary color for fist pass
25072520
Assert( primary );
25082521

2509-
g3_render_rod(primary, static_cast<int>(Arc_segment_points.size()), Arc_segment_points.data(), arc_width);
2522+
g3_render_rod(primary, size, pvecs, arc_width);
25102523

25112524
if (secondary) {
2512-
g3_render_rod(secondary, static_cast<int>(Arc_segment_points.size()), Arc_segment_points.data(), arc_width * 0.33f);
2525+
g3_render_rod(secondary, size, pvecs, arc_width * 0.33f);
25132526
}
25142527
}
25152528

code/model/modelrender.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ struct arc_effect
164164
color primary;
165165
color secondary;
166166
float width;
167+
ubyte segment_depth;
168+
169+
const SCP_vector<vec3d> *persistent_arc_points;
167170
};
168171

169172
struct insignia_draw_data
@@ -281,7 +284,7 @@ class model_draw_list
281284
void pop_transform();
282285
void set_scale(const vec3d *scale = NULL);
283286

284-
void add_arc(const vec3d *v1, const vec3d *v2, const color *primary, const color *secondary, float arc_width);
287+
void add_arc(const vec3d *v1, const vec3d *v2, const SCP_vector<vec3d> *persistent_arc_points, const color *primary, const color *secondary, float arc_width, ubyte segment_depth);
285288
void render_arcs();
286289

287290
void add_insignia(const model_render_params *params, const polymodel *pm, int detail_level, int bitmap_num);
@@ -308,7 +311,7 @@ void submodel_render_immediate(const model_render_params* render_info, const pol
308311
void submodel_render_queue(const model_render_params* render_info, model_draw_list* scene, const polymodel* pm, const polymodel_instance* pmi, int submodel_num, const matrix* orient, const vec3d* pos);
309312
void model_render_buffers(model_draw_list* scene, model_material* rendering_material, const model_render_params* interp, const vertex_buffer* buffer, const polymodel* pm, int mn, int detail_level, uint tmap_flags);
310313
bool model_render_check_detail_box(const vec3d* view_pos, const polymodel* pm, int submodel_num, uint64_t flags);
311-
void model_render_arc(const vec3d* v1, const vec3d* v2, const color* primary, const color* secondary, float arc_width);
314+
void model_render_arc(const vec3d* v1, const vec3d* v2, const SCP_vector<vec3d> *persistent_arc_points, const color* primary, const color* secondary, float arc_width, ubyte depth_limit);
312315
void model_render_insignias(const insignia_draw_data* insignia);
313316
void model_render_set_wireframe_color(const color* clr);
314317
bool render_tech_model(tech_render_type model_type, int x1, int y1, int x2, int y2, float zoom, bool lighting, int class_idx, const matrix* orient, const SCP_string& pof_filename = "", float closeup_zoom = 0, const vec3d* closeup_pos = &vmd_zero_vector);

code/scripting/api/objs/ship.cpp

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
extern void ship_reset_disabled_physics(object *objp, int ship_class);
4242
extern bool sexp_check_flag_arrays(const char *flag_name, Object::Object_Flags &object_flag, Ship::Ship_Flags &ship_flags, Mission::Parse_Object_Flags &parse_obj_flag, AI::AI_Flags &ai_flag);
4343
extern void sexp_alter_ship_flag_helper(object_ship_wing_point_team &oswpt, bool future_ships, Object::Object_Flags object_flag, Ship::Ship_Flags ship_flag, Mission::Parse_Object_Flags parse_obj_flag, AI::AI_Flags ai_flag, bool set_flag);
44+
extern void interp_generate_arc_segment(SCP_vector<vec3d> &arc_segment_points, const vec3d *v1, const vec3d *v2, ubyte depth_limit, ubyte depth);
4445

4546
namespace scripting {
4647
namespace api {
@@ -2753,8 +2754,9 @@ ADE_FUNC(jettison, l_Ship, "number jettison_speed, [ship... dockee_ships /* All
27532754
return jettison_helper(L, docker_objh, jettison_speed, 2);
27542755
}
27552756

2756-
ADE_FUNC(AddElectricArc, l_Ship, "vector firstPoint, vector secondPoint, number duration, number width",
2757-
"Creates an electric arc on the ship between two points in the ship's reference frame, for the specified duration in seconds, and the specified width in meters.",
2757+
ADE_FUNC(AddElectricArc, l_Ship, "vector firstPoint, vector secondPoint, number duration, number width, [number segment_depth, boolean persistent_points]",
2758+
"Creates an electric arc on the ship between two points in the ship's reference frame, for the specified duration in seconds, and the specified width in meters. Optionally, "
2759+
"specify the segment depth (the number of times the spark is divided) and whether to generate a set of arc points that will persist from frame to frame.",
27582760
"number",
27592761
"The arc index if successful, 0 otherwise")
27602762
{
@@ -2763,8 +2765,10 @@ ADE_FUNC(AddElectricArc, l_Ship, "vector firstPoint, vector secondPoint, number
27632765
vec3d* v2;
27642766
float duration = 0.0f;
27652767
float width = 0.0f;
2768+
int segment_depth = 4;
2769+
bool persistent_points = false;
27662770

2767-
if (!ade_get_args(L, "oooff", l_Ship.GetPtr(&objh), l_Vector.GetPtr(&v1), l_Vector.GetPtr(&v2), &duration, &width))
2771+
if (!ade_get_args(L, "oooff|ib", l_Ship.GetPtr(&objh), l_Vector.GetPtr(&v1), l_Vector.GetPtr(&v2), &duration, &width, &segment_depth, &persistent_points))
27682772
return ade_set_error(L, "i", 0);
27692773

27702774
if (!objh->isValid())
@@ -2789,6 +2793,19 @@ ADE_FUNC(AddElectricArc, l_Ship, "vector firstPoint, vector secondPoint, number
27892793
arc->type = MARC_TYPE_SCRIPTED;
27902794

27912795
arc->width = width;
2796+
arc->segment_depth = static_cast<ubyte>(segment_depth);
2797+
2798+
// we might want to generate the arc points ahead of time, rather than every frame
2799+
if (persistent_points)
2800+
{
2801+
arc->persistent_arc_points.reset(new SCP_vector<vec3d>());
2802+
2803+
// need to add the first point
2804+
arc->persistent_arc_points->push_back(*v1);
2805+
2806+
// this should fill in all of the middle, and the last, points
2807+
interp_generate_arc_segment(*arc->persistent_arc_points, v1, v2, static_cast<ubyte>(segment_depth), 1); // start at depth 1 for the benefit of Lua
2808+
}
27922809

27932810
return ade_set_args(L, "i", static_cast<int>(arc - shipp->electrical_arcs.data()) + 1); // FS2 -> Lua
27942811
}
@@ -2821,8 +2838,9 @@ ADE_FUNC(DeleteElectricArc, l_Ship, "number index",
28212838
return ADE_RETURN_NIL;
28222839
}
28232840

2824-
ADE_FUNC(ModifyElectricArc, l_Ship, "number index, vector firstPoint, vector secondPoint, [number width]",
2825-
"Sets the endpoints (in the ship's reference frame) and width of the specified electric arc on the ship, .",
2841+
ADE_FUNC(ModifyElectricArc, l_Ship, "number index, vector firstPoint, vector secondPoint, [number width, number segment_depth, boolean persistent_points]",
2842+
"Sets the endpoints (in the ship's reference frame), width, and segment depth of the specified electric arc on the ship, plus whether the arc has persistent points. "
2843+
"If this arc already had a collection of persistent points and it still does after this function is called, the points will be regenerated.",
28262844
nullptr,
28272845
nullptr)
28282846
{
@@ -2831,8 +2849,10 @@ ADE_FUNC(ModifyElectricArc, l_Ship, "number index, vector firstPoint, vector sec
28312849
vec3d* v1;
28322850
vec3d* v2;
28332851
float width = 0.0f;
2852+
int segment_depth = 4;
2853+
bool persistent_points = false;
28342854

2835-
int args = ade_get_args(L, "oioo|f", l_Ship.GetPtr(&objh), &index, l_Vector.GetPtr(&v1), l_Vector.GetPtr(&v2), &width);
2855+
int args = ade_get_args(L, "oioo|fib", l_Ship.GetPtr(&objh), &index, l_Vector.GetPtr(&v1), l_Vector.GetPtr(&v2), &width, &segment_depth, &persistent_points);
28362856
if (args < 4)
28372857
return ADE_RETURN_NIL;
28382858

@@ -2848,8 +2868,35 @@ ADE_FUNC(ModifyElectricArc, l_Ship, "number index, vector firstPoint, vector sec
28482868
arc.endpoint_1 = *v1;
28492869
arc.endpoint_2 = *v2;
28502870

2851-
if (args == 5)
2871+
if (args >= 5)
28522872
arc.width = width;
2873+
if (args >= 6)
2874+
arc.segment_depth = static_cast<ubyte>(segment_depth);
2875+
if (args >= 7)
2876+
{
2877+
if (persistent_points)
2878+
{
2879+
if (!arc.persistent_arc_points)
2880+
arc.persistent_arc_points.reset(new SCP_vector<vec3d>());
2881+
}
2882+
else
2883+
{
2884+
if (arc.persistent_arc_points)
2885+
arc.persistent_arc_points.reset();
2886+
}
2887+
}
2888+
2889+
// persistent points need to be regenerated when the arc is moved; they also need to be generated if we are adding them for the first time
2890+
if (arc.persistent_arc_points)
2891+
{
2892+
arc.persistent_arc_points->clear();
2893+
2894+
// need to add the first point
2895+
arc.persistent_arc_points->push_back(*v1);
2896+
2897+
// this should fill in all of the middle, and the last, points
2898+
interp_generate_arc_segment(*arc.persistent_arc_points, v1, v2, static_cast<ubyte>(segment_depth), 1); // start at depth 1 for the benefit of Lua
2899+
}
28532900
}
28542901

28552902
return ADE_RETURN_NIL;

code/ship/ship.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21394,7 +21394,7 @@ void ship_render(object* obj, model_draw_list* scene)
2139421394
if ( vm_vec_dist_quick( &obj->pos, &Eye_position ) < obj->radius*50.0f && !Rendering_to_shadow_map ) {
2139521395
for (auto &arc: shipp->electrical_arcs) {
2139621396
if (arc.timestamp.isValid()) {
21397-
model_instance_add_arc(pm, pmi, -1, &arc.endpoint_1, &arc.endpoint_2, arc.type, &arc.primary_color_1, &arc.primary_color_2, &arc.secondary_color, arc.width);
21397+
model_instance_add_arc(pm, pmi, -1, &arc.endpoint_1, &arc.endpoint_2, arc.persistent_arc_points.get(), arc.type, &arc.primary_color_1, &arc.primary_color_2, &arc.secondary_color, arc.width, arc.segment_depth);
2139821398
}
2139921399
}
2140021400
}

code/ship/ship.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,9 @@ struct reload_pct
544544
struct ship_electrical_arc : electrical_arc
545545
{
546546
TIMESTAMP timestamp; // When this times out, the spark goes away. Invalid is not used
547+
548+
// if this vector exists, these points will be used instead of the ones generated on each frame by interp_generate_arc_segment()
549+
std::unique_ptr<SCP_vector<vec3d>> persistent_arc_points;
547550
};
548551

549552
// NOTE: Can't be treated as a struct anymore, since it has STL data structures in its object tree!

code/ship/shipfx.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,6 +2087,10 @@ void shipfx_do_lightning_arcs_frame( ship *shipp )
20872087
}
20882088
}
20892089

2090+
arc->segment_depth = 4; // previously hard-coded in interp_generate_arc_segment()
2091+
2092+
arc->persistent_arc_points.reset(); // by default, no persistent points
2093+
20902094
shipp->passive_arc_next_times[passive_arc_info_idx] = _timestamp(fl2i(arc_info->frequency * MILLISECONDS_PER_SECOND));
20912095
}
20922096
}
@@ -2236,6 +2240,10 @@ void shipfx_do_lightning_arcs_frame( ship *shipp )
22362240
arc->type = MARC_TYPE_DAMAGED;
22372241
}
22382242

2243+
arc->segment_depth = 4; // previously hard-coded in interp_generate_arc_segment()
2244+
2245+
arc->persistent_arc_points.reset(); // by default, no persistent points
2246+
22392247
num_damage_arcs++;
22402248
}
22412249
}

0 commit comments

Comments
 (0)