Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/fmodifier.c')
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c141
1 files changed, 103 insertions, 38 deletions
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 2b393b4d90b..19912a19d94 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -141,55 +141,34 @@ static void fcm_generator_verify(FModifier *fcm)
switch (data->mode) {
case FCM_GENERATOR_POLYNOMIAL: /* expanded polynomial expression */
{
+ const int arraysize_new = data->poly_order + 1;
/* arraysize needs to be order+1, so resize if not */
- if (data->arraysize != (data->poly_order + 1)) {
- float *nc;
-
- /* make new coefficients array, and copy over as much data as can fit */
- nc = MEM_callocN(sizeof(float) * (data->poly_order + 1), "FMod_Generator_Coefs");
-
+ if (data->arraysize != arraysize_new) {
if (data->coefficients) {
- if ((int)data->arraysize > (data->poly_order + 1))
- memcpy(nc, data->coefficients, sizeof(float) * (data->poly_order + 1));
- else
- memcpy(nc, data->coefficients, sizeof(float) * data->arraysize);
-
- /* free the old data */
- MEM_freeN(data->coefficients);
+ data->coefficients = MEM_recallocN(data->coefficients, sizeof(float) * arraysize_new);
}
-
- /* set the new data */
- data->coefficients = nc;
- data->arraysize = data->poly_order + 1;
+ else {
+ data->coefficients = MEM_callocN(sizeof(float) * arraysize_new, "FMod_Generator_Coefs");
+ }
+ data->arraysize = arraysize_new;
}
+ break;
}
- break;
-
case FCM_GENERATOR_POLYNOMIAL_FACTORISED: /* expanded polynomial expression */
{
- /* arraysize needs to be 2*order, so resize if not */
- if (data->arraysize != (data->poly_order * 2)) {
- float *nc;
-
- /* make new coefficients array, and copy over as much data as can fit */
- nc = MEM_callocN(sizeof(float) * (data->poly_order * 2), "FMod_Generator_Coefs");
-
+ const int arraysize_new = data->poly_order * 2;
+ /* arraysize needs to be (2 * order), so resize if not */
+ if (data->arraysize != arraysize_new) {
if (data->coefficients) {
- if (data->arraysize > (unsigned int)(data->poly_order * 2))
- memcpy(nc, data->coefficients, sizeof(float) * (data->poly_order * 2));
- else
- memcpy(nc, data->coefficients, sizeof(float) * data->arraysize);
-
- /* free the old data */
- MEM_freeN(data->coefficients);
+ data->coefficients = MEM_recallocN(data->coefficients, sizeof(float) * arraysize_new);
}
-
- /* set the new data */
- data->coefficients = nc;
- data->arraysize = data->poly_order * 2;
+ else {
+ data->coefficients = MEM_callocN(sizeof(float) * arraysize_new, "FMod_Generator_Coefs");
+ }
+ data->arraysize = arraysize_new;
}
+ break;
}
- break;
}
}
@@ -501,6 +480,92 @@ static FModifierTypeInfo FMI_ENVELOPE = {
fcm_envelope_evaluate /* evaluate */
};
+/* exported function for finding points */
+
+/* Binary search algorithm for finding where to insert Envelope Data Point.
+ * Returns the index to insert at (data already at that index will be offset if replace is 0)
+ */
+#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001f
+
+int BKE_fcm_envelope_find_index(FCM_EnvelopeData array[], float frame, int arraylen, bool *r_exists)
+{
+ int start = 0, end = arraylen;
+ int loopbreaker = 0, maxloop = arraylen * 2;
+
+ /* initialize exists-flag first */
+ *r_exists = false;
+
+ /* sneaky optimizations (don't go through searching process if...):
+ * - keyframe to be added is to be added out of current bounds
+ * - keyframe to be added would replace one of the existing ones on bounds
+ */
+ if ((arraylen <= 0) || (array == NULL)) {
+ printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array\n");
+ return 0;
+ }
+ else {
+ /* check whether to add before/after/on */
+ float framenum;
+
+ /* 'First' Point (when only one point, this case is used) */
+ framenum = array[0].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *r_exists = true;
+ return 0;
+ }
+ else if (frame < framenum) {
+ return 0;
+ }
+
+ /* 'Last' Point */
+ framenum = array[(arraylen - 1)].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *r_exists = true;
+ return (arraylen - 1);
+ }
+ else if (frame > framenum) {
+ return arraylen;
+ }
+ }
+
+
+ /* most of the time, this loop is just to find where to put it
+ * - 'loopbreaker' is just here to prevent infinite loops
+ */
+ for (loopbreaker = 0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
+ /* compute and get midpoint */
+ int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
+ float midfra = array[mid].time;
+
+ /* check if exactly equal to midpoint */
+ if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *r_exists = true;
+ return mid;
+ }
+
+ /* repeat in upper/lower half */
+ if (frame > midfra) {
+ start = mid + 1;
+ }
+ else if (frame < midfra) {
+ end = mid - 1;
+ }
+ }
+
+ /* print error if loop-limit exceeded */
+ if (loopbreaker == (maxloop - 1)) {
+ printf("Error: binarysearch_fcm_envelopedata_index() was taking too long\n");
+
+ // include debug info
+ printf("\tround = %d: start = %d, end = %d, arraylen = %d\n", loopbreaker, start, end, arraylen);
+ }
+
+ /* not found, so return where to place it */
+ return start;
+}
+#undef BINARYSEARCH_FRAMEEQ_THRESH
+
+
/* Cycles F-Curve Modifier --------------------------- */
/* This modifier changes evaltime to something that exists within the curve's frame-range,