Esempio n. 1
0
static bool kdtree2d_isect_tri(
        struct KDTree2D *tree,
        const unsigned int ind[3])
{
	const float *vs[3];
	unsigned int i;
	struct KDRange2D bounds[2] = {
	    {FLT_MAX, -FLT_MAX},
	    {FLT_MAX, -FLT_MAX},
	};
	float tri_center[2] = {0.0f, 0.0f};

	for (i = 0; i < 3; i++) {
		vs[i] = tree->coords[ind[i]];

		add_v2_v2(tri_center, vs[i]);

		CLAMP_MAX(bounds[0].min, vs[i][0]);
		CLAMP_MIN(bounds[0].max, vs[i][0]);
		CLAMP_MAX(bounds[1].min, vs[i][1]);
		CLAMP_MIN(bounds[1].max, vs[i][1]);
	}

	mul_v2_fl(tri_center, 1.0f / 3.0f);

	return kdtree2d_isect_tri_recursive(tree, ind, vs, tri_center, bounds, &tree->nodes[tree->root]);
}
Esempio n. 2
0
/**
* Apply smooth for thickness to stroke point (use pressure)
* \param gps: Stroke to smooth
* \param i: Point index
* \param inf: Amount of smoothing to apply
*/
bool gp_smooth_stroke_thickness(bGPDstroke *gps, int i, float inf)
{
	bGPDspoint *ptb = &gps->points[i];

	/* Do nothing if not enough points */
	if (gps->totpoints <= 2) {
		return false;
	}

	/* Compute theoretical optimal value using distances */
	bGPDspoint *pta, *ptc;
	int before = i - 1;
	int after = i + 1;

	CLAMP_MIN(before, 0);
	CLAMP_MAX(after, gps->totpoints - 1);

	pta = &gps->points[before];
	ptc = &gps->points[after];

	/* the optimal value is the corresponding to the interpolation of the pressure
	 * at the distance of point b
	 */
	float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
	float optimal = (1.0f - fac) * pta->pressure + fac * ptc->pressure;

	/* Based on influence factor, blend between original and optimal */
	ptb->pressure = (1.0f - inf) * ptb->pressure + inf * optimal;

	return true;
}
Esempio n. 3
0
static void camera_to_frame_view_cb(const float co[3], void *user_data)
{
	CameraViewFrameData *data = (CameraViewFrameData *)user_data;
	unsigned int i;

	for (i = 0; i < CAMERA_VIEWFRAME_NUM_PLANES; i++) {
		const float nd = dist_signed_squared_to_plane_v3(co, data->plane_tx[i]);
		CLAMP_MAX(data->dist_vals_sq[i], nd);
	}

	if (data->is_ortho) {
		const float d = dot_v3v3(data->camera_no, co);
		CLAMP_MAX(data->dist_to_cam, d);
	}

	data->tot++;
}
Esempio n. 4
0
/* helper function returns length of the 'value', -1 on error */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{
	const int flag = array_max;
	int size;

	array_max &= ~MU_ARRAY_FLAGS;

#if 1 /* approx 6x speedup for mathutils types */

	if ((size = VectorObject_Check(value)     ? ((VectorObject *)value)->size : 0) ||
	    (size = EulerObject_Check(value)      ? 3 : 0) ||
	    (size = QuaternionObject_Check(value) ? 4 : 0) ||
	    (size = ColorObject_Check(value)      ? 3 : 0))
	{
		if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
			return -1;
		}

		if (flag & MU_ARRAY_SPILL) {
			CLAMP_MAX(size, array_max);
		}

		if (size > array_max || size < array_min) {
			if (array_max == array_min) {
				PyErr_Format(PyExc_ValueError,
				             "%.200s: sequence size is %d, expected %d",
				             error_prefix, size, array_max);
			}
			else {
				PyErr_Format(PyExc_ValueError,
				             "%.200s: sequence size is %d, expected [%d - %d]",
				             error_prefix, size, array_min, array_max);
			}
			return -1;
		}

		memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
	}
	else
