1
/************************************************************************************************
5
Original Location : http://www-dinma.univ.trieste.it/~nirftc/research/easymesh/easymesh.html
6
modified : Eric Espie (eric.espie@torcs.org)
7
copyright : Bojan NICENO & Eric Espie (parts)
8
version : $Id: easymesh.cpp,v 1.11 2005/06/30 22:23:45 berniw Exp $
10
************************************************************************************************/
20
#include <robottools.h>
23
#include "elevation.h"
32
static tdble ExtHeight;
33
static tdble GridStep;
34
static tdble TrackStep;
35
static char buf[1024];
36
static const char *TexName;
41
#define max(a,b) (((a) > (b)) ? (a) : (b))
44
#define min(a,b) (((a) < (b)) ? (a) : (b))
47
#define PI 3.14159265359
54
#define OFF -1 /* element is switched off */
55
#define WAIT -2 /* node is waiting (it is a corner node) */
60
#define MAX_NODES 15000
62
/*-----------------------------+
63
| definitions for the chains |
64
+-----------------------------*/
76
int mark; /* is it off (ON or OFF) */
77
int state; /* is it (D)one, (A)ctive or (W)aiting */
80
double xv, yv, xin, yin, R, r, Det;
82
int new_numb; /* used for renumeration */
89
int ea, eb; /* left and right element */
90
int a, b, c, d; /* left, right, start and end point */
92
int mark; /* is it off, is on the boundary */
96
int new_numb; /* used for renumeration */
101
struct nod node[MAX_NODES], *point;
112
int Ne, Nn, Ns, Nc, Fl; /* number of: elements, nodes, sides */
113
int ugly; /* mora li biti globalna ??? */
115
double xmax, xmin, ymax, ymin;
142
struct vtx *vertices;
146
struct surf *surfaces;
149
#define SURF_INCR 100
152
static struct group *Groups;
153
static int ActiveGroups;
154
static float GroupSize;
155
static float XGroupOffset;
156
static float YGroupOffset;
161
void swap_side(int s);
164
/*=========================================================================*/
165
double area(struct nod *na, struct nod *nb, struct nod *nc)
167
return 0.5 * (((*nb).x - (*na).x) * ((*nc).y - (*na).y)
168
- ((*nb).y - (*na).y) * ((*nc).x - (*na).x));
170
/*-------------------------------------------------------------------------*/
173
/*=========================================================================*/
174
double dist(struct nod *na, struct nod *nb)
176
return sqrt(((*nb).x-(*na).x)*((*nb).x-(*na).x)
177
+ ((*nb).y-(*na).y)*((*nb).y-(*na).y) );
179
/*-------------------------------------------------------------------------*/
182
/*=========================================================================*/
183
int in_elem(struct nod *n)
187
for (e = 0; e < Ne; e++) { /* This must search through all elements ?? */
188
if (area(n, &node[elem[e].i], &node[elem[e].j]) >= 0.0
189
&& area(n, &node[elem[e].j], &node[elem[e].k]) >= 0.0
190
&& area(n, &node[elem[e].k], &node[elem[e].i]) >= 0.0) {
196
/*-in_elem-----------------------------------------------------------------*/
199
/*=========================================================================*/
200
void bowyer(int n, int spac)
207
for (s = 0; s < Ns; s++) {
208
if (side[s].mark == 0) {
209
if (side[s].a == n) {
214
if (dist(&vor, &node[n]) < elem[e].R) {
220
if (side[s].b == n) {
225
if (dist(&vor, &node[n]) < elem[e].R) {
237
/*-bowyer------------------------------------------------------------------*/
240
/*=========================================================================*/
241
/*---------------------------------------------------+
242
| This function calculates radii of inscribed and |
243
| circumscribed circle for a given element (int e) |
244
+---------------------------------------------------*/
247
double x, y, xi, yi, xj, yj, xk, yk, xij, yij, xjk, yjk, num, den;
248
double si, sj, sk, O;
250
xi = node[elem[e].i].x;
251
yi = node[elem[e].i].y;
252
xj = node[elem[e].j].x;
253
yj = node[elem[e].j].y;
254
xk = node[elem[e].k].x;
255
yk = node[elem[e].k].y;
257
xij = 0.5 * (xi + xj);
258
yij = 0.5 * (yi + yj);
259
xjk = 0.5 * (xj + xk);
260
yjk = 0.5 * (yj + yk);
262
num = (xij - xjk) * (xj - xi) + (yij - yjk) * (yj - yi);
263
den = (xj - xi) * (yk - yj) - (xk - xj) * (yj - yi);
266
elem[e].xv = x = xjk + num / den * (yk - yj);
267
elem[e].yv = y = yjk - num / den * (xk - xj);
268
elem[e].R = sqrt((xi - x) * (xi - x) + (yi - y) * (yi - y));
272
si = side[elem[e].si].s;
273
sj = side[elem[e].sj].s;
274
sk = side[elem[e].sk].s;
276
elem[e].Det = xi * (yj - yk) - xj * (yi - yk) + xk * (yi - yj);
278
elem[e].xin = (xi * si + xj * sj + xk * sk ) / O;
279
elem[e].yin = (yi * si + yj * sj + yk * sk ) / O;
281
elem[e].r = elem[e].Det / O;
283
/*-circles-----------------------------------------------------------------*/
286
/*=========================================================================*/
287
/*----------------------------------------------------------------+
288
| This function calculates the value of the spacing function in |
289
| a new node 'n' which is inserted in element 'e' by a linear |
290
| approximation from the values of the spacing function in the |
292
+----------------------------------------------------------------*/
293
void spacing(int e, int n)
295
double dxji, dxki, dyji, dyki, dx_i, dy_i, det, a, b;
297
dxji = node[elem[e].j].x - node[elem[e].i].x;
298
dyji = node[elem[e].j].y - node[elem[e].i].y;
299
dxki = node[elem[e].k].x - node[elem[e].i].x;
300
dyki = node[elem[e].k].y - node[elem[e].i].y;
301
dx_i = node[n].x - node[elem[e].i].x;
302
dy_i = node[n].y - node[elem[e].i].y;
304
det = dxji*dyki - dxki*dyji;
306
a = (+dyki * dx_i - dxki * dy_i) / det;
307
b = (-dyji * dx_i + dxji * dy_i) / det;
309
node[n].F = node[elem[e].i].F +
310
a * (node[elem[e].j].F - node[elem[e].i].F) +
311
b * (node[elem[e].k].F - node[elem[e].i].F);
313
/*-spacing-----------------------------------------------------------------*/
316
/*=========================================================================*/
317
int insert_node(double x, double y, double z, int spac,
318
int prev_n, int prev_s_mark, int mark, int next_s_mark, int next_n)
320
int i,j,k,e,ei,ej,ek, s,si,sj,sk;
323
Nn++; /* one new node */
324
//if ((Nn % 100) == 0) {
325
printf("\r%d Nodes", Nn);
329
if (Nn > MAX_NODES) {
330
printf("\nResize MAX_NODES... > %d\n", MAX_NODES);
334
if ((x < xmin) || (x > xmax) || (y < ymin) || (y > ymax)) {
335
printf("\nDon't Insert %f %f\n", x, y);
337
/* if (x < xmin) x = xmin; */
338
/* if (x > xmax) x = xmax; */
339
/* if (y < ymin) y = ymin; */
340
/* if (y > ymax) y = ymax; */
346
node[Nn-1].mark = mark;
348
/* find the element which contains new node */
349
e = in_elem(&node[Nn-1]);
351
/* calculate the spacing function in the new node */
372
elem[Ne-2].i = Nn - 1;
375
elem[Ne-1].i = Nn - 1;
380
elem[Ne-2].ej = Ne - 1;
384
elem[Ne-1].ek = Ne - 2;
387
elem[Ne-2].sj = Ns - 2;
388
elem[Ne-2].sk = Ns - 3;
390
elem[Ne-1].sj = Ns - 1;
391
elem[Ne-1].sk = Ns - 2;
397
side[Ns-3].d = Nn - 1; /* c-d */
399
side[Ns-3].b = i; /* a-b */
401
side[Ns-3].eb = Ne - 2;
404
side[Ns-2].d = Nn - 1; /* c-d */
406
side[Ns-2].b = j; /* a-b */
407
side[Ns-2].ea = Ne - 2;
408
side[Ns-2].eb = Ne - 1;
411
side[Ns-1].d = Nn - 1; /* c-d */
413
side[Ns-1].b = k; /* a-b */
414
side[Ns-1].ea = Ne - 1;
417
for (s = 1; s <= 3; s++) {
418
sx = node[side[Ns-s].c].x - node[side[Ns-s].d].x;
419
sy = node[side[Ns-s].c].y - node[side[Ns-s].d].y;
420
side[Ns-s].s = sqrt(sx * sx + sy * sy);
429
if (side[si].a == i) {
433
if (side[si].b == i) {
438
if (side[sj].a == j) {
440
side[sj].ea = Ne - 2;
442
if (side[sj].b == j) {
444
side[sj].eb = Ne - 2;
447
if (side[sk].a == k) {
449
side[sk].ea = Ne - 1;
451
if (side[sk].b == k) {
453
side[sk].eb = Ne - 1;
457
if (elem[ej].ei == e) {
458
elem[ej].ei = Ne - 2;
460
if (elem[ej].ej == e) {
463
if (elem[ej].ek == e) {
464
elem[ej].ek = Ne - 2;
469
if (elem[ek].ei == e) {
470
elem[ek].ei = Ne - 1;
472
if (elem[ek].ej == e) {
473
elem[ek].ej = Ne - 1;
475
if (elem[ek].ek == e) {
476
elem[ek].ek = Ne - 1;
480
/* Find circumenters for two new elements,
481
and for the one who's segment has changed */
486
bowyer(Nn - 1, spac);
488
/*-------------------------------------------------+
489
| NEW ! Insert boundary conditions for the sides |
490
+-------------------------------------------------*/
491
for (s = 3; s < Ns; s++) {
492
if (side[s].c == prev_n && side[s].d == Nn - 1) {
493
side[s].mark = prev_s_mark;
495
if (side[s].d == prev_n && side[s].c == Nn - 1) {
496
side[s].mark = prev_s_mark;
498
if (side[s].c == next_n && side[s].d == Nn - 1) {
499
side[s].mark = next_s_mark;
501
if (side[s].d == next_n && side[s].c == Nn - 1) {
502
side[s].mark = next_s_mark;
508
/*-insert_node-------------------------------------------------------------*/
511
/*=========================================================================*/
512
void swap_side(int s)
514
int a, b, c, d, ea, eb, eac = 0, ead = 0, ebc = 0, ebd = 0, sad = 0, sac = 0, sbc = 0, sbd = 0;
524
if (elem[ea].ei == eb) {
531
if (elem[ea].ej == eb) {
538
if (elem[ea].ek == eb) {
545
if (elem[eb].ei == ea) {
552
if (elem[eb].ej == ea) {
559
if (elem[eb].ek == ea) {
587
if (elem[eac].ei == ea) {
590
if (elem[eac].ej == ea) {
593
if (elem[eac].ek == ea) {
599
if (elem[ebd].ei == eb) {
602
if (elem[ebd].ej == eb) {
605
if (elem[ebd].ek == eb) {
610
if (side[sad].ea == ea) {
613
if (side[sad].eb == ea) {
617
if (side[sbc].ea == eb) {
620
if (side[sbc].eb == eb) {
624
if (side[sbd].ea == eb) {
628
if (side[sbd].eb == eb) {
649
sx = node[side[s].c].x - node[side[s].d].x;
650
sy = node[side[s].c].y - node[side[s].d].y;
651
side[s].s = sqrt(sx * sx + sy * sy);
653
if (side[sac].ea == ea) {
657
if (side[sac].eb == ea) {
662
if (side[sad].ea == ea) {
665
if (side[sad].eb == ea) {
669
if (side[sbc].ea == eb) {
672
if (side[sbc].eb == eb) {
676
if (side[sbd].ea == eb) {
680
if (side[sbd].eb == eb) {
688
/*-swap_side---------------------------------------------------------------*/
691
/*=========================================================================*/
698
/*--------------------------+
700
| Negative area check for |
701
| elimination of elements |
703
+--------------------------*/
704
for (e = 0; e < Ne; e++) {
705
if ((node[elem[e].i].chain == node[elem[e].j].chain) &&
706
(node[elem[e].j].chain == node[elem[e].k].chain) &&
707
(chain[node[elem[e].i].chain].type == CLOSED)) {
708
a = min(min(elem[e].i, elem[e].j), elem[e].k);
709
c = max(max(elem[e].i, elem[e].j), elem[e].k);
710
b = elem[e].i + elem[e].j + elem[e].k - a - c;
715
if (area(&node[a], &node[b], &node[c]) < 0.0) {
723
for (e = 0; e < Ne; e++) {
724
if (elem[elem[e].ei].mark == OFF) {
727
if (elem[elem[e].ej].mark == OFF) {
730
if (elem[elem[e].ek].mark == OFF) {
735
/*-----------------------+
737
| Elimination of sides |
739
+-----------------------*/
740
for (s = 0; s < 3; s++) {
744
for (s = 3; s < Ns; s++) {
745
if ((elem[side[s].ea].mark == OFF) && (elem[side[s].eb].mark == OFF)) {
751
for (s = 3; s < Ns; s++) {
752
if (side[s].mark != OFF) {
753
if (elem[side[s].ea].mark == OFF) {
757
if (elem[side[s].eb].mark == OFF) {
765
/*-----------------------+
767
| Elimination of nodes |
769
+-----------------------*/
770
for (n = 0; n < 3; n++) {
776
/*-erase-------------------------------------------------------------------*/
779
/*=========================================================================*/
782
int ea, eb, eac = 0, ead = 0, ebc = 0, ebd = 0, s;
784
for (s = 0; s < Ns; s++) {
786
if (side[s].mark != OFF) {
790
if (elem[ea].ei == eb) {
794
if (elem[ea].ej == eb) {
798
if (elem[ea].ek == eb) {
802
if (elem[eb].ei == ea) {
806
if (elem[eb].ej == ea) {
810
if (elem[eb].ek == ea) {
815
if ((eac == OFF || elem[eac].state == D) &&
816
(ebc == OFF || elem[ebc].state == D) &&
817
(ead == OFF || elem[ead].state == D) &&
818
(ebd == OFF || elem[ebd].state == D)) {
826
/*-diamond-----------------------------------------------------------------*/
829
/*=========================================================================*/
831
/*----------------------------------------------------------+
832
| This function searches through all elements every time. |
833
| Some optimisation will definitely bee needed |
835
| But it also must me noted, that this function defines |
836
| the strategy for insertion of new nodes |
838
| It's MUCH MUCH better when the ugliest element is found |
839
| as one with highest ratio of R/r !!! (before it was |
840
| element with greater R) |
841
+----------------------------------------------------------*/
843
int e, ei, ej, ek,si,sj,sk;
844
double ratio = 0.7, F;
848
for (e = 0; e < Ne; e++) {
849
if (elem[e].mark != OFF) {
854
F = (node[elem[e].i].F + node[elem[e].j].F + node[elem[e].k].F) / 3.0;
858
/*--------------------------+
859
| 0.577 is ideal triangle |
860
+--------------------------*/
861
if (elem[e].R < 0.700*F) {
862
elem[e].state = D; /* 0.0866; 0.07 */
865
/*------------------------+
866
| even this is possible |
867
+------------------------*/
868
if (ei != OFF && ej != OFF && ek != OFF) {
869
if (elem[ei].state == D && elem[ej].state == D && elem[ek].state == D) {
877
/*--------------------------------------+
878
| Diamond check. Is it so important ? |
879
+--------------------------------------*/
882
/*------------------------------------------------+
883
| First part of the trick: |
884
| search through the elements on the boundary |
885
+------------------------------------------------*/
886
for (e = 0; e < Ne; e++) {
887
if (elem[e].mark != OFF && elem[e].state != D) {
892
if (side[si].mark != 0) {
895
if (side[sj].mark != 0) {
898
if (side[sk].mark != 0) {
902
if (elem[e].state == A && elem[e].R / elem[e].r > ratio) {
903
ratio = max(ratio, elem[e].R/elem[e].r);
910
/*-------------------------------------------------+
911
| Second part of the trick: |
912
| if non-acceptable element on the boundary is |
913
| found, ignore the elements inside the domain |
914
+-------------------------------------------------*/
916
for (e = 0; e < Ne; e++) {
917
if (elem[e].mark != OFF) {
918
if (elem[e].state != D) {
924
if (elem[ei].state == D) {
929
if (elem[ej].state == D) {
934
if (elem[ek].state == D) {
938
if (elem[e].state == A && elem[e].R/elem[e].r > ratio) {
939
ratio = max(ratio, elem[e].R / elem[e].r);
947
/*-classify----------------------------------------------------------------*/
950
/*=========================================================================*/
951
/*---------------------------------------------------+
952
| This function is very important. |
953
| It determines the position of the inserted node. |
954
+---------------------------------------------------*/
958
double xM, yM, zM, p, q, qx, qy, rhoM, rho_M, d;
962
/*-------------------------------------------------------------------------+
963
| It's obvious that elements which are near the boundary, will come into |
966
| However, some attention has to be payed for the case when two accepted |
967
| elements surround the ugly one |
969
| What if new points falls outside the domain |
970
+-------------------------------------------------------------------------*/
971
if ((elem[ugly].ei != OFF) && (elem[elem[ugly].ei].state == D)) {
975
if ((elem[ugly].ej != OFF) && (elem[elem[ugly].ej].state == D)) {
979
if ((elem[ugly].ek != OFF) && (elem[elem[ugly].ek].state == D)) {
983
if ((elem[ugly].si != OFF) && (side[elem[ugly].si].mark > 0)) {
987
if ((elem[ugly].sj != OFF) && (side[elem[ugly].sj].mark > 0)) {
991
if ((elem[ugly].sk != OFF) && (side[elem[ugly].sk].mark > 0)) {
1000
xM = 0.5 * (node[side[s].c].x + node[side[s].d].x);
1001
yM = 0.5 * (node[side[s].c].y + node[side[s].d].y);
1002
zM = 0.5 * (node[side[s].c].z + node[side[s].d].z);
1004
Ca.x = elem[ugly].xv;
1005
Ca.y = elem[ugly].yv;
1007
p = 0.5 * side[s].s; /* not checked */
1011
q = sqrt(qx * qx + qy * qy);
1013
rhoM = 0.577 * 0.5 *(node[side[s].c].F + node[side[s].d].F);
1015
rho_M = min(max(rhoM, p), 0.5 * (p * p + q * q) / q);
1020
d = rho_M + sqrt(rho_M * rho_M - p * p);
1023
/*---------------------------------------------------------------------+
1024
| The following line check can the new point fall outside the domain. |
1025
| However, I can't remember how it works, but I believe that it is |
1026
| still a weak point of the code, particulary when there are lines |
1027
| inside the domain |
1028
+---------------------------------------------------------------------*/
1030
if (area(&node[side[s].c], &node[side[s].d], &Ca) *
1031
area(&node[side[s].c], &node[side[s].d], &node[n]) > 0.0 ) {
1032
insert_node(xM + d * qx / q, yM + d * qy / q, zM, ON, OFF, 0, 0, 0, OFF);
1036
/*-new_node----------------------------------------------------------------*/
1039
/*=========================================================================*/
1041
/*--------------------------------------------------------------+
1042
| Counting the elements which surround each node. |
1043
| It is important for the two functions: 'relax' and 'smooth' |
1044
+--------------------------------------------------------------*/
1048
for (s = 0; s < Ns; s++) {
1049
if (side[s].mark == 0) {
1050
if (node[side[s].c].mark == 0) {
1051
node[side[s].c].Nne++;
1054
if (node[side[s].d].mark == 0) {
1055
node[side[s].d].Nne++;
1060
/*-neighbours--------------------------------------------------------------*/
1063
/*=========================================================================*/
1066
int e, c, mater = 0, over;
1067
int ei, ej, ek, si, sj, sk;
1069
for (e = 0; e < Ne; e++) {
1070
if (elem[e].mark != OFF) {
1071
elem[e].material = OFF;
1076
for (c = 0; c < Nc; c++) {
1077
if (point[c].inserted == 0) {
1078
elem[in_elem(&point[c])].material = point[c].mark;
1086
for (e = 0; e < Ne; e++) {
1087
if (elem[e].mark != OFF && elem[e].material == OFF) {
1097
if (elem[ei].material != OFF && side[si].mark == 0) {
1098
elem[e].material = elem[ei].material;
1105
if (elem[ej].material != OFF && side[sj].mark == 0) {
1106
elem[e].material = elem[ej].material;
1113
if (elem[ek].material != OFF && side[sk].mark == 0) {
1114
elem[e].material = elem[ek].material;
1126
/*-materials---------------------------------------------------------------*/
1129
/*=========================================================================*/
1134
for (T = 6; T >= 3; T--) {
1135
for (s = 0; s < Ns; s++) {
1136
if (side[s].mark == 0) {
1137
if ((node[side[s].a].mark == 0) &&
1138
(node[side[s].b].mark == 0) &&
1139
(node[side[s].c].mark == 0) &&
1140
(node[side[s].d].mark == 0)) {
1141
E = node[side[s].c].Nne + node[side[s].d].Nne
1142
- node[side[s].a].Nne - node[side[s].b].Nne;
1145
node[side[s].a].Nne++;
1146
node[side[s].b].Nne++;
1147
node[side[s].c].Nne--;
1148
node[side[s].d].Nne--;
1156
/*-relax-------------------------------------------------------------------*/
1159
/*=========================================================================*/
1164
for (it = 0; it < 10; it++) {
1165
for (s = 0; s < Ns; s++) {
1166
if (side[s].mark == 0) {
1167
if (node[side[s].c].mark == 0) {
1168
node[side[s].c].sumx += node[side[s].d].x;
1169
node[side[s].c].sumy += node[side[s].d].y;
1171
if (node[side[s].d].mark == 0) {
1172
node[side[s].d].sumx += node[side[s].c].x;
1173
node[side[s].d].sumy += node[side[s].c].y;
1177
for (n = 0; n < Nn; n++) {
1178
if(node[n].mark == 0) {
1179
node[n].x = node[n].sumx/node[n].Nne;
1180
node[n].y = node[n].sumy/node[n].Nne;
1187
for (e = 0; e < Ne; e++) {
1188
if (elem[e].mark != OFF) {
1195
/*-smooth------------------------------------------------------------------*/
1198
/*=========================================================================*/
1201
int n, s, e, c, d, i, j, k;
1202
int new_elem=0, new_node=0, new_side=0, next_e, next_s, lowest;
1204
for (n = 0; n < Nn; n++) {
1205
node[n].new_numb = OFF;
1207
for (e = 0; e < Ne; e++) {
1208
elem[e].new_numb = OFF;
1210
for (s = 0; s < Ns; s++) {
1211
side[s].new_numb = OFF;
1214
/*-------------------------------+
1215
| Searching the first element. |
1216
| It is the first which is ON |
1217
+-------------------------------*/
1218
for (e = 0; e < Ne; e++) {
1219
if (elem[e].mark != OFF) {
1224
/*----------------------------------------------------------+
1225
| Assigning numbers 0 and 1 to the nodes of first element |
1226
+----------------------------------------------------------*/
1227
node[elem[e].i].new_numb = new_node;
1229
node[elem[e].j].new_numb = new_node;
1232
/*%%%%%%%%%%%%%%%%%%%%%%%%%
1234
% Renumeration of nodes %
1236
%%%%%%%%%%%%%%%%%%%%%%%%%*/
1237
printf("\nRenum Nodes, ");
1243
for (e = 0; e < Ne; e++) {
1244
if (elem[e].mark != OFF && elem[e].new_numb == OFF) {
1245
i = node[elem[e].i].new_numb;
1246
j = node[elem[e].j].new_numb;
1247
k = node[elem[e].k].new_numb;
1249
if (i + j + k + 2 == abs(i) + abs(j) + abs(k)) {
1250
if ((i == OFF) && (j + k) < lowest) {
1254
if ((j == OFF) && (i + k) < lowest) {
1258
if ((k == OFF) && (i + j) < lowest) {
1267
if (next_e != OFF) {
1268
i = node[elem[next_e].i].new_numb;
1269
j = node[elem[next_e].j].new_numb;
1270
k = node[elem[next_e].k].new_numb;
1272
/*----------------------------------+
1273
| Assign a new number to the node |
1274
+----------------------------------*/
1276
node[elem[next_e].i].new_numb = new_node;
1280
node[elem[next_e].j].new_numb = new_node;
1284
node[elem[next_e].k].new_numb = new_node;
1288
} while (next_e != OFF);
1290
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1292
% Renumeration of triangles %
1294
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1295
printf("Triangles, ");
1298
lowest = Nn + Nn + Nn;
1301
for (e = 0; e < Ne; e++) {
1302
if (elem[e].mark != OFF && elem[e].new_numb == OFF) {
1303
i = node[elem[e].i].new_numb;
1304
j = node[elem[e].j].new_numb;
1305
k = node[elem[e].k].new_numb;
1307
if ((i + j + k) < lowest) {
1314
if (next_e != OFF) {
1315
elem[next_e].new_numb = new_elem;
1318
} while (next_e != OFF);
1322
/*%%%%%%%%%%%%%%%%%%%%%%%%%
1324
% Renumeration of sides %
1326
%%%%%%%%%%%%%%%%%%%%%%%%%*/
1333
for (s = 0; s < Ns; s++) {
1334
if (side[s].mark != OFF && side[s].new_numb == OFF) {
1335
c = node[side[s].c].new_numb;
1336
d = node[side[s].d].new_numb;
1338
if ((c + d) < lowest) {
1345
if (next_s != OFF) {
1346
side[next_s].new_numb = new_side;
1349
} while (next_s != OFF);
1352
/*-renum-------------------------------------------------------------------*/
1356
/*=========================================================================*/
1359
int c, n, s, M = 0, chains;
1362
double xO, yO, zO, xN, yN, zN, L, Lx, Ly, Lz, dLm, ddL = 0, L_tot;
1365
memset(elem, 0, sizeof(elem));
1366
memset(side, 0, sizeof(side));
1367
memset(node, 0, sizeof(node));
1374
printf("Segments = %d\n", Fl);
1376
inserted = (int *)calloc(Nc, sizeof(int));
1377
chain = (struct chai *)calloc(Fl + 1, sizeof(struct chai)); /* approximation */
1379
for (n = 0; n < Nc; n++) {
1380
xmax = max(xmax, point[n].x);
1381
ymax = max(ymax, point[n].y);
1382
xmin = min(xmin, point[n].x);
1383
ymin = min(ymin, point[n].y);
1386
printf("xmin = %f ymin = %f\n", xmin, ymin);
1387
printf("xmax = %f ymax = %f\n", xmax, ymax);
1390
/*----------------------+
1392
+----------------------*/
1394
chain[chains].s0 = 0;
1395
for (s = 0; s < Fl; s++) {
1396
point[segment[s].n0].inserted++;
1397
point[segment[s].n1].inserted++;
1399
segment[s].chain = chains;
1401
if (segment[s].n1 != segment[s+1].n0) {
1402
chain[chains].s1 = s;
1404
chain[chains].s0 = s+1;
1408
printf("Chains = %d\n", chains);
1410
/*-------------------------------------+
1411
counting the nodes on each segment
1412
+-------------------------------------*/
1413
for (s = 0; s < Fl; s++) {
1414
xO = point[segment[s].n0].x;
1415
yO = point[segment[s].n0].y;
1416
xN = point[segment[s].n1].x;
1417
yN = point[segment[s].n1].y;
1421
L = sqrt(Lx * Lx + Ly * Ly);
1423
if ((point[segment[s].n0].F + point[segment[s].n1].F > L ) &&
1424
(segment[s].n0 != segment[s].n1)) {
1425
point[segment[s].n0].F = min(point[segment[s].n0].F,L);
1426
point[segment[s].n1].F = min(point[segment[s].n1].F,L);
1430
/*-------------------------------------+
1431
counting the nodes on each segment
1432
+-------------------------------------*/
1433
for (s = 0; s < Fl; s++) {
1434
xO = point[segment[s].n0].x;
1435
yO = point[segment[s].n0].y;
1436
xN = point[segment[s].n1].x;
1437
yN = point[segment[s].n1].y;
1441
L = sqrt(Lx * Lx + Ly * Ly);
1443
if (point[segment[s].n1].F + point[segment[s].n0].F <= L) {
1444
dLm = 0.5 * (point[segment[s].n0].F + point[segment[s].n1].F);
1445
segment[s].N = (int)ceil(L / dLm);
1452
for (n = 0; n < chains; n++) {
1453
if (segment[chain[n].s0].n0 == segment[chain[n].s1].n1) {
1454
chain[n].type = CLOSED;
1457
if (segment[chain[n].s0].n0 != segment[chain[n].s1].n1) {
1458
chain[n].type = OPEN;
1461
if ((point[segment[chain[n].s0].n0].inserted == 1) &&
1462
(point[segment[chain[n].s1].n1].inserted == 1)) {
1463
chain[n].type = INSIDE;
1472
xt = 0.5 * (xmax + xmin);
1473
yt = 0.5 * (ymax + ymin);
1475
gab = max((xmax - xmin), (ymax - ymin));
1479
node[2].y = yt + 2.8 * gab;
1480
node[2].z = point[0].z;
1482
node[0].x = xt - 2.0 * gab;
1483
node[0].y = yt - 1.4 * gab;
1484
node[0].z = point[0].z;
1486
node[1].x = xt + 2.0 * gab;
1487
node[1].y = yt - 1.4 * gab;
1488
node[1].z = point[0].z;
1490
node[2].inserted = 2;
1491
node[1].inserted = 2;
1492
node[0].inserted = 2;
1535
for (n = 0; n < Nc; n++) {
1536
point[n].new_numb = OFF;
1540
for (c = 0; c < chains; c++) {
1541
for (s = chain[c].s0; s <= chain[c].s1; s++) {
1542
xO = point[segment[s].n0].x;
1543
yO = point[segment[s].n0].y;
1544
zO = point[segment[s].n0].z;
1545
xN = point[segment[s].n1].x;
1546
yN = point[segment[s].n1].y;
1547
zN = point[segment[s].n1].z;
1552
if (point[segment[s].n0].new_numb == OFF ) {
1553
if (s == chain[c].s0) { /* first segment in the chain */
1554
insert_node(xO, yO, zO, OFF,
1555
OFF, OFF, point[segment[s].n0].mark, OFF, OFF);
1557
if (s == chain[c].s1 && segment[s].N == 1) {
1558
insert_node(xO, yO, zO, OFF,
1559
Nn-1, segment[s-1].mark,
1560
point[segment[s].n0].mark,
1561
segment[s].mark, point[segment[chain[c].s0].n0].new_numb);
1563
insert_node(xO, yO, zO, OFF,
1564
Nn-1, segment[s-1].mark, point[segment[s].n0].mark, OFF, OFF);
1568
node[Nn-1].next = Nn; /* Nn-1 is index of inserted node */
1569
node[Nn-1].chain = segment[s].chain;
1570
node[Nn-1].F = point[segment[s].n0].F;
1571
point[segment[s].n0].new_numb = Nn-1;
1577
L = sqrt(Lx * Lx + Ly * Ly);
1580
if (point[segment[s].n0].F + point[segment[s].n1].F <= L) {
1581
if (point[segment[s].n0].F > point[segment[s].n1].F) {
1582
M = -segment[s].N / 2;
1583
ddL = (point[segment[s].n1].F-dLm) / M;
1585
M = +segment[s].N / 2;
1586
ddL = (dLm - point[segment[s].n0].F) / M;
1594
if (point[segment[s].n0].F + point[segment[s].n1].F <= L) {
1595
for (m = 1; m < abs(segment[s].N); m++) {
1596
L_tot += (dLm - M * ddL);
1598
if (point[segment[s].n0].F > point[segment[s].n1].F) {
1600
if (M == 0 && segment[s].N % 2 == 0) {
1605
if (M == 0 && segment[s].N % 2 == 0) {
1610
if (s == chain[c].s1 && m == (abs(segment[s].N) - 1)) {
1611
insert_node(xO + Lx / L * L_tot, yO + Ly / L * L_tot, zO + Lz / L * L_tot, OFF,
1612
Nn - 1, segment[s].mark, segment[s].mark, segment[s].mark, point[segment[s].n1].new_numb);
1613
node[Nn - 1].next = Nn;
1616
insert_node(xO + Lx / L * L_tot, yO + Ly / L * L_tot, zO + Lz / L * L_tot, OFF,
1617
point[segment[s].n0].new_numb, segment[s].mark, segment[s].mark, OFF, OFF);
1618
node[Nn - 1].next = Nn;
1620
insert_node(xO + Lx / L * L_tot, yO + Ly / L * L_tot, zO + Lz / L * L_tot, OFF,
1621
Nn - 1, segment[s].mark, segment[s].mark, OFF, OFF);
1622
node[Nn - 1].next = Nn;
1627
node[Nn - 1].chain = segment[s].chain;
1628
node[Nn - 1].F = 0.5 * (node[Nn - 2].F + (dLm-M * ddL));
1633
* last point * -> just for the inside chains
1635
if ((point[segment[s].n1].new_numb == OFF) && (s==chain[c].s1)) {
1636
insert_node(xN, yN, zN, OFF,
1637
Nn - 1, segment[s].mark, point[segment[s].n1].mark, OFF, OFF);
1638
node[Nn - 1].next = OFF;
1639
node[Nn - 1].chain = segment[s].chain;
1640
node[Nn - 1].F = point[segment[s].n1].F;
1643
if (chain[c].type == CLOSED && s == chain[c].s1) {
1644
node[Nn - 1].next = point[segment[chain[c].s0].n0].new_numb;
1647
if (chain[c].type == OPEN && s == chain[c].s1) {
1648
node[Nn-1].next = OFF;
1659
/*-load--------------------------------------------------------------------*/
1662
insert_node_in_group(struct nod *nod, struct group *group)
1666
/* find if node is already present in this group */
1667
for (i = 0; i < group->nbvtx; i++) {
1668
if ((group->vertices[i].x == nod->x) &&
1669
(group->vertices[i].y == nod->y) &&
1670
(group->vertices[i].z == nod->z)) {
1674
/* insert new node */
1675
if (group->nbvtx == group->maxvtx) {
1676
group->maxvtx += VTX_INCR;
1677
group->vertices = (struct vtx *)realloc(group->vertices, group->maxvtx * sizeof (struct vtx));
1679
group->vertices[group->nbvtx].x = nod->x;
1680
group->vertices[group->nbvtx].y = nod->y;
1681
group->vertices[group->nbvtx].z = nod->z;
1683
return (group->nbvtx - 1);
1687
insert_elem_in_group(struct ele *elem, struct nod *nods)
1690
double xmean, ymean;
1691
struct group *curGrp;
1692
struct surf *curSurf;
1694
xmean = (nods[elem->i].x + nods[elem->j].x + nods[elem->k].x) / 3.0;
1695
ymean = (nods[elem->i].y + nods[elem->j].y + nods[elem->k].y) / 3.0;
1697
grIdx = (int)((xmean - XGroupOffset) / GroupSize) +
1698
XGroupNb * (int)((ymean - YGroupOffset) / GroupSize);
1700
curGrp = &(Groups[grIdx]);
1702
/* insert the surface */
1703
if (curGrp->nbsurf == curGrp->maxsurf) {
1704
if (curGrp->nbsurf == 0) {
1707
curGrp->maxsurf += SURF_INCR;
1708
curGrp->surfaces = (struct surf *)realloc(curGrp->surfaces, curGrp->maxsurf * sizeof (struct surf));
1710
curSurf = &(curGrp->surfaces[curGrp->nbsurf++]);
1712
curSurf->ref[0].u = nods[elem->i].x / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
1713
curSurf->ref[0].v = nods[elem->i].y / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
1714
curSurf->ref[1].u = nods[elem->j].x / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
1715
curSurf->ref[1].v = nods[elem->j].y / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
1716
curSurf->ref[2].u = nods[elem->k].x / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
1717
curSurf->ref[2].v = nods[elem->k].y / TexSize; // + (TexRand * rand()/(RAND_MAX+1.0));
1719
curSurf->ref[0].vtxidx = insert_node_in_group(&(nods[elem->i]), curGrp);
1720
curSurf->ref[1].vtxidx = insert_node_in_group(&(nods[elem->j]), curGrp);
1721
curSurf->ref[2].vtxidx = insert_node_in_group(&(nods[elem->k]), curGrp);
1727
int e, s, n, r_Nn=0, r_Ns=0, r_Ne=0;
1733
r_node = (struct nod *)calloc(Nn, sizeof(struct nod));
1734
r_elem = (struct ele *)calloc(Ne, sizeof(struct ele));
1735
r_side = (struct sid *)calloc(Ns, sizeof(struct sid));
1736
if (r_side == NULL) {
1737
fprintf(stderr, "Sorry, cannot allocate enough memory !\n");
1741
for (n = 0; n < Nn; n++) {
1742
if (node[n].mark != OFF && node[n].new_numb != OFF) {
1744
r_node[node[n].new_numb].x = node[n].x;
1745
r_node[node[n].new_numb].y = node[n].y;
1746
if ((node[n].mark == 0) || (node[n].mark == 100000)) {
1747
r_node[node[n].new_numb].z = GetElevation(node[n].x, node[n].y, node[n].z);
1749
r_node[node[n].new_numb].z = node[n].z;
1751
r_node[node[n].new_numb].mark = node[n].mark;
1756
for (e = 0; e < Ne; e++) {
1757
if (elem[e].mark != OFF && elem[e].new_numb != OFF) {
1759
r_elem[elem[e].new_numb].i = node[elem[e].i].new_numb;
1760
r_elem[elem[e].new_numb].j = node[elem[e].j].new_numb;
1761
r_elem[elem[e].new_numb].k = node[elem[e].k].new_numb;
1762
r_elem[elem[e].new_numb].si = side[elem[e].si].new_numb;
1763
r_elem[elem[e].new_numb].sj = side[elem[e].sj].new_numb;
1764
r_elem[elem[e].new_numb].sk = side[elem[e].sk].new_numb;
1765
r_elem[elem[e].new_numb].xv = elem[e].xv;
1766
r_elem[elem[e].new_numb].yv = elem[e].yv;
1767
r_elem[elem[e].new_numb].material = elem[e].material;
1769
if (elem[e].ei != -1)
1770
r_elem[elem[e].new_numb].ei = elem[elem[e].ei].new_numb;
1772
r_elem[elem[e].new_numb].ei = -1;
1774
if (elem[e].ej != -1)
1775
r_elem[elem[e].new_numb].ej = elem[elem[e].ej].new_numb;
1777
r_elem[elem[e].new_numb].ej = -1;
1779
if (elem[e].ek != -1)
1780
r_elem[elem[e].new_numb].ek = elem[elem[e].ek].new_numb;
1782
r_elem[elem[e].new_numb].ek = -1;
1787
for (s = 0; s < Ns; s++) {
1788
if (side[s].mark != OFF && side[s].new_numb != OFF) {
1790
r_side[side[s].new_numb].c = node[side[s].c].new_numb;
1791
r_side[side[s].new_numb].d = node[side[s].d].new_numb;
1792
r_side[side[s].new_numb].mark = side[s].mark;
1794
if (side[s].a != OFF) {
1795
r_side[side[s].new_numb].a = node[side[s].a].new_numb;
1796
r_side[side[s].new_numb].ea = elem[side[s].ea].new_numb;
1798
r_side[side[s].new_numb].a = OFF;
1799
r_side[side[s].new_numb].ea = OFF;
1802
if (side[s].b != OFF) {
1803
r_side[side[s].new_numb].b = node[side[s].b].new_numb;
1804
r_side[side[s].new_numb].eb = elem[side[s].eb].new_numb;
1806
r_side[side[s].new_numb].b = OFF;
1807
r_side[side[s].new_numb].eb = OFF;
1812
for (e = 0; e < r_Ne; e++) {
1813
insert_elem_in_group(&(r_elem[e]), r_node);
1816
/*-groups--------------------------------------------------------------------*/
1820
draw_ac(FILE *ac_file, const char *name)
1823
struct group *curGrp;
1825
Ac3dGroup(ac_file, name, ActiveGroups);
1827
for (i = 0; i < GroupNb; i++) {
1828
curGrp = &(Groups[i]);
1829
if (curGrp->nbsurf == 0) {
1833
fprintf(ac_file, "OBJECT poly\n");
1834
fprintf(ac_file, "name \"%s%d\"\n", name, i);
1835
fprintf(ac_file, "texture \"%s\"\n", TexName);
1836
fprintf(ac_file, "numvert %d\n", curGrp->nbvtx);
1837
for (j = 0; j < curGrp->nbvtx; j++) {
1838
fprintf(ac_file, "%g %g %g\n", curGrp->vertices[j].x, curGrp->vertices[j].z, -curGrp->vertices[j].y);
1840
fprintf(ac_file, "numsurf %d\n", curGrp->nbsurf);
1841
for (j = 0; j < curGrp->nbsurf; j++) {
1842
fprintf(ac_file, "SURF 0x30\n");
1843
fprintf(ac_file, "mat 0\n");
1844
fprintf(ac_file, "refs 3\n");
1845
for (k = 0; k < 3; k++) {
1846
fprintf(ac_file, "%d %f %f\n", curGrp->surfaces[j].ref[k].vtxidx, curGrp->surfaces[j].ref[k].u, curGrp->surfaces[j].ref[k].v);
1849
fprintf(ac_file, "kids 0\n");
1853
/*-draw_ac--------------------------------------------------------------------*/
1863
printf("Load Chains\n");
1872
if (Nn > (MAX_NODES / 2 - 2)) {
1878
} while (ugly != OFF);
1891
GetTrackOrientation(tTrack *track)
1897
for (i = 0, seg = track->seg->next; i < track->nseg; i++, seg = seg->next) {
1898
switch (seg->type) {
1910
return ANTICLOCKWISE;
1916
#define ADD_POINT(_x,_y,_z,_F,_mark) \
1918
point[nbvert].x = _x; \
1919
point[nbvert].y = _y; \
1920
point[nbvert].z = _z; \
1921
point[nbvert].F = _F; \
1922
point[nbvert].mark = _mark; \
1924
if (nbvert == maxVert) { \
1926
point = (struct nod*)realloc(point, maxVert); \
1927
memset(&point[nbvert], 0, maxVert / 2); \
1931
/** Generate the terrain mesh.
1932
@param rightside 1 if use the right side
1933
0 if use the left side
1934
@param reverse 1 if reverse the points order
1935
0 if keep the track order
1936
@param exterior 1 if it is the exterior
1937
0 if it is the interior
1942
GenerateMesh(tTrack *Track, int rightside, int reverse, int exterior)
1945
int i, j, nbvert, maxVert;
1946
tdble ts, step, anz;
1951
tdble radiusr, radiusl;
1953
int nb_relief_vtx, nb_relief_seg;
1955
printf("GenerateMesh: ");
1962
printf("reverse order, ");
1964
printf("normal order, ");
1967
printf("exterior\n");
1969
printf("interior\n");
1972
CountRelief(1 - exterior, &nb_relief_vtx, &nb_relief_seg);
1974
printf("Relief: %d vtx, %d seg\n", nb_relief_vtx, nb_relief_seg);
1976
/* Estimation of the number of points */
1977
maxVert = ((int)(Track->length) + nb_relief_vtx) * sizeof(struct nod);
1978
point = (struct nod*)calloc(1, maxVert);
1983
if (exterior && !reverse && UseBorder) {
1984
ADD_POINT(-Margin, -Margin, ExtHeight, GridStep, 100000);
1985
ADD_POINT(Track->max.x + Margin, -Margin, ExtHeight, GridStep, 100000);
1986
ADD_POINT(Track->max.x + Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
1987
ADD_POINT(-Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
1992
for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next) {
1993
if (mseg->rside != NULL) {
1995
if (seg->rside != NULL) {
2002
ADD_POINT(seg->vertex[TR_SR].x, seg->vertex[TR_SR].y, seg->vertex[TR_SR].z, GridStep, i+1);
2004
switch (seg->type) {
2008
while (ts < seg->length) {
2009
trkpos.toStart = ts;
2011
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
2012
ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
2017
step = TrackStep / (mseg->radiusr);
2018
anz = seg->angle[TR_ZS] + step;
2020
radiusr = seg->radiusr;
2023
while (anz < seg->angle[TR_ZE]) {
2024
trkpos.toStart = ts;
2026
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
2027
ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
2033
step = TrackStep / (mseg->radiusl);
2034
anz = seg->angle[TR_ZS] - step;
2036
radiusr = seg->radiusr;
2039
while (anz > seg->angle[TR_ZE]) {
2040
trkpos.toStart = ts;
2042
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
2043
ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
2049
if (i != (Track->nseg - 1)) {
2050
ADD_POINT(seg->vertex[TR_ER].x, seg->vertex[TR_ER].y, seg->vertex[TR_ER].z, GridStep, i+1);
2055
if (exterior && reverse && UseBorder) {
2056
ADD_POINT(-Margin,Track->max.y + Margin, ExtHeight, GridStep, 100000);
2057
ADD_POINT(Track->max.x + Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
2058
ADD_POINT(Track->max.x + Margin, -Margin, ExtHeight, GridStep, 100000);
2059
ADD_POINT(-Margin, -Margin, ExtHeight, GridStep, 100000);
2065
if (exterior && !reverse && UseBorder) {
2066
ADD_POINT(-Margin, -Margin, ExtHeight, GridStep, 100000);
2067
ADD_POINT(Track->max.x + Margin, -Margin, ExtHeight, GridStep, 100000);
2068
ADD_POINT(Track->max.x + Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
2069
ADD_POINT(-Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
2074
for (i = 0, mseg = Track->seg->next; i < Track->nseg; i++, mseg = mseg->next) {
2084
ADD_POINT(seg->vertex[TR_SL].x, seg->vertex[TR_SL].y, seg->vertex[TR_SL].z, GridStep, i+1);
2087
switch (seg->type) {
2091
while (ts < seg->length) {
2092
trkpos.toStart = ts;
2093
trkpos.toRight = RtTrackGetWidth(seg, ts);
2094
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
2095
ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
2100
step = TrackStep / (mseg->radiusr);
2101
anz = seg->angle[TR_ZS] + step;
2103
radiusl = seg->radiusl;
2105
while (anz < seg->angle[TR_ZE]) {
2106
trkpos.toStart = ts;
2107
trkpos.toRight = RtTrackGetWidth(seg, ts);
2108
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
2110
ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
2116
step = TrackStep / (mseg->radiusl);
2117
anz = seg->angle[TR_ZS] - step;
2119
radiusl = seg->radiusl;
2121
while (anz > seg->angle[TR_ZE]) {
2122
trkpos.toStart = ts;
2123
trkpos.toRight = RtTrackGetWidth(seg, ts);
2124
RtTrackLocal2Global(&trkpos, &x, &y, TR_TORIGHT);
2126
ADD_POINT(x, y, RtTrackHeightL(&trkpos), GridStep, i+1);
2132
if (i != (Track->nseg - 1)) {
2133
ADD_POINT(seg->vertex[TR_EL].x, seg->vertex[TR_EL].y, seg->vertex[TR_EL].z, GridStep, i+1);
2138
if (exterior && reverse && UseBorder) {
2139
ADD_POINT(-Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
2140
ADD_POINT(Track->max.x + Margin, Track->max.y + Margin, ExtHeight, GridStep, 100000);
2141
ADD_POINT(Track->max.x + Margin, -Margin, ExtHeight, GridStep, 100000);
2142
ADD_POINT(-Margin, -Margin, ExtHeight, GridStep, 100000);
2147
segment = (struct seg *)calloc(Nc + 1 + nb_relief_seg, sizeof(struct seg));
2148
segment[Nc].n0 = -1;
2149
segment[Nc].n1 = -1;
2153
point2 = (struct nod*)calloc(Nc + 1 + nb_relief_vtx, sizeof(struct nod));
2154
for (i = 0; i < Nc; i++) {
2155
memcpy(&(point2[i]), &(point[Nc-i-1]), sizeof(struct nod));
2162
if (exterior && !UseBorder) {
2165
if (exterior && UseBorder) {
2168
segment[0].mark = 100000;
2171
segment[1].mark = 100000;
2174
segment[2].mark = 100000;
2177
segment[3].mark = 100000;
2182
segment[j+4].n0 = i+4;
2183
i = (i + 1) % (Nc - 4);
2184
segment[j+4].n1 = i+4;
2185
segment[j+4].mark = 2;
2194
i = (i + 1) % nbvert;
2196
segment[j].mark = 1;
2210
segment[Fl].n0 = -1;
2211
segment[Fl].n1 = -1;
2217
GenerateTerrain(tTrack *track, void *TrackHandle, char *outfile, FILE *AllFd, int noElevation)
2219
const char *FileName;
2223
TrackStep = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_TSTEP, NULL, 10.0);
2224
GfOut("Track step: %.2f\n", TrackStep);
2225
Margin = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_BMARGIN, NULL, 100.0);
2226
GridStep = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_BSTEP, NULL, 10.0);
2227
ExtHeight = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_BHEIGHT, NULL, 0.0);
2228
GfOut("Border margin: %.2f step: %.2f height: %.2f\n", Margin, GridStep, ExtHeight);
2230
GroupSize = GfParmGetNum(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_GRPSZ, NULL, 100.0);
2231
XGroupOffset = track->min.x - Margin;
2232
YGroupOffset = track->min.y - Margin;
2234
XGroupNb = (int)((track->max.x + Margin - (track->min.x - Margin)) / GroupSize) + 1;
2236
GroupNb = XGroupNb * ((int)((track->max.y + Margin - (track->min.y - Margin)) / GroupSize) + 1);
2238
Groups = (struct group *)calloc(GroupNb, sizeof (struct group));
2243
mat = GfParmGetStr(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_SURF, "grass");
2244
if (track->version < 4) {
2245
sprintf(buf, "%s/%s/%s", TRK_SECT_SURFACES, TRK_LST_SURF, mat);
2247
sprintf(buf, "%s/%s", TRK_SECT_SURFACES, mat);
2249
TexName = GfParmGetStr(TrackHandle, buf, TRK_ATT_TEXTURE, "grass.rgb");
2250
TexSize = GfParmGetNum(TrackHandle, buf, TRK_ATT_TEXSIZE, (char*)NULL, 20.0);
2251
TexRand = GfParmGetNum(TrackHandle, buf, TRK_ATT_SURFRAND, (char*)NULL, TexSize / 10.0);
2253
FileName = GfParmGetStr(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_RELIEF, NULL);
2255
sprintf(buf, "tracks/%s/%s/%s", track->category, track->internalname, FileName);
2256
LoadRelief(TrackHandle, buf);
2258
if (noElevation == -1) {
2259
FileName = GfParmGetStr(TrackHandle, TRK_SECT_TERRAIN, TRK_ATT_ELEVATION, NULL);
2261
sprintf(buf, "tracks/%s/%s/%s", track->category, track->internalname, FileName);
2262
LoadElevation(track, TrackHandle, buf);
2267
// Attempt to fix AC3D (the application) segfault on opening the msh file.
2268
//curFd = Ac3dOpen(outfile, 2);
2269
curFd = Ac3dOpen(outfile, 1);
2272
if (GetTrackOrientation(track) == CLOCKWISE) {
2274
GenerateMesh(track, 1 /* right */, 1 /* reverse */, 0 /* interior */);
2275
GenerateMesh(track, 0 /* left */, 0 /* normal */, 1 /* exterior */);
2277
draw_ac(curFd, "TERR");
2280
draw_ac(AllFd, "TERR");
2283
GenerateMesh(track, 0 /* left */, 0 /* normal */, 0 /* interior */);
2284
GenerateMesh(track, 1 /* right */, 1 /* reverse */, 1 /* exterior */);
2286
draw_ac(curFd, "TERR");
2289
draw_ac(AllFd, "TERR");