GP: Fix precision issue with Circle and Arc tools
Differential Revision: https://developer.blender.org/D4030
This commit is contained in:
parent
cdf626615d
commit
94503efb12
|
@ -228,6 +228,13 @@ void gp_stroke_convertcoords_tpoint(
|
|||
bGPDlayer *gpl, const struct tGPspoint *point2D,
|
||||
float *depth, float out[3]);
|
||||
|
||||
/* helper to convert 2d to 3d for primitive. See: D4030 */
|
||||
void gp_stroke_convertcoords_tpoint_primitive(
|
||||
struct Scene *scene, struct ARegion *ar,
|
||||
struct Object *ob,
|
||||
bGPDlayer *gpl, const struct tPGPspoint *point2D,
|
||||
float out[3]);
|
||||
|
||||
/* Poll Callbacks ------------------------------------ */
|
||||
/* gpencil_utils.c */
|
||||
|
||||
|
|
|
@ -260,37 +260,37 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi
|
|||
/* ----------------------- */
|
||||
|
||||
/* create a rectangle */
|
||||
static void gp_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D)
|
||||
static void gp_primitive_rectangle(tGPDprimitive *tgpi, tPGPspoint *points2D)
|
||||
{
|
||||
BLI_assert(tgpi->tot_edges == 4);
|
||||
|
||||
points2D[0].x = tgpi->top[0];
|
||||
points2D[0].y = tgpi->top[1];
|
||||
points2D[0].x = (float)tgpi->top[0];
|
||||
points2D[0].y = (float)tgpi->top[1];
|
||||
|
||||
points2D[1].x = tgpi->bottom[0];
|
||||
points2D[1].y = tgpi->top[1];
|
||||
points2D[1].x = (float)tgpi->bottom[0];
|
||||
points2D[1].y = (float)tgpi->top[1];
|
||||
|
||||
points2D[2].x = tgpi->bottom[0];
|
||||
points2D[2].y = tgpi->bottom[1];
|
||||
points2D[2].x = (float)tgpi->bottom[0];
|
||||
points2D[2].y = (float)tgpi->bottom[1];
|
||||
|
||||
points2D[3].x = tgpi->top[0];
|
||||
points2D[3].y = tgpi->bottom[1];
|
||||
points2D[3].x = (float)tgpi->top[0];
|
||||
points2D[3].y = (float)tgpi->bottom[1];
|
||||
}
|
||||
|
||||
/* create a line */
|
||||
static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D)
|
||||
static void gp_primitive_line(tGPDprimitive *tgpi, tPGPspoint *points2D)
|
||||
{
|
||||
BLI_assert(tgpi->tot_edges == 2);
|
||||
|
||||
points2D[0].x = tgpi->top[0];
|
||||
points2D[0].y = tgpi->top[1];
|
||||
points2D[0].x = (float)tgpi->top[0];
|
||||
points2D[0].y = (float)tgpi->top[1];
|
||||
|
||||
points2D[1].x = tgpi->bottom[0];
|
||||
points2D[1].y = tgpi->bottom[1];
|
||||
points2D[1].x = (float)tgpi->bottom[0];
|
||||
points2D[1].y = (float)tgpi->bottom[1];
|
||||
}
|
||||
|
||||
/* create an arc */
|
||||
static void gp_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D)
|
||||
static void gp_primitive_arc(tGPDprimitive *tgpi, tPGPspoint *points2D)
|
||||
{
|
||||
const int totpoints = tgpi->tot_edges;
|
||||
const float step = M_PI_2 / (float)(totpoints - 1);
|
||||
|
@ -313,15 +313,15 @@ static void gp_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D)
|
|||
length[1] = end[1] - start[1];
|
||||
|
||||
for (int i = 0; i < totpoints; i++) {
|
||||
tGPspoint *p2d = &points2D[i];
|
||||
p2d->x = (int)(start[0] + sinf(a) * length[0]);
|
||||
p2d->y = (int)(end[1] - cosf(a) * length[1]);
|
||||
tPGPspoint *p2d = &points2D[i];
|
||||
p2d->x = (start[0] + sinf(a) * length[0]);
|
||||
p2d->y = (end[1] - cosf(a) * length[1]);
|
||||
a += step;
|
||||
}
|
||||
}
|
||||
|
||||
/* create a circle */
|
||||
static void gp_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D)
|
||||
static void gp_primitive_circle(tGPDprimitive *tgpi, tPGPspoint *points2D)
|
||||
{
|
||||
const int totpoints = tgpi->tot_edges;
|
||||
const float step = (2.0f * M_PI) / (float)(totpoints);
|
||||
|
@ -336,10 +336,9 @@ static void gp_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D)
|
|||
radius[1] = fabsf(((tgpi->bottom[1] - tgpi->top[1]) / 2.0f));
|
||||
|
||||
for (int i = 0; i < totpoints; i++) {
|
||||
tGPspoint *p2d = &points2D[i];
|
||||
|
||||
p2d->x = (int)(center[0] + cosf(a) * radius[0]);
|
||||
p2d->y = (int)(center[1] + sinf(a) * radius[1]);
|
||||
tPGPspoint *p2d = &points2D[i];
|
||||
p2d->x = (center[0] + cosf(a) * radius[0]);
|
||||
p2d->y = (center[1] + sinf(a) * radius[1]);
|
||||
a += step;
|
||||
}
|
||||
}
|
||||
|
@ -360,7 +359,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
|
|||
gps->totpoints = tgpi->tot_edges;
|
||||
|
||||
/* compute screen-space coordinates for points */
|
||||
tGPspoint *points2D = MEM_callocN(sizeof(tGPspoint) * tgpi->tot_edges, "gp primitive points2D");
|
||||
tPGPspoint *points2D = MEM_callocN(sizeof(tPGPspoint) * tgpi->tot_edges, "gp primitive points2D");
|
||||
switch (tgpi->type) {
|
||||
case GP_STROKE_BOX:
|
||||
gp_primitive_rectangle(tgpi, points2D);
|
||||
|
@ -385,10 +384,10 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
|
|||
/* convert screen-coordinates to 3D coordinates */
|
||||
for (int i = 0; i < gps->totpoints; i++) {
|
||||
bGPDspoint *pt = &gps->points[i];
|
||||
tGPspoint *p2d = &points2D[i];
|
||||
tPGPspoint *p2d = &points2D[i];
|
||||
|
||||
/* convert screen-coordinates to 3D coordinates */
|
||||
gp_stroke_convertcoords_tpoint(tgpi->scene, tgpi->ar, tgpi->ob, tgpi->gpl, p2d, NULL, &pt->x);
|
||||
gp_stroke_convertcoords_tpoint_primitive(tgpi->scene, tgpi->ar, tgpi->ob, tgpi->gpl, p2d, &pt->x);
|
||||
|
||||
pt->pressure = 1.0f;
|
||||
pt->strength = tgpi->brush->gpencil_settings->draw_strength;
|
||||
|
|
|
@ -806,6 +806,41 @@ void gp_stroke_convertcoords_tpoint(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert primitive tPGPspoint (temporary 2D/screenspace point data used by GP primitive operators)
|
||||
* to 3D coordinates.
|
||||
*
|
||||
* See: D4030
|
||||
*/
|
||||
void gp_stroke_convertcoords_tpoint_primitive(
|
||||
Scene *scene, ARegion *ar,
|
||||
Object *ob, bGPDlayer *gpl,
|
||||
const tPGPspoint *point2D,
|
||||
float r_out[3])
|
||||
{
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
|
||||
float mval_f[2] = { point2D->x, point2D->y };
|
||||
float mval_prj[2];
|
||||
float rvec[3], dvec[3];
|
||||
float zfac;
|
||||
|
||||
/* Current method just converts each point in screen-coordinates to
|
||||
* 3D-coordinates using the 3D-cursor as reference.
|
||||
*/
|
||||
ED_gp_get_drawing_reference(scene, ob, gpl, ts->gpencil_v3d_align, rvec);
|
||||
zfac = ED_view3d_calc_zfac(ar->regiondata, rvec, NULL);
|
||||
|
||||
if (ED_view3d_project_float_global(ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
|
||||
sub_v2_v2v2(mval_f, mval_prj, mval_f);
|
||||
ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
|
||||
sub_v3_v3v3(r_out, rvec, dvec);
|
||||
}
|
||||
else {
|
||||
zero_v3(r_out);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get drawing reference point for conversion or projection of the stroke
|
||||
* \param[out] r_vec : Reference point found
|
||||
|
|
|
@ -81,6 +81,19 @@ typedef struct tGPspoint {
|
|||
float uv_rot; /* uv rotation for dor mode */
|
||||
} tGPspoint;
|
||||
|
||||
/* Temporary 'Stroke Point' data (2D / screen-space)
|
||||
*
|
||||
* Used for primitives. See: D4030
|
||||
*/
|
||||
typedef struct tPGPspoint {
|
||||
float x, y; /* x and y coordinates of cursor (in relative to area) */
|
||||
float pressure; /* pressure of tablet at this point */
|
||||
float strength; /* pressure of tablet at this point for alpha factor */
|
||||
float time; /* Time relative to stroke start (used when converting to path) */
|
||||
float uv_fac; /* factor of uv along the stroke */
|
||||
float uv_rot; /* uv rotation for dor mode */
|
||||
} tPGPspoint;
|
||||
|
||||
/* used to sort by zdepth gpencil objects in viewport */
|
||||
/* TODO: this could be a system parameter in userprefs screen */
|
||||
#define GP_CACHE_BLOCK_SIZE 16
|
||||
|
|
Loading…
Reference in New Issue