439
static void p_flush_uvs(PChart *chart)
433
static void p_flush_uvs(PHandle *handle, PChart *chart)
443
437
for (e=chart->edges; e; e=e->nextlink) {
444
438
if (e->orig_uv) {
445
e->orig_uv[0] = e->vert->uv[0];
446
e->orig_uv[1] = e->vert->uv[1];
439
e->orig_uv[0] = e->vert->uv[0]/handle->aspx;
440
e->orig_uv[1] = e->vert->uv[1]/handle->aspy;
451
static void p_flush_uvs_blend(PChart *chart, float blend)
445
static void p_flush_uvs_blend(PHandle *handle, PChart *chart, float blend)
454
448
float invblend = 1.0f - blend;
456
450
for (e=chart->edges; e; e=e->nextlink) {
457
451
if (e->orig_uv) {
458
e->orig_uv[0] = blend*e->old_uv[0] + invblend*e->vert->uv[0];
459
e->orig_uv[1] = blend*e->old_uv[1] + invblend*e->vert->uv[1];
452
e->orig_uv[0] = blend*e->old_uv[0] + invblend*e->vert->uv[0]/handle->aspx;
453
e->orig_uv[1] = blend*e->old_uv[1] + invblend*e->vert->uv[1]/handle->aspy;
2275
2269
sys->J2dt[e2->u.id][0] = j2[1][0] = p_abf_compute_sin_product(sys, v1, e2->u.id)*wi2;
2276
2270
sys->J2dt[e3->u.id][0] = j2[2][0] = p_abf_compute_sin_product(sys, v1, e3->u.id)*wi3;
2278
nlRightHandSideAdd(v1->u.id, j2[0][0]*beta[0]);
2279
nlRightHandSideAdd(ninterior + v1->u.id, j2[1][0]*beta[1] + j2[2][0]*beta[2]);
2272
nlRightHandSideAdd(0, v1->u.id, j2[0][0]*beta[0]);
2273
nlRightHandSideAdd(0, ninterior + v1->u.id, j2[1][0]*beta[1] + j2[2][0]*beta[2]);
2281
2275
row1[0] = j2[0][0]*W[0][0];
2282
2276
row2[0] = j2[0][0]*W[1][0];
2295
2289
sys->J2dt[e2->u.id][1] = j2[1][1] = 1.0*wi2;
2296
2290
sys->J2dt[e3->u.id][1] = j2[2][1] = p_abf_compute_sin_product(sys, v2, e3->u.id)*wi3;
2298
nlRightHandSideAdd(v2->u.id, j2[1][1]*beta[1]);
2299
nlRightHandSideAdd(ninterior + v2->u.id, j2[0][1]*beta[0] + j2[2][1]*beta[2]);
2292
nlRightHandSideAdd(0, v2->u.id, j2[1][1]*beta[1]);
2293
nlRightHandSideAdd(0, ninterior + v2->u.id, j2[0][1]*beta[0] + j2[2][1]*beta[2]);
2301
2295
row1[1] = j2[1][1]*W[0][1];
2302
2296
row2[1] = j2[1][1]*W[1][1];
2315
2309
sys->J2dt[e2->u.id][2] = j2[1][2] = p_abf_compute_sin_product(sys, v3, e2->u.id)*wi2;
2316
2310
sys->J2dt[e3->u.id][2] = j2[2][2] = 1.0*wi3;
2318
nlRightHandSideAdd(v3->u.id, j2[2][2]*beta[2]);
2319
nlRightHandSideAdd(ninterior + v3->u.id, j2[0][2]*beta[0] + j2[1][2]*beta[1]);
2312
nlRightHandSideAdd(0, v3->u.id, j2[2][2]*beta[2]);
2313
nlRightHandSideAdd(0, ninterior + v3->u.id, j2[0][2]*beta[0] + j2[1][2]*beta[1]);
2321
2315
row1[2] = j2[2][2]*W[0][2];
2322
2316
row2[2] = j2[2][2]*W[1][2];
2373
2367
pre[0] = pre[1] = pre[2] = 0.0;
2375
2369
if (v1->flag & PVERT_INTERIOR) {
2376
float x = nlGetVariable(v1->u.id);
2377
float x2 = nlGetVariable(ninterior + v1->u.id);
2370
float x = nlGetVariable(0, v1->u.id);
2371
float x2 = nlGetVariable(0, ninterior + v1->u.id);
2378
2372
pre[0] += sys->J2dt[e1->u.id][0]*x;
2379
2373
pre[1] += sys->J2dt[e2->u.id][0]*x2;
2380
2374
pre[2] += sys->J2dt[e3->u.id][0]*x2;
2383
2377
if (v2->flag & PVERT_INTERIOR) {
2384
float x = nlGetVariable(v2->u.id);
2385
float x2 = nlGetVariable(ninterior + v2->u.id);
2378
float x = nlGetVariable(0, v2->u.id);
2379
float x2 = nlGetVariable(0, ninterior + v2->u.id);
2386
2380
pre[0] += sys->J2dt[e1->u.id][1]*x2;
2387
2381
pre[1] += sys->J2dt[e2->u.id][1]*x;
2388
2382
pre[2] += sys->J2dt[e3->u.id][1]*x2;
2391
2385
if (v3->flag & PVERT_INTERIOR) {
2392
float x = nlGetVariable(v3->u.id);
2393
float x2 = nlGetVariable(ninterior + v3->u.id);
2386
float x = nlGetVariable(0, v3->u.id);
2387
float x2 = nlGetVariable(0, ninterior + v3->u.id);
2394
2388
pre[0] += sys->J2dt[e1->u.id][2]*x2;
2395
2389
pre[1] += sys->J2dt[e2->u.id][2]*x2;
2396
2390
pre[2] += sys->J2dt[e3->u.id][2]*x;
2809
2807
nlNewContext();
2810
2808
nlSolverParameteri(NL_NB_VARIABLES, 2*chart->nverts);
2809
nlSolverParameteri(NL_NB_ROWS, 2*chart->nfaces);
2811
2810
nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE);
2813
2812
chart->u.lscm.context = nlGetCurrent();
2817
static PBool p_chart_lscm_solve(PChart *chart)
2816
static PBool p_chart_lscm_solve(PHandle *handle, PChart *chart)
2819
2818
PVert *v, *pin1 = chart->u.lscm.pin1, *pin2 = chart->u.lscm.pin2;
2821
2820
float *alpha = chart->u.lscm.abf_alpha;
2823
2823
nlMakeCurrent(chart->u.lscm.context);
2838
2838
nlLockVariable(2*pin2->u.id);
2839
2839
nlLockVariable(2*pin2->u.id + 1);
2841
nlSetVariable(2*pin1->u.id, pin1->uv[0]);
2842
nlSetVariable(2*pin1->u.id + 1, pin1->uv[1]);
2843
nlSetVariable(2*pin2->u.id, pin2->uv[0]);
2844
nlSetVariable(2*pin2->u.id + 1, pin2->uv[1]);
2841
nlSetVariable(0, 2*pin1->u.id, pin1->uv[0]);
2842
nlSetVariable(0, 2*pin1->u.id + 1, pin1->uv[1]);
2843
nlSetVariable(0, 2*pin2->u.id, pin2->uv[0]);
2844
nlSetVariable(0, 2*pin2->u.id + 1, pin2->uv[1]);
2847
2847
/* set and lock the pins */
2917
2916
nlCoefficient(2*v2->u.id+1, -cosine);
2918
2917
nlCoefficient(2*v3->u.id+1, 1.0);
2920
nlMatrixAdd(row, 2*v1->u.id, cosine - 1.0);
2921
nlMatrixAdd(row, 2*v1->u.id+1, -sine);
2922
nlMatrixAdd(row, 2*v2->u.id, -cosine);
2923
nlMatrixAdd(row, 2*v2->u.id+1, sine);
2924
nlMatrixAdd(row, 2*v3->u.id, 1.0);
2927
nlMatrixAdd(row, 2*v1->u.id, sine);
2928
nlMatrixAdd(row, 2*v1->u.id+1, cosine - 1.0);
2929
nlMatrixAdd(row, 2*v2->u.id, -sine);
2930
nlMatrixAdd(row, 2*v2->u.id+1, -cosine);
2931
nlMatrixAdd(row, 2*v3->u.id+1, 1.0);
2922
2936
nlEnd(NL_MATRIX);
3103
static int p_compare_chart_area(const void *a, const void *b)
3105
PChart *ca = *((PChart**)a);
3106
PChart *cb = *((PChart**)b);
3108
if (ca->u.pack.area > cb->u.pack.area)
3110
else if (ca->u.pack.area == cb->u.pack.area)
3116
static PBool p_pack_try(PHandle *handle, float side)
3119
float packx, packy, rowh, groupw, w, h;
3124
groupw= 1.0/sqrt(handle->ncharts);
3126
for (i = 0; i < handle->ncharts; i++) {
3127
chart = handle->charts[i];
3129
if (chart->flag & PCHART_NOPACK)
3132
w = chart->u.pack.size[0];
3133
h = chart->u.pack.size[1];
3135
if(w <= (side-packx)) {
3136
chart->u.pack.trans[0] = packx;
3137
chart->u.pack.trans[1] = packy;
3140
rowh= MAX2(rowh, h);
3147
chart->u.pack.trans[0] = 0.0;
3148
chart->u.pack.trans[1] = packy;
3151
if (packy+rowh > side)
3158
#define PACK_SEARCH_DEPTH 15
3160
void p_charts_pack(PHandle *handle)
3163
float uv_area, area, trans[2], minside, maxside, totarea, side;
3166
/* very simple rectangle packing */
3168
if (handle->ncharts == 0)
3174
for (i = 0; i < handle->ncharts; i++) {
3175
chart = handle->charts[i];
3177
if (chart->flag & PCHART_NOPACK) {
3178
chart->u.pack.area = 0.0f;
3182
p_chart_area(chart, &uv_area, &area);
3183
p_chart_uv_bbox(chart, trans, chart->u.pack.size);
3185
/* translate to origin and make area equal to 3d area */
3186
chart->u.pack.rescale = (uv_area > 0.0f)? sqrt(area)/sqrt(uv_area): 0.0f;
3187
chart->u.pack.area = area;
3190
trans[0] = -trans[0];
3191
trans[1] = -trans[1];
3192
p_chart_uv_translate(chart, trans);
3193
p_chart_uv_scale(chart, chart->u.pack.rescale);
3195
/* compute new dimensions for packing */
3196
chart->u.pack.size[0] += trans[0];
3197
chart->u.pack.size[1] += trans[1];
3198
chart->u.pack.size[0] *= chart->u.pack.rescale;
3199
chart->u.pack.size[1] *= chart->u.pack.rescale;
3201
maxside = MAX3(maxside, chart->u.pack.size[0], chart->u.pack.size[1]);
3204
/* sort by chart area, largest first */
3205
qsort(handle->charts, handle->ncharts, sizeof(PChart*), p_compare_chart_area);
3207
/* binary search over pack region size */
3208
minside = MAX2(sqrt(totarea), maxside);
3209
maxside = (((int)sqrt(handle->ncharts-1))+1)*maxside;
3211
if (minside < maxside) { /* should always be true */
3213
for (i = 0; i < PACK_SEARCH_DEPTH; i++) {
3214
if (p_pack_try(handle, (minside+maxside)*0.5f + 1e-5))
3215
maxside = (minside+maxside)*0.5f;
3217
minside = (minside+maxside)*0.5f;
3221
/* do the actual packing */
3222
side = maxside + 1e-5;
3223
if (!p_pack_try(handle, side))
3224
param_warning("packing failed.\n");
3226
for (i = 0; i < handle->ncharts; i++) {
3227
chart = handle->charts[i];
3229
if (chart->flag & PCHART_NOPACK)
3232
p_chart_uv_scale(chart, 1.0f/side);
3233
trans[0] = chart->u.pack.trans[0]/side;
3234
trans[1] = chart->u.pack.trans[1]/side;
3235
p_chart_uv_translate(chart, trans);
3239
3115
/* Minimum area enclosing rectangle for packing */
3241
3117
static int p_compare_geometric_uv(const void *a, const void *b)
4236
4122
p_smooth(chart);
4240
4126
void param_pack(ParamHandle *handle)
4242
p_charts_pack((PHandle*)handle);
4128
/* box packing variables */
4129
boxPack *boxarray, *box;
4130
float tot_width, tot_height, scale;
4136
PHandle *phandle = (PHandle*)handle;
4138
if (phandle->ncharts == 0)
4141
if(phandle->aspx != phandle->aspy)
4142
param_scale(handle, 1.0f/phandle->aspx, 1.0f/phandle->aspy);
4144
/* we may not use all these boxes */
4145
boxarray = MEM_mallocN( phandle->ncharts*sizeof(boxPack), "boxPack box");
4147
for (i = 0; i < phandle->ncharts; i++) {
4148
chart = phandle->charts[i];
4150
if (chart->flag & PCHART_NOPACK) {
4155
box = boxarray+(i-unpacked);
4157
p_chart_uv_bbox(chart, trans, chart->u.pack.size);
4159
trans[0] = -trans[0];
4160
trans[1] = -trans[1];
4162
p_chart_uv_translate(chart, trans);
4164
box->w = chart->u.pack.size[0] + trans[0];
4165
box->h = chart->u.pack.size[1] + trans[1];
4166
box->index = i; /* warning this index skips PCHART_NOPACK boxes */
4169
boxPack2D(boxarray, phandle->ncharts-unpacked, &tot_width, &tot_height);
4171
if (tot_height>tot_width)
4172
scale = 1.0/tot_height;
4174
scale = 1.0/tot_width;
4176
for (i = 0; i < phandle->ncharts-unpacked; i++) {
4181
chart = phandle->charts[box->index];
4182
p_chart_uv_translate(chart, trans);
4183
p_chart_uv_scale(chart, scale);
4185
MEM_freeN(boxarray);
4187
if(phandle->aspx != phandle->aspy)
4188
param_scale(handle, phandle->aspx, phandle->aspy);
4191
void param_average(ParamHandle *handle)
4195
float tot_uvarea = 0.0f, tot_facearea = 0.0f;
4197
float minv[2], maxv[2], trans[2];
4198
PHandle *phandle = (PHandle*)handle;
4200
if (phandle->ncharts == 0)
4203
for (i = 0; i < phandle->ncharts; i++) {
4205
chart = phandle->charts[i];
4207
chart->u.pack.area = 0.0f; /* 3d area */
4208
chart->u.pack.rescale = 0.0f; /* UV area, abusing rescale for tmp storage, oh well :/ */
4210
for (f=chart->faces; f; f=f->nextlink) {
4211
chart->u.pack.area += p_face_area(f);
4212
chart->u.pack.rescale += fabs(p_face_uv_area_signed(f));
4215
tot_facearea += chart->u.pack.area;
4216
tot_uvarea += chart->u.pack.rescale;
4219
if (tot_facearea == tot_uvarea || tot_facearea==0.0f || tot_uvarea==0.0f) {
4224
tot_fac = tot_facearea/tot_uvarea;
4226
for (i = 0; i < phandle->ncharts; i++) {
4227
chart = phandle->charts[i];
4228
if (chart->u.pack.area != 0.0f && chart->u.pack.rescale != 0.0f) {
4229
fac = chart->u.pack.area / chart->u.pack.rescale;
4231
/* Get the island center */
4232
p_chart_uv_bbox(chart, minv, maxv);
4233
trans[0] = (minv[0] + maxv[0]) /-2.0f;
4234
trans[1] = (minv[1] + maxv[1]) /-2.0f;
4236
/* Move center to 0,0 */
4237
p_chart_uv_translate(chart, trans);
4238
p_chart_uv_scale(chart, sqrt(fac / tot_fac));
4240
/* Move to original center */
4241
trans[0] = -trans[0];
4242
trans[1] = -trans[1];
4243
p_chart_uv_translate(chart, trans);
4248
void param_scale(ParamHandle *handle, float x, float y)
4250
PHandle *phandle = (PHandle*)handle;
4254
for (i = 0; i < phandle->ncharts; i++) {
4255
chart = phandle->charts[i];
4256
p_chart_uv_scale_xy(chart, x, y);
4245
4260
void param_flush(ParamHandle *handle)