#endif
	{
		PyObject *value_fast = NULL;

		/* non list/tuple cases */
		if (!(value_fast = PySequence_Fast(value, error_prefix))) {
			/* PySequence_Fast sets the error */
			return -1;
		}

		size = PySequence_Fast_GET_SIZE(value_fast);

		if (flag & MU_ARRAY_SPILL) {
			CLAMP_MAX(size, array_max);
		}

		if (size > array_max || size < array_min) {
			if (array_max == array_min) {
				PyErr_Format(PyExc_ValueError,
				             "%.200s: sequence size is %d, expected %d",
				             error_prefix, size, array_max);
			}
			else {
				PyErr_Format(PyExc_ValueError,
				             "%.200s: sequence size is %d, expected [%d - %d]",
				             error_prefix, size, array_min, array_max);
			}
			Py_DECREF(value_fast);
			return -1;
		}

		size = mathutils_array_parse_fast(array, size, value_fast, error_prefix);
	}

	if (size != -1) {
		if (flag & MU_ARRAY_ZERO) {
			int size_left = array_max - size;
			if (size_left) {
				memset(&array[size], 0, sizeof(float) * size_left);
			}
		}
	}

	return size;
}
Esempio n. 5
0
/**
 * Apply smooth to stroke point
 * \param gps: Stroke to smooth
 * \param i: Point index
 * \param inf: Amount of smoothing to apply
 * \param affect_pressure: Apply smoothing to pressure values too?
 */
bool gp_smooth_stroke(bGPDstroke *gps, int i, float inf, bool affect_pressure)
{
	bGPDspoint *pt = &gps->points[i];
	float pressure = 0.0f;
	float sco[3] = {0.0f};

	/* Do nothing if not enough points to smooth out */
	if (gps->totpoints <= 2) {
		return false;
	}

	/* Only affect endpoints by a fraction of the normal strength,
	 * to prevent the stroke from shrinking too much
	 */
	if ((i == 0) || (i == gps->totpoints - 1)) {
		inf *= 0.1f;
	}

	/* Compute smoothed coordinate by taking the ones nearby */
	/* XXX: This is potentially slow, and suffers from accumulation error as earlier points are handled before later ones */
	{
		// XXX: this is hardcoded to look at 2 points on either side of the current one (i.e. 5 items total)
		const int   steps = 2;
		const float average_fac = 1.0f / (float)(steps * 2 + 1);
		int step;

		/* add the point itself */
		madd_v3_v3fl(sco, &pt->x, average_fac);

		if (affect_pressure) {
			pressure += pt->pressure * average_fac;
		}

		/* n-steps before/after current point */
		// XXX: review how the endpoints are treated by this algorithm
		// XXX: falloff measures should also introduce some weighting variations, so that further-out points get less weight
		for (step = 1; step <= steps; step++) {
			bGPDspoint *pt1, *pt2;
			int before = i - step;
			int after = i + step;

			CLAMP_MIN(before, 0);
			CLAMP_MAX(after, gps->totpoints - 1);

			pt1 = &gps->points[before];
			pt2 = &gps->points[after];

			/* add both these points to the average-sum (s += p[i]/n) */
			madd_v3_v3fl(sco, &pt1->x, average_fac);
			madd_v3_v3fl(sco, &pt2->x, average_fac);

#if 0
			/* XXX: Disabled because get weird result */
			/* do pressure too? */
			if (affect_pressure) {
				pressure += pt1->pressure * average_fac;
				pressure += pt2->pressure * average_fac;
			}
#endif
		}
	}

	/* Based on influence factor, blend between original and optimal smoothed coordinate */
	interp_v3_v3v3(&pt->x, &pt->x, sco, inf);

#if 0
	/* XXX: Disabled because get weird result */
	if (affect_pressure) {
		pt->pressure = pressure;
	}
#endif

	return true;
}
Esempio n. 6
0
/**
 * Evaluate the expression with the given parameters.
 * The order and number of parameters must match the names given to parse.
 */
eExprPyLike_EvalStatus BLI_expr_pylike_eval(ExprPyLike_Parsed *expr,
                                            const double *param_values,
                                            int param_values_len,
                                            double *r_result)
{
  *r_result = 0.0;

  if (!BLI_expr_pylike_is_valid(expr)) {
    return EXPR_PYLIKE_INVALID;
  }

#define FAIL_IF(condition) \
  if (condition) { \
    return EXPR_PYLIKE_FATAL_ERROR; \
  } \
  ((void)0)

  /* Check the stack requirement is at least remotely sane and allocate on the actual stack. */
  FAIL_IF(expr->max_stack <= 0 || expr->max_stack > 1000);

  double *stack = BLI_array_alloca(stack, expr->max_stack);

  /* Evaluate expression. */
  ExprOp *ops = expr->ops;
  int sp = 0, pc;

  feclearexcept(FE_ALL_EXCEPT);

  for (pc = 0; pc >= 0 && pc < expr->ops_count; pc++) {
    switch (ops[pc].opcode) {
      /* Arithmetic */
      case OPCODE_CONST:
        FAIL_IF(sp >= expr->max_stack);
        stack[sp++] = ops[pc].arg.dval;
        break;
      case OPCODE_PARAMETER:
        FAIL_IF(sp >= expr->max_stack || ops[pc].arg.ival >= param_values_len);
        stack[sp++] = param_values[ops[pc].arg.ival];
        break;
      case OPCODE_FUNC1:
        FAIL_IF(sp < 1);
        stack[sp - 1] = ops[pc].arg.func1(stack[sp - 1]);
        break;
      case OPCODE_FUNC2:
        FAIL_IF(sp < 2);
        stack[sp - 2] = ops[pc].arg.func2(stack[sp - 2], stack[sp - 1]);
        sp--;
        break;
      case OPCODE_MIN:
        FAIL_IF(sp < ops[pc].arg.ival);
        for (int j = 1; j < ops[pc].arg.ival; j++, sp--) {
          CLAMP_MAX(stack[sp - 2], stack[sp - 1]);
        }
        break;
      case OPCODE_MAX:
        FAIL_IF(sp < ops[pc].arg.ival);
        for (int j = 1; j < ops[pc].arg.ival; j++, sp--) {
          CLAMP_MIN(stack[sp - 2], stack[sp - 1]);
        }
        break;

      /* Jumps */
      case OPCODE_JMP:
        pc += ops[pc].jmp_offset;
        break;
      case OPCODE_JMP_ELSE:
        FAIL_IF(sp < 1);
        if (!stack[--sp]) {
          pc += ops[pc].jmp_offset;
        }
        break;
      case OPCODE_JMP_OR:
      case OPCODE_JMP_AND:
        FAIL_IF(sp < 1);
        if (!stack[sp - 1] == !(ops[pc].opcode == OPCODE_JMP_OR)) {
          pc += ops[pc].jmp_offset;
        }
        else {
          sp--;
        }
        break;

      /* For chaining comparisons, i.e. "a < b < c" as "a < b and b < c" */
      case OPCODE_CMP_CHAIN:
        FAIL_IF(sp < 2);
        /* If comparison fails, return 0 and jump to end. */
        if (!ops[pc].arg.func2(stack[sp - 2], stack[sp - 1])) {
          stack[sp - 2] = 0.0;
          pc += ops[pc].jmp_offset;
        }
        /* Otherwise keep b on the stack and proceed. */
        else {
          stack[sp - 2] = stack[sp - 1];
        }
        sp--;
        break;

      default:
        return EXPR_PYLIKE_FATAL_ERROR;
    }
  }

  FAIL_IF(sp != 1 || pc != expr->ops_count);

#undef FAIL_IF

  *r_result = stack[0];

  /* Detect floating point evaluation errors. */
  int flags = fetestexcept(FE_DIVBYZERO | FE_INVALID);
  if (flags) {
    return (flags & FE_INVALID) ? EXPR_PYLIKE_MATH_ERROR : EXPR_PYLIKE_DIV_BY_ZERO;
  }

  return EXPR_PYLIKE_SUCCESS;
}
Esempio n. 7
0
static GPUTexture *GPU_texture_create_nD(
        int w, int h, int n, const float *fpixels, int depth,
        GPUHDRType hdr_type, int components, int samples,
        char err_out[256])
{
	GLenum type, format, internalformat;
	void *pixels = NULL;

	if (samples) {
		CLAMP_MAX(samples, GPU_max_color_texture_samples());
	}

	GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
	tex->w = w;
	tex->h = h;
	tex->number = -1;
	tex->refcount = 1;
	tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
	tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
	tex->depth = depth;
	tex->fb_attachment = -1;

	glGenTextures(1, &tex->bindcode);

	if (!tex->bindcode) {
		if (err_out) {
			BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d",
				(int)glGetError());
		}
		else {
			fprintf(stderr, "GPUTexture: texture create failed: %d\n",
				(int)glGetError());
		}
		GPU_texture_free(tex);
		return NULL;
	}

	if (!GPU_full_non_power_of_two_support()) {
		tex->w = power_of_2_max_i(tex->w);
		tex->h = power_of_2_max_i(tex->h);
	}

	tex->number = 0;
	glBindTexture(tex->target, tex->bindcode);

	if (depth) {
		type = GL_UNSIGNED_BYTE;
		format = GL_DEPTH_COMPONENT;
		internalformat = GL_DEPTH_COMPONENT;
	}
	else {
		type = GL_FLOAT;

		if (components == 4) {
			format = GL_RGBA;
			switch (hdr_type) {
				case GPU_HDR_NONE:
					internalformat = GL_RGBA8;
					break;
				/* the following formats rely on ARB_texture_float or OpenGL 3.0 */
				case GPU_HDR_HALF_FLOAT:
					internalformat = GL_RGBA16F_ARB;
					break;
				case GPU_HDR_FULL_FLOAT:
					internalformat = GL_RGBA32F_ARB;
					break;
				default:
					break;
			}
		}
		else if (components == 2) {
			/* these formats rely on ARB_texture_rg or OpenGL 3.0 */
			format = GL_RG;
			switch (hdr_type) {
				case GPU_HDR_NONE:
					internalformat = GL_RG8;
					break;
				case GPU_HDR_HALF_FLOAT:
					internalformat = GL_RG16F;
					break;
				case GPU_HDR_FULL_FLOAT:
					internalformat = GL_RG32F;
					break;
				default:
					break;
			}
		}

		if (fpixels && hdr_type == GPU_HDR_NONE) {
			type = GL_UNSIGNED_BYTE;
			pixels = GPU_texture_convert_pixels(w * h, fpixels);
		}
	}

	if (tex->target == GL_TEXTURE_1D) {
		glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);

		if (fpixels) {
			glTexSubImage1D(tex->target, 0, 0, w, format, type,
				pixels ? pixels : fpixels);

			if (tex->w > w) {
				GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
			}
		}
	}
	else {
		if (samples) {
			glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
		}
		else {
			glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
			             format, type, NULL);
		}

		if (fpixels) {
			glTexSubImage2D(tex->target, 0, 0, 0, w, h,
				format, type, pixels ? pixels : fpixels);

			if (tex->w > w)
				GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h);
			if (tex->h > h)
				GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h);
		}
	}

	if (pixels)
		MEM_freeN(pixels);

	if (depth) {
		glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
		glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
		glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
	}
	else {
		glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	}

	if (tex->target_base != GL_TEXTURE_1D) {
		glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}
	else
		glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

	return tex;
}