| 18 |  |  | 
| 19 |  | SM *smMesh = NULL; | 
| 20 |  | double smDist_sum=0; | 
| 21 | + | #define S_INC 1000 | 
| 22 |  | int smNew_tri_cnt=0; | 
| 23 | < | double smMinSampDiff = 4.25e-4; /* min edge length in radians */ | 
| 23 | > | int smNew_tri_size=0; | 
| 24 |  |  | 
| 25 | + | #define SM_MIN_SAMP_DIFF 1e-4/* min edge length in radians */ | 
| 26 | + |  | 
| 27 |  | /* Each edge extends .5536 radians - 31.72 degrees */ | 
| 28 |  | static FVECT icosa_verts[162] = | 
| 29 |  | {{-0.018096,0.495400,0.868477},{0.018614,-0.554780,0.831789}, | 
| 448 |  |  | 
| 449 |  | total_points = n + SM_EXTRA_POINTS; | 
| 450 |  |  | 
| 451 | < | max_tris = total_points*4; | 
| 451 | > | max_tris = total_points*2; | 
| 452 |  | /* Now allocate space for mesh vertices and triangles */ | 
| 453 |  | max_tris = smAlloc_mesh(smMesh, total_points, max_tris); | 
| 454 |  |  | 
| 571 |  | /* If the set size is below expansion threshold,or at maximum | 
| 572 |  | number of quadtree levels : just add */ | 
| 573 |  | optr = qtqueryset(qt); | 
| 574 | < | if(QT_SET_CNT(optr) < QT_SET_THRESHOLD || (n >= QT_MAX_LEVELS)) | 
| 574 | > | if(QT_SET_CNT(optr) < QT_SET_THRESHOLD || (n > (QT_MAX_LEVELS-2))) | 
| 575 |  | return(qtadduelem(qt,t_id)); | 
| 576 |  | /* otherwise: expand node- and insert tri, and reinsert existing tris | 
| 577 |  | in set to children of new node | 
| 700 |  | SM_NTH_VERT(sm,v2_id) = t_id; | 
| 701 |  |  | 
| 702 |  | if(SM_BASE_ID(sm,v0_id) || SM_BASE_ID(sm,v1_id) || SM_BASE_ID(sm,v2_id)) | 
| 700 | – | { | 
| 701 | – | smClear_tri_flags(sm,t_id); | 
| 703 |  | SM_SET_NTH_T_BASE(sm,t_id); | 
| 703 | – | } | 
| 704 |  | else | 
| 705 | < | { | 
| 706 | < | SM_CLR_NTH_T_BASE(sm,t_id); | 
| 707 | < | SM_SET_NTH_T_ACTIVE(sm,t_id); | 
| 708 | < | SM_SET_NTH_T_NEW(sm,t_id); | 
| 709 | < | S_SET_FLAG(T_NTH_V(t,0)); | 
| 710 | < | S_SET_FLAG(T_NTH_V(t,1)); | 
| 711 | < | S_SET_FLAG(T_NTH_V(t,2)); | 
| 712 | < | SM_SAMPLE_TRIS(sm)++; | 
| 713 | < | smNew_tri_cnt++; | 
| 714 | < | } | 
| 705 | > | if(SM_DIR_ID(sm,v0_id) && SM_DIR_ID(sm,v1_id) && SM_DIR_ID(sm,v2_id)) | 
| 706 | > | SM_SET_NTH_T_BG(sm,t_id); | 
| 707 |  |  | 
| 708 | + | S_SET_FLAG(T_NTH_V(t,0)); | 
| 709 | + | S_SET_FLAG(T_NTH_V(t,1)); | 
| 710 | + | S_SET_FLAG(T_NTH_V(t,2)); | 
| 711 | + |  | 
| 712 | + | SM_SET_NTH_T_ACTIVE(sm,t_id); | 
| 713 | + | SM_SET_NTH_T_NEW(sm,t_id); | 
| 714 | + |  | 
| 715 | + | SM_SAMPLE_TRIS(sm)++; | 
| 716 | + | smNew_tri_cnt++; | 
| 717 | + |  | 
| 718 |  | /* return initialized triangle */ | 
| 719 |  | return(t_id); | 
| 720 |  | } | 
| 771 |  | !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(tb,1))) || | 
| 772 |  | !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(tb,2)))) | 
| 773 |  | goto Ltri_error; | 
| 774 | + | /* | 
| 775 |  | if(SM_NTH_TRI(sm,T_NTH_NBR(ta,0))==SM_NTH_TRI(sm,T_NTH_NBR(ta,1)) || | 
| 776 |  | SM_NTH_TRI(sm,T_NTH_NBR(ta,0))==SM_NTH_TRI(sm,T_NTH_NBR(ta,2)) || | 
| 777 |  | SM_NTH_TRI(sm,T_NTH_NBR(ta,1))==SM_NTH_TRI(sm,T_NTH_NBR(ta,2)) || | 
| 779 |  | SM_NTH_TRI(sm,T_NTH_NBR(tb,0))==SM_NTH_TRI(sm,T_NTH_NBR(tb,2)) || | 
| 780 |  | SM_NTH_TRI(sm,T_NTH_NBR(tb,1))==SM_NTH_TRI(sm,T_NTH_NBR(tb,2)) ) | 
| 781 |  | goto Ltri_error; | 
| 782 | + | */ | 
| 783 |  | #endif | 
| 784 |  | /* Reset neighbor pointers of original neighbors */ | 
| 785 |  | n = SM_NTH_TRI(sm,T_NTH_NBR(t,enext)); | 
| 815 |  |  | 
| 816 |  | remove_from_list(t_id,add_ptr); | 
| 817 |  | remove_from_list(t1_id,add_ptr); | 
| 818 | < | #if 1 | 
| 818 | > |  | 
| 819 |  | smDelete_tri(sm,t_id); | 
| 820 |  | smDelete_tri(sm,t1_id); | 
| 817 | – | #else | 
| 818 | – | *del_ptr = push_data(*del_ptr,t_id); | 
| 819 | – | *del_ptr = push_data(*del_ptr,t1_id); | 
| 820 | – | #endif | 
| 821 |  |  | 
| 822 | – |  | 
| 823 | – |  | 
| 822 |  | *tn_id = ta_id; | 
| 823 |  | *tn1_id = tb_id; | 
| 824 |  |  | 
| 848 |  | SM *sm; | 
| 849 |  | LIST *add_list; | 
| 850 |  | { | 
| 851 | < | int t_id,i; | 
| 851 | > | int t_id; | 
| 852 |  | TRI *t; | 
| 855 | – | OBJECT *optr; | 
| 853 |  |  | 
| 854 |  | while(add_list) | 
| 855 |  | { | 
| 869 |  | FVECT p,p0,p1,p2; | 
| 870 |  | int e,e1,swapped = 0; | 
| 871 |  | int t_id,t_opp_id; | 
| 872 | < | LIST *del_list=NULL; | 
| 872 | > | LIST *del_list=NULL,*lptr; | 
| 873 |  |  | 
| 874 |  | VSUB(p,SM_NTH_WV(sm,id),SM_VIEW_CENTER(sm)); | 
| 875 |  | while(tlist) | 
| 906 |  | tlist = push_data(tlist,t_opp_id); | 
| 907 |  | } | 
| 908 |  | } | 
| 909 | < | #if 0 | 
| 913 | < | while(del_list) | 
| 914 | < | { | 
| 915 | < | t_id = pop_list(&del_list); | 
| 916 | < | smDelete_tri(sm,t_id); | 
| 917 | < | } | 
| 918 | < | #endif | 
| 909 | > |  | 
| 910 |  | smUpdate_locator(sm,add_list); | 
| 911 |  |  | 
| 912 |  | return(swapped); | 
| 958 |  | FVECT npt; | 
| 959 |  | TRI *tri,*nbr,*topp; | 
| 960 |  |  | 
| 970 | – |  | 
| 961 |  | add_list = NULL; | 
| 962 |  | for(i=0; i<3;i++) | 
| 963 |  | v_id[i] = T_NTH_V(SM_NTH_TRI(sm,tri_id),i); | 
| 1216 |  | optr = qtqueryset(qt); | 
| 1217 |  | tri_id = smTri_in_set(sm,tpt,optr,onptr,whichptr); | 
| 1218 |  |  | 
| 1229 | – | #ifdef DEBUG | 
| 1230 | – | if(!T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(SM_NTH_TRI(sm,tri_id),0))) || | 
| 1231 | – | !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(SM_NTH_TRI(sm,tri_id),1))) || | 
| 1232 | – | !T_IS_VALID(SM_NTH_TRI(sm,T_NTH_NBR(SM_NTH_TRI(sm,tri_id),2)))) | 
| 1233 | – | eputs("Invalid tri nbrs smPointLocateTri()\n"); | 
| 1234 | – | #endif | 
| 1219 |  | return(tri_id); | 
| 1220 |  | } | 
| 1221 |  |  | 
| 1269 |  |  | 
| 1270 |  | for(i=0; i<3; i++) | 
| 1271 |  | { | 
| 1272 | < | if(SM_BASE_ID(sm,vid[i])) | 
| 1273 | < | { | 
| 1274 | < | bcnt++; | 
| 1275 | < | continue; | 
| 1276 | < | } | 
| 1293 | < | if(SM_DIR_ID(sm,vid[i])) | 
| 1294 | < | dcnt++; | 
| 1295 | < | VSUB(diff[i],SM_NTH_WV(sm,vid[i]),p); | 
| 1296 | < | /* If same world point: replace */ | 
| 1272 | > | if(SM_BASE_ID(sm,vid[i])) | 
| 1273 | > | bcnt++; | 
| 1274 | > | if(SM_DIR_ID(sm,vid[i])) | 
| 1275 | > | dcnt++; | 
| 1276 | > |  | 
| 1277 |  | } | 
| 1278 |  | /* TEST 1: If the new sample is close in ws, and close in the spherical | 
| 1279 |  | projection to one of the triangle vertex samples | 
| 1280 |  | */ | 
| 1281 | + | #if 0 | 
| 1282 |  | norm = FALSE; | 
| 1302 | – | if(bcnt + dcnt != 3) | 
| 1303 | – | { | 
| 1283 |  | VSUB(spt,p,SM_VIEW_CENTER(sm)); | 
| 1284 |  | ds = DOT(spt,spt); | 
| 1285 |  | dnear = FHUGE; | 
| 1286 |  | for(i=0; i<3; i++) | 
| 1287 |  | { | 
| 1309 | – | if(SM_BASE_ID(sm,vid[i]) || SM_DIR_ID(sm,vid[i])) | 
| 1310 | – | continue; | 
| 1288 |  | d = DOT(diff[i],diff[i])/ds; | 
| 1289 |  | if(d < dnear) | 
| 1290 |  | { | 
| 1293 |  | } | 
| 1294 |  | } | 
| 1295 |  |  | 
| 1296 | < | if(dnear <=  smMinSampDiff*smMinSampDiff) | 
| 1296 | > | if(dnear <=  SM_MIN_SAMP_DIFF*SM_MIN_SAMP_DIFF) | 
| 1297 |  | { | 
| 1298 |  | /* Pick the point with dir closest to that of the canonical view | 
| 1299 |  | if it is the new sample: mark existing point for deletion | 
| 1300 |  | */ | 
| 1301 | + | if(SM_BASE_ID(sm,nearid)) | 
| 1302 | + | { | 
| 1303 | + | *rptr = nearid; | 
| 1304 | + | return(TRUE); | 
| 1305 | + | } | 
| 1306 | + | if(SM_DIR_ID(sm,nearid)) | 
| 1307 | + | return(FALSE); | 
| 1308 | + | if(!dir) | 
| 1309 | + | { | 
| 1310 | + | *rptr = nearid; | 
| 1311 | + | return(TRUE); | 
| 1312 | + | } | 
| 1313 |  | normalize(spt); | 
| 1314 |  | norm = TRUE; | 
| 1315 |  | VSUB(npt,SM_NTH_WV(sm,nearid),SM_VIEW_CENTER(sm)); | 
| 1317 |  | d = fdir2diff(SM_NTH_W_DIR(sm,nearid), npt); | 
| 1318 |  | d2 = 2. - 2.*DOT(dir,spt); | 
| 1319 |  | /* The existing sample is a better sample:punt */ | 
| 1320 | < | if(d2 > d) | 
| 1320 | > | if(d2 > d) | 
| 1321 |  | return(FALSE); | 
| 1322 | < | else | 
| 1323 | < | { | 
| 1324 | < | /* The new sample is better: mark the existing one | 
| 1322 | > | else | 
| 1323 | > | { | 
| 1324 | > | /* The new sample is better: mark the existing one | 
| 1325 |  | for deletion after the new one is added*/ | 
| 1326 | < | *rptr = nearid; | 
| 1327 | < | return(TRUE); | 
| 1339 | < | } | 
| 1326 | > | *rptr = nearid; | 
| 1327 | > | return(TRUE); | 
| 1328 |  | } | 
| 1329 | < | } | 
| 1329 | > | } | 
| 1330 | > |  | 
| 1331 |  | /* TEST 3: If the spherical projection of new is < S_REPLACE_EPS | 
| 1332 |  | from a base point: Edge length is constrained to subtend <45 degrees: | 
| 1333 |  | original base mesh edges are approx 32 degrees- so have about 13 degrees | 
| 1334 |  | to work in: S_REPLACE_EPS is the square of the radian value | 
| 1335 |  | */ | 
| 1336 | + |  | 
| 1337 |  | if(bcnt) | 
| 1338 |  | { | 
| 1339 |  | dnear = FHUGE; | 
| 1350 | – | if(bcnt + dcnt ==3) | 
| 1351 | – | VSUB(spt,p,SM_VIEW_CENTER(sm)); | 
| 1340 |  | if(!norm) | 
| 1341 |  | normalize(spt); | 
| 1342 |  |  | 
| 1346 |  | continue; | 
| 1347 |  | VSUB(npt,SM_NTH_WV(sm,vid[i]),SM_VIEW_CENTER(sm)); | 
| 1348 |  | d = DIST_SQ(npt,spt); | 
| 1349 | < | if(d < S_REPLACE_EPS && d < dnear) | 
| 1349 | > | if(dnear <=  SM_MIN_SAMP_DIFF*SM_MIN_SAMP_DIFF && d< near) | 
| 1350 |  | { | 
| 1351 |  | dnear = d; | 
| 1352 |  | nearid = vid[i]; | 
| 1359 |  | return(TRUE); | 
| 1360 |  | } | 
| 1361 |  | } | 
| 1362 | + | #else | 
| 1363 | + | { | 
| 1364 | + | FVECT nearpt; | 
| 1365 | + | dnear = FHUGE; | 
| 1366 | + | VSUB(spt,p,SM_VIEW_CENTER(sm)); | 
| 1367 | + | ds = DOT(spt,spt); | 
| 1368 | + | normalize(spt); | 
| 1369 | + |  | 
| 1370 | + | for(i=0; i<3; i++) | 
| 1371 | + | { | 
| 1372 |  |  | 
| 1373 | + | VSUB(npt,SM_NTH_WV(sm,vid[i]),SM_VIEW_CENTER(sm)); | 
| 1374 | + |  | 
| 1375 | + | if(!SM_BASE_ID(sm,vid[i]) && !SM_DIR_ID(sm,vid[i])) | 
| 1376 | + | normalize(npt); | 
| 1377 | + |  | 
| 1378 | + | d = DIST_SQ(npt,spt); | 
| 1379 | + | if(d < SM_MIN_SAMP_DIFF*SM_MIN_SAMP_DIFF && d < dnear) | 
| 1380 | + | { | 
| 1381 | + | dnear = d; | 
| 1382 | + | nearid = vid[i]; | 
| 1383 | + | VCOPY(nearpt,npt); | 
| 1384 | + | } | 
| 1385 | + |  | 
| 1386 | + | } | 
| 1387 | + | if(dnear != FHUGE) | 
| 1388 | + | { | 
| 1389 | + | /* Pick the point with dir closest to that of the canonical view | 
| 1390 | + | if it is the new sample: mark existing point for deletion | 
| 1391 | + | */ | 
| 1392 | + | if(SM_BASE_ID(sm,nearid)) | 
| 1393 | + | { | 
| 1394 | + | *rptr = nearid; | 
| 1395 | + | return(TRUE); | 
| 1396 | + | } | 
| 1397 | + | if(SM_DIR_ID(sm,nearid)) | 
| 1398 | + | return(FALSE); | 
| 1399 | + | if(!dir) | 
| 1400 | + | { | 
| 1401 | + | *rptr = nearid; | 
| 1402 | + | return(TRUE); | 
| 1403 | + | } | 
| 1404 | + | d = fdir2diff(SM_NTH_W_DIR(sm,nearid), nearpt); | 
| 1405 | + | d2 = 2. - 2.*DOT(dir,spt); | 
| 1406 | + | /* The existing sample is a better sample:punt */ | 
| 1407 | + | if(d2 > d) | 
| 1408 | + | return(FALSE); | 
| 1409 | + | else | 
| 1410 | + | { | 
| 1411 | + | /* The new sample is better: mark the existing one | 
| 1412 | + | for deletion after the new one is added*/ | 
| 1413 | + | *rptr = nearid; | 
| 1414 | + | return(TRUE); | 
| 1415 | + | } | 
| 1416 | + | } | 
| 1417 | + | } | 
| 1418 | + | #endif | 
| 1419 |  | /* TEST 4: | 
| 1420 |  | If the addition of the new sample point would introduce a "puncture" | 
| 1421 |  | or cause new triangles with large depth differences:dont add: | 
| 1422 |  | */ | 
| 1423 |  | if(bcnt || dcnt) | 
| 1424 |  | return(TRUE); | 
| 1425 | + |  | 
| 1426 |  | /* If the new point is in front of the existing points- add */ | 
| 1427 |  | dv = DIST_SQ(SM_NTH_WV(sm,vid[0]),SM_VIEW_CENTER(sm)); | 
| 1428 |  | if(ds < dv) | 
| 1429 |  | return(TRUE); | 
| 1430 |  |  | 
| 1431 |  | d01 = DIST_SQ(SM_NTH_WV(sm,vid[1]),SM_NTH_WV(sm,vid[0])); | 
| 1432 | + | VSUB(diff[0],SM_NTH_WV(sm,vid[0]),p); | 
| 1433 |  | s0 = DOT(diff[0],diff[0]); | 
| 1434 |  | if(s0 < S_REPLACE_SCALE*d01) | 
| 1435 |  | return(TRUE); | 
| 1436 | + |  | 
| 1437 |  | d12 = DIST_SQ(SM_NTH_WV(sm,vid[2]),SM_NTH_WV(sm,vid[1])); | 
| 1438 |  | if(s0 < S_REPLACE_SCALE*d12) | 
| 1439 |  | return(TRUE); | 
| 1441 |  | if(s0 < S_REPLACE_SCALE*d20) | 
| 1442 |  | return(TRUE); | 
| 1443 |  | d = MIN3(d01,d12,d20); | 
| 1444 | < | s1 = DOT(diff[1],diff[1]); | 
| 1444 | > | VSUB(diff[1],SM_NTH_WV(sm,vid[1]),p); | 
| 1445 | > | s1 = DOT(diff[1],diff[1]); | 
| 1446 |  | if(s1 < S_REPLACE_SCALE*d) | 
| 1447 |  | return(TRUE); | 
| 1448 | + | VSUB(diff[2],SM_NTH_WV(sm,vid[2]),p); | 
| 1449 |  | s2 = DOT(diff[2],diff[2]); | 
| 1450 |  | if(s2 < S_REPLACE_SCALE*d) | 
| 1451 |  | return(TRUE); | 
| 1462 |  | return(FALSE); | 
| 1463 |  | } | 
| 1464 |  |  | 
| 1465 | < |  | 
| 1417 | < | int | 
| 1418 | < | smAlloc_samp(sm) | 
| 1465 | > | smReplace_base_samp(sm,b_id,s_id,tri,t_id,which) | 
| 1466 |  | SM *sm; | 
| 1467 | + | int b_id,s_id; | 
| 1468 | + | TRI *tri; | 
| 1469 | + | int t_id,which; | 
| 1470 |  | { | 
| 1471 | < | int s_id,replaced,cnt; | 
| 1422 | < | SAMP *s; | 
| 1423 | < | FVECT p; | 
| 1471 | > | TRI *t; | 
| 1472 |  |  | 
| 1473 | < | s = SM_SAMP(sm); | 
| 1474 | < | s_id = sAlloc_samp(s,&replaced); | 
| 1475 | < |  | 
| 1476 | < | cnt=0; | 
| 1477 | < | while(replaced) | 
| 1473 | > | SM_NTH_VERT(sm,s_id) = t_id; | 
| 1474 | > | T_NTH_V(tri,which) = s_id; | 
| 1475 | > | if(!(SM_BASE_ID(sm,T_NTH_V(tri,(which+1)%3)) || | 
| 1476 | > | SM_BASE_ID(sm,T_NTH_V(tri,(which+2)%3)))) | 
| 1477 | > | SM_CLR_NTH_T_BASE(sm,t_id); | 
| 1478 | > | if(!SM_IS_NTH_T_NEW(sm,t_id)) | 
| 1479 |  | { | 
| 1480 | < | if(smRemoveVertex(sm,s_id)) | 
| 1481 | < | break; | 
| 1433 | < | s_id = sAlloc_samp(s,&replaced); | 
| 1434 | < | cnt++; | 
| 1435 | < | if(cnt > S_MAX_SAMP(s)) | 
| 1436 | < | error(CONSISTENCY,"smAlloc_samp():unable to find free samp\n"); | 
| 1480 | > | smNew_tri_cnt++; | 
| 1481 | > | SM_SET_NTH_T_NEW(sm,t_id); | 
| 1482 |  | } | 
| 1483 | < | return(s_id); | 
| 1483 | > | t_id = smTri_next_ccw_nbr(sm,tri,b_id); | 
| 1484 | > | while(t_id != INVALID) | 
| 1485 | > | { | 
| 1486 | > | t = SM_NTH_TRI(sm,t_id); | 
| 1487 | > | which = T_WHICH_V(t,b_id); | 
| 1488 | > | T_NTH_V(t,which) = s_id; | 
| 1489 | > | /* Check if still a base triangle */ | 
| 1490 | > | if(!(SM_BASE_ID(sm,T_NTH_V(t,(which+1)%3)) || | 
| 1491 | > | SM_BASE_ID(sm,T_NTH_V(t,(which+2)%3)))) | 
| 1492 | > | SM_CLR_NTH_T_BASE(sm,t_id); | 
| 1493 | > | if(!SM_IS_NTH_T_NEW(sm,t_id)) | 
| 1494 | > | { | 
| 1495 | > | smNew_tri_cnt++; | 
| 1496 | > | SM_SET_NTH_T_NEW(sm,t_id); | 
| 1497 | > | } | 
| 1498 | > | t_id = smTri_next_ccw_nbr(sm,t,b_id); | 
| 1499 | > | } | 
| 1500 |  | } | 
| 1501 |  |  | 
| 1502 |  | int | 
| 1506 |  | FVECT dir,p; | 
| 1507 |  | int s_id,t_id,o_id,on,which; | 
| 1508 |  | { | 
| 1509 | < | int tonemap,v_id; | 
| 1509 | > | int v_id,tri_id; | 
| 1510 |  | TRI *t,*tri; | 
| 1511 |  |  | 
| 1512 |  | tri = SM_NTH_TRI(sm,t_id); | 
| 1515 |  | /* If it is a base id, need new sample */ | 
| 1516 |  | if(SM_BASE_ID(sm,v_id)) | 
| 1517 |  | { | 
| 1518 | < | tonemap = (SM_TONE_MAP(sm) > s_id); | 
| 1519 | < | sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id,tonemap); | 
| 1459 | < | SM_NTH_VERT(sm,s_id) = t_id; | 
| 1460 | < | T_NTH_V(tri,which) = s_id; | 
| 1461 | < | if(!(SM_BASE_ID(sm,T_NTH_V(tri,(which+1)%3)) || | 
| 1462 | < | SM_BASE_ID(sm,T_NTH_V(tri,(which+2)%3)))) | 
| 1463 | < | SM_CLR_NTH_T_BASE(sm,t_id); | 
| 1464 | < | t_id = smTri_next_ccw_nbr(sm,tri,v_id); | 
| 1465 | < | while(t_id != INVALID) | 
| 1466 | < | { | 
| 1467 | < | t = SM_NTH_TRI(sm,t_id); | 
| 1468 | < | which = T_WHICH_V(t,v_id); | 
| 1469 | < | T_NTH_V(t,which) = s_id; | 
| 1470 | < | /* Check if still a base triangle */ | 
| 1471 | < | if(!(SM_BASE_ID(sm,T_NTH_V(t,(which+1)%3)) || | 
| 1472 | < | SM_BASE_ID(sm,T_NTH_V(t,(which+2)%3)))) | 
| 1473 | < | SM_CLR_NTH_T_BASE(sm,t_id); | 
| 1474 | < | t_id = smTri_next_ccw_nbr(sm,t,v_id); | 
| 1475 | < | } | 
| 1518 | > | sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id); | 
| 1519 | > | smReplace_base_samp(sm,v_id,s_id,tri,t_id,which); | 
| 1520 |  | return(s_id); | 
| 1521 |  | } | 
| 1522 | < | else | 
| 1523 | < | if(on == ON_V || !p) | 
| 1522 | > | if(dir) | 
| 1523 | > | { | 
| 1524 | > | /* If world point */ | 
| 1525 | > | /* if existing point is a dir: leave */ | 
| 1526 | > | if(SM_DIR_ID(sm,v_id)) | 
| 1527 | > | return(INVALID); | 
| 1528 | > | if(on == ON_V) | 
| 1529 |  | { | 
| 1530 | < | tonemap = (SM_TONE_MAP(sm) > v_id); | 
| 1531 | < | sInit_samp(SM_SAMP(sm),v_id,c,dir,p,o_id,tonemap); | 
| 1530 | > | sInit_samp(SM_SAMP(sm),v_id,c,dir,p,o_id); | 
| 1531 | > |  | 
| 1532 | > | if(!SM_IS_NTH_T_NEW(sm,t_id)) | 
| 1533 | > | { | 
| 1534 | > | smNew_tri_cnt++; | 
| 1535 | > | SM_SET_NTH_T_NEW(sm,t_id); | 
| 1536 | > | } | 
| 1537 | > | tri_id = smTri_next_ccw_nbr(sm,tri,v_id); | 
| 1538 | > | while(tri_id != t_id) | 
| 1539 | > | { | 
| 1540 | > | t = SM_NTH_TRI(sm,tri_id); | 
| 1541 | > | if(!SM_IS_NTH_T_NEW(sm,tri_id)) | 
| 1542 | > | { | 
| 1543 | > | smNew_tri_cnt++; | 
| 1544 | > | SM_SET_NTH_T_NEW(sm,tri_id); | 
| 1545 | > | } | 
| 1546 | > |  | 
| 1547 | > | tri_id = smTri_next_ccw_nbr(sm,t,v_id); | 
| 1548 | > | } | 
| 1549 |  | return(v_id); | 
| 1550 |  | } | 
| 1551 | < | else /* on == ON_P */ | 
| 1552 | < | { | 
| 1553 | < | FVECT spt,npt; | 
| 1554 | < | double d,d2; | 
| 1551 | > | /* on == ON_P */ | 
| 1552 | > | else | 
| 1553 | > | { | 
| 1554 | > | FVECT spt,npt; | 
| 1555 | > | double d,d2; | 
| 1556 |  |  | 
| 1557 | < | /* Need to check which sample is preferable */ | 
| 1558 | < | VSUB(spt,p,SM_VIEW_CENTER(sm)); | 
| 1559 | < | normalize(spt); | 
| 1557 | > | /* Need to check which sample is preferable */ | 
| 1558 | > | VSUB(spt,p,SM_VIEW_CENTER(sm)); | 
| 1559 | > | normalize(spt); | 
| 1560 |  |  | 
| 1561 | < | VSUB(npt,SM_NTH_WV(sm,v_id),SM_VIEW_CENTER(sm)); | 
| 1562 | < | normalize(npt); | 
| 1563 | < | d = fdir2diff(SM_NTH_W_DIR(sm,v_id), npt); | 
| 1564 | < | d2 = 2. - 2.*DOT(dir,spt); | 
| 1561 | > | VSUB(npt,SM_NTH_WV(sm,v_id),SM_VIEW_CENTER(sm)); | 
| 1562 | > | normalize(npt); | 
| 1563 | > | d = fdir2diff(SM_NTH_W_DIR(sm,v_id), npt); | 
| 1564 | > | d2 = 2. - 2.*DOT(dir,spt); | 
| 1565 |  | /* The existing sample is a better sample:punt */ | 
| 1566 | < | if(d2 < d) | 
| 1567 | < | { | 
| 1568 | < | /* The new sample has better information- replace values */ | 
| 1569 | < | tonemap = (SM_TONE_MAP(sm) > v_id); | 
| 1570 | < | sInit_samp(SM_SAMP(sm),v_id,c,dir,p,o_id,tonemap); | 
| 1571 | < | } | 
| 1572 | < | return(v_id); | 
| 1566 | > | if(d2 < d) | 
| 1567 | > | { | 
| 1568 | > | /* The new sample has better information- replace values */ | 
| 1569 | > | sInit_samp(SM_SAMP(sm),v_id,c,dir,p,o_id); | 
| 1570 | > | if(!SM_IS_NTH_T_NEW(sm,t_id)) | 
| 1571 | > | { | 
| 1572 | > | smNew_tri_cnt++; | 
| 1573 | > | SM_SET_NTH_T_NEW(sm,t_id); | 
| 1574 | > | } | 
| 1575 | > |  | 
| 1576 | > | tri_id = smTri_next_ccw_nbr(sm,tri,v_id); | 
| 1577 | > | while(tri_id != t_id) | 
| 1578 | > | { | 
| 1579 | > | t = SM_NTH_TRI(sm,tri_id); | 
| 1580 | > | if(!SM_IS_NTH_T_NEW(sm,tri_id)) | 
| 1581 | > | { | 
| 1582 | > | smNew_tri_cnt++; | 
| 1583 | > | SM_SET_NTH_T_NEW(sm,tri_id); | 
| 1584 | > | } | 
| 1585 | > | tri_id = smTri_next_ccw_nbr(sm,t,v_id); | 
| 1586 | > | } | 
| 1587 | > | } | 
| 1588 | > | return(v_id); | 
| 1589 | > | } | 
| 1590 | > | } | 
| 1591 | > | else | 
| 1592 | > | { /* New point is a dir */ | 
| 1593 | > | return(INVALID); | 
| 1594 |  | } | 
| 1595 |  | } | 
| 1596 |  |  | 
| 1597 | + | int | 
| 1598 | + | smAlloc_samp(sm) | 
| 1599 | + | SM *sm; | 
| 1600 | + | { | 
| 1601 | + | int s_id,replaced,cnt; | 
| 1602 | + | SAMP *s; | 
| 1603 | + | FVECT p; | 
| 1604 | + |  | 
| 1605 | + | s = SM_SAMP(sm); | 
| 1606 | + | s_id = sAlloc_samp(s,&replaced); | 
| 1607 | + |  | 
| 1608 | + | cnt=0; | 
| 1609 | + | while(replaced) | 
| 1610 | + | { | 
| 1611 | + | if(smRemoveVertex(sm,s_id)) | 
| 1612 | + | break; | 
| 1613 | + | s_id = sAlloc_samp(s,&replaced); | 
| 1614 | + | cnt++; | 
| 1615 | + | if(cnt > S_MAX_SAMP(s)) | 
| 1616 | + | error(CONSISTENCY,"smAlloc_samp():unable to find free samp\n"); | 
| 1617 | + | } | 
| 1618 | + | return(s_id); | 
| 1619 | + | } | 
| 1620 | + |  | 
| 1621 | + |  | 
| 1622 |  | /* Add sample to the mesh: | 
| 1623 |  |  | 
| 1624 |  | the sample can be a world space or directional point. If o_id !=INVALID, | 
| 1650 |  | /* If sample is a world space point */ | 
| 1651 |  | if(p) | 
| 1652 |  | { | 
| 1653 | < | t_id = smPointLocateTri(sm,p,&on,&which); | 
| 1654 | < | if(t_id == INVALID) | 
| 1653 | > | while(1) | 
| 1654 | > | { | 
| 1655 | > | t_id = smPointLocateTri(sm,p,&on,&which); | 
| 1656 | > | if(t_id == INVALID) | 
| 1657 |  | { | 
| 1658 |  | #ifdef DEBUG | 
| 1659 | < | eputs("smAddSamp(): unable to locate tri containing sample \n"); | 
| 1659 | > | eputs("smAddSamp(): unable to locate tri containing sample \n"); | 
| 1660 |  | #endif | 
| 1661 | + | smUnalloc_samp(sm,s_id); | 
| 1662 | + | return(INVALID); | 
| 1663 | + | } | 
| 1664 | + | /* If spherical projection coincides with existing sample: replace */ | 
| 1665 | + | if((on == ON_V || on == ON_P)) | 
| 1666 | + | { | 
| 1667 | + | n_id = smReplace_samp(sm,c,dir,p,s_id,t_id,o_id,on,which); | 
| 1668 | + | if(n_id!= s_id) | 
| 1669 | + | smUnalloc_samp(sm,s_id); | 
| 1670 | + | return(n_id); | 
| 1671 | + | } | 
| 1672 | + | if((!(smTest_sample(sm,t_id,dir,p,&r_id)))) | 
| 1673 | + | { | 
| 1674 |  | smUnalloc_samp(sm,s_id); | 
| 1675 |  | return(INVALID); | 
| 1676 |  | } | 
| 1677 | < | /* If spherical projection coincides with existing sample: replace */ | 
| 1678 | < | if((on == ON_V || on == ON_P)) | 
| 1679 | < | { | 
| 1680 | < | if((n_id = smReplace_samp(sm,c,dir,p,s_id,t_id,o_id,on,which))!= s_id) | 
| 1681 | < | smUnalloc_samp(sm,s_id); | 
| 1682 | < | return(n_id); | 
| 1677 | > | if(r_id != INVALID) | 
| 1678 | > | { | 
| 1679 | > | smRemoveVertex(sm,r_id); | 
| 1680 | > | sDelete_samp(SM_SAMP(sm),r_id); | 
| 1681 | > | } | 
| 1682 | > | else | 
| 1683 | > | break; | 
| 1684 |  | } | 
| 1556 | – | if((!(smTest_sample(sm,t_id,dir,p,&r_id)))) | 
| 1557 | – | { | 
| 1558 | – | smUnalloc_samp(sm,s_id); | 
| 1559 | – | return(INVALID); | 
| 1560 | – | } | 
| 1685 |  | /* If sample is being added in the middle of the sample array: tone | 
| 1686 |  | map individually | 
| 1687 |  | */ | 
| 1688 |  | /* Initialize sample */ | 
| 1689 | < | sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id,(SM_TONE_MAP(sm)>s_id)); | 
| 1689 | > | sInit_samp(SM_SAMP(sm),s_id,c,dir,p,o_id); | 
| 1690 |  |  | 
| 1691 |  | } | 
| 1692 |  | /* If sample is a direction vector */ | 
| 1693 |  | else | 
| 1694 |  | { | 
| 1695 |  | VADD(wpt,dir,SM_VIEW_CENTER(sm)); | 
| 1696 | < | t_id = smPointLocateTri(sm,wpt,&on,&which); | 
| 1697 | < | if(t_id == INVALID) | 
| 1698 | < | { | 
| 1696 | > | while(1) | 
| 1697 | > | { | 
| 1698 | > | t_id = smPointLocateTri(sm,wpt,&on,&which); | 
| 1699 | > | if(t_id == INVALID) | 
| 1700 | > | { | 
| 1701 |  | #ifdef DEBUG | 
| 1702 | < | eputs("smAddSamp(): unable to locate tri containing sample \n"); | 
| 1702 | > | eputs("smAddSamp(): can'tlocate tri containing samp\n"); | 
| 1703 |  | #endif | 
| 1704 | < | smUnalloc_samp(sm,s_id); | 
| 1705 | < | return(INVALID); | 
| 1704 | > | smUnalloc_samp(sm,s_id); | 
| 1705 | > | return(INVALID); | 
| 1706 | > | } | 
| 1707 | > | if(on == ON_V || on == ON_P) | 
| 1708 | > | { | 
| 1709 | > | n_id=smReplace_samp(sm,c,NULL,wpt,s_id,t_id,o_id,on,which); | 
| 1710 | > | if(n_id !=s_id) | 
| 1711 | > | smUnalloc_samp(sm,s_id); | 
| 1712 | > | return(n_id); | 
| 1713 | > | } | 
| 1714 | > | if((!(smTest_sample(sm,t_id,NULL,wpt,&r_id)))) | 
| 1715 | > | { | 
| 1716 | > | smUnalloc_samp(sm,s_id); | 
| 1717 | > | return(INVALID); | 
| 1718 | > | } | 
| 1719 | > | if(r_id != INVALID) | 
| 1720 | > | { | 
| 1721 | > | smRemoveVertex(sm,r_id); | 
| 1722 | > | sDelete_samp(SM_SAMP(sm),r_id); | 
| 1723 | > | } | 
| 1724 | > | else | 
| 1725 | > | break; | 
| 1726 |  | } | 
| 1581 | – | if(on == ON_V || on == ON_P) | 
| 1582 | – | { | 
| 1583 | – | if((n_id = smReplace_samp(sm,c,wpt,NULL,s_id,t_id,o_id,on,which))!= s_id) | 
| 1584 | – | smUnalloc_samp(sm,s_id); | 
| 1585 | – | return(n_id); | 
| 1586 | – | } | 
| 1727 |  | /* Allocate space for a sample and initialize */ | 
| 1728 | < | sInit_samp(SM_SAMP(sm),s_id,c,wpt,NULL,o_id,(SM_TONE_MAP(sm)>s_id)); | 
| 1728 | > | sInit_samp(SM_SAMP(sm),s_id,c,NULL,wpt,o_id); | 
| 1729 |  | } | 
| 1730 |  | if(!SM_DIR_ID(sm,s_id)) | 
| 1731 |  | { | 
| 1736 |  | } | 
| 1737 |  | smInsert_samp(sm,s_id,t_id,on,which); | 
| 1738 |  |  | 
| 1599 | – | /* If new sample replaces existing one- remove that vertex now */ | 
| 1600 | – | if(r_id != INVALID) | 
| 1601 | – | { | 
| 1602 | – | smRemoveVertex(sm,r_id); | 
| 1603 | – | sDelete_samp(SM_SAMP(sm),r_id); | 
| 1604 | – | } | 
| 1739 |  | return(s_id); | 
| 1740 |  | } | 
| 1741 |  |  | 
| 1758 |  | { | 
| 1759 |  | int s_id; | 
| 1760 |  |  | 
| 1627 | – |  | 
| 1761 |  | /* First check if this the first sample: if so initialize mesh */ | 
| 1629 | – |  | 
| 1762 |  | if(SM_NUM_SAMP(smMesh) == 0) | 
| 1763 |  | { | 
| 1764 |  | smInit_sm(smMesh,odev.v.vp); | 
| 1859 |  | } | 
| 1860 |  |  | 
| 1861 |  |  | 
| 1862 | + |  | 
| 1863 |  | int | 
| 1864 |  | smNext_valid_tri(sm,i) | 
| 1865 |  | SM *sm; | 
| 1940 |  | } | 
| 1941 |  |  | 
| 1942 |  | } | 
| 1810 | – |  | 
| 1811 | – | smNew_tri_cnt = SM_SAMPLE_TRIS(sm); | 
| 1943 |  | #ifdef DEBUG | 
| 1944 |  | fprintf(stderr,"smRebuild_mesh():done\n"); | 
| 1945 |  | #endif | 
| 2276 |  | t_id = QT_SET_NEXT_ELEM(optr); | 
| 2277 |  | /* Set the render flag */ | 
| 2278 |  | tri = SM_NTH_TRI(smMesh,t_id); | 
| 2279 | < | if(!T_IS_VALID(tri) ||  SM_IS_NTH_T_BASE(smMesh,t_id)) | 
| 2279 | > | if(!T_IS_VALID(tri)) | 
| 2280 |  | continue; | 
| 2281 |  | SM_SET_NTH_T_ACTIVE(smMesh,t_id); | 
| 2282 |  | /* Set the Active bits of the Vertices */ | 
| 2283 |  | S_SET_FLAG(T_NTH_V(tri,0)); | 
| 2284 |  | S_SET_FLAG(T_NTH_V(tri,1)); | 
| 2285 |  | S_SET_FLAG(T_NTH_V(tri,2)); | 
| 2286 | < | } | 
| 2286 | > | } | 
| 2287 |  | } | 
| 2288 |  |  | 
| 2289 |  |  |