Fix #124297: GPv3: Build modifier natural drawing speed fix #124350
@ 766,7 +766,6 @@ static Drawing legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gp


/* Curve Attributes. */


SpanAttributeWriter<bool> stroke_cyclic = attributes.lookup_or_add_for_write_span<bool>(


"cyclic", AttrDomain::Curve);


/* TODO: This should be a `double` attribute. */


SpanAttributeWriter<float> stroke_init_times = attributes.lookup_or_add_for_write_span<float>(


"init_time", AttrDomain::Curve);


SpanAttributeWriter<int8_t> stroke_start_caps = attributes.lookup_or_add_for_write_span<int8_t>(


@ 795,8 +794,8 @@ static Drawing legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gp


}




stroke_cyclic.span[stroke_i] = (gps>flag & GP_STROKE_CYCLIC) != 0;


/* TODO: This should be a `double` attribute. */


stroke_init_times.span[stroke_i] = float(gps>inittime);


/* Truncating time in ms to uint32 then we don't lose precision in lower bits. */


stroke_init_times.span[stroke_i] = float(uint32_t(gps>inittime * double(1e3))) / float(1e3);


ChengduLittleA marked this conversation as resolved
Outdated


stroke_start_caps.span[stroke_i] = int8_t(gps>caps[0]);


stroke_end_caps.span[stroke_i] = int8_t(gps>caps[1]);


ChengduLittleA marked this conversation as resolved
Outdated
Falk David
commented
Use Use `double(1e3)`.
No need to cast to `uint64_t` before casting to `uint32_t`.


stroke_softness.span[stroke_i] = 1.0f  gps>hardness;



@ 591,7 +591,8 @@ struct PaintOperationExecutor {




bke::SpanAttributeWriter<float> init_times = attributes.lookup_or_add_for_write_span<float>(


"init_time", bke::AttrDomain::Curve);


init_times.span[active_curve] = self.start_time_;


/* Truncating time in ms to uint32 then we don't lose precision in lower bits. */


ChengduLittleA marked this conversation as resolved
Outdated
Falk David
commented
Same as above, no need to cast to Same as above, no need to cast to `uint64_t` before casting to `uint32_t`.


init_times.span[active_curve] = float(uint64_t(self.start_time_ * double(1e3))) / float(1e3);


curve_attributes_to_skip.add("init_time");


init_times.finish();





@ 472,24 +472,30 @@ static float get_factor_from_draw_speed(const bke::CurvesGeometry &curves,


const VArray<float> delta_times = *attributes.lookup_or_default<float>(


"delta_time", bke::AttrDomain::Point, 0.0f);




Array<float> times(curves.points_num());


/* For the first stroke, the start time is 0. */


for (const int point : points_by_curve[0]) {


times[point] = delta_times[point];


}


Array<float> start_times(curves.curves_num());


start_times[0] = 0;


filedescriptor marked this conversation as resolved
Outdated
Falk David
commented
I think it's better if we precompute the start times (accounting for the maximum gap) for each curve first, and then go over the points.
The second loop then becomes much simpler. We can even return from there directly:
I think it's better if we precompute the start times (accounting for the maximum gap) for each curve first, and then go over the points.
```cpp
Array<float> start_times(curves.curves_num());
start_times[0] = init_times[0];
float accumulated_shift_delta_time = 0.0f;
for (const int curve : curves.curves_range().drop_front(1)) {
const float previous_start_time = start_times[curve  1];
const float previous_delta_time = delta_times[points_by_curve[curve  1].last()];
const float previous_end_time = previous_start_time + previous_delta_time;
const float shifted_start_time = init_times[curve]  accumulated_shift_delta_time;
const float gap_delta_time = math::min(shifted_start_time  previous_end_time, max_gap);
start_times[curve] = previous_end_time + gap_delta_time;
accumulated_shift_delta_time += math::max(shifted_start_time  start_times[curve], 0.0f);
}
```
The second loop then becomes much simpler. We can even return from there directly:
```cpp
const float limit = time_elapsed * speed_fac;
for (const int curve : curves.curves_range()) {
const float start_time = start_times[curve];
for (const int point : points_by_curve[curve]) {
if (start_time + delta_times[point] >= limit) {
return math::clamp(float(point) / float(curves.points_num()), 0.0f, 1.0f);
}
}
}
```
YimingWu
commented
Thanks for the suggestion. Let me see if I could make this work :D Thanks for the suggestion. Let me see if I could make this work :D
YimingWu
commented
`start_times[0]` needs to be 0 obviously and otherwise it seems to be working fine taking into account of gap limit. Thanks!
Falk David
commented
Hm if Hm if `start_times[0] = 0` then you need to set `float accumulated_shift_delta_time = init_times[0];` so that all the strokes after are also shifted relative to the first stroke start time.
YimingWu
commented
Ah yes, this way the first stroke won't have a gap time Ah yes, this way the first stroke won't have a gap time


float accumulated_shift_delta_time = init_times[0];


for (const int curve : curves.curves_range().drop_front(1)) {


const float previous_init_time = init_times[curve  1];


const float start_time = math::min(init_times[curve]  previous_init_time, max_gap);


const float previous_start_time = start_times[curve  1];


const float previous_delta_time = delta_times[points_by_curve[curve  1].last()];


const float previous_end_time = previous_start_time + previous_delta_time;




const float shifted_start_time = init_times[curve]  accumulated_shift_delta_time;


const float gap_delta_time = math::min(shifted_start_time  previous_end_time, max_gap);




start_times[curve] = previous_end_time + gap_delta_time;


accumulated_shift_delta_time += math::max(shifted_start_time  start_times[curve], 0.0f);


}


const float limit = time_elapsed * speed_fac;


for (const int curve : curves.curves_range()) {


const float start_time = start_times[curve];


for (const int point : points_by_curve[curve]) {


times[point] = start_time + delta_times[point];


}


}


for (const int point : curves.points_range()) {


const float limit = time_elapsed * speed_fac;


if (times[point] >= limit) {


return math::clamp(float(point) / float(curves.points_num()), 0.0f, 1.0f);


if (start_time + delta_times[point] >= limit) {


return math::clamp(float(point) / float(curves.points_num()), 0.0f, 1.0f);


}


}


}




return 1.0f;


}





We can remove this TODO I think