001: #include <stdio.h>
002: #include <string.h>
003: #include <math.h>
004: #include <stdlib.h>
005: #ifdef __BORLANDC__
006: #define MINRECSZ 1
007: #else
008: #define MINRECSZ 0
009: #endif
010: #ifdef _WIN32
011: #include <windows.h>
012: #include <process.h>
013: #endif
014: 
015: #ifdef _PA_RISC1_1
016: #include <unistd.h>
017: #define wchar_t unsigned short
018: #define __int64 long long
019: #define MAX_PATH 256
020: #endif
021: 
022: #define MAX_COORDS 12000
023: #define HASHSIZE 256
024: 
025: #define SLP_STL_ASCII_HEAD "solid "
026: 
027: void Pause(void)
028: { char Zeile[100];
029:   fprintf(stderr, ">>> RETURN bitte >>> RETURN please >>>");
030:   fgets(Zeile, 100, stdin);
031: }
032: 
033: struct HEAD {
034:   unsigned char  c[30];
035:   unsigned short us;
036:   unsigned long  ul;
037:   float          f;
038:   double         d;
039: } head = { "triangulara dosiero (.vtf)\r\n\32", 1, 987654321L,
040:            7654321.0, 9876543210123456.0 };
041: 
042: FILE *aus = NULL, *aus2 = NULL;
043: 
044: void swap2(unsigned short *p)
045: { unsigned char uc;
046:   union tausch2 {
047:     unsigned short h;
048:     unsigned char c[2];
049:   } *u;
050:   uc = ((union tausch2 *)p)->c[0];
051:   ((union tausch2 *)p)->c[0] = ((union tausch2 *)p)->c[1];
052:   ((union tausch2 *)p)->c[1] = uc;
053: }
054: 
055: void swap4(unsigned long *p)
056: { unsigned char uc;
057:   union tausch4 {
058:     unsigned long h;
059:     unsigned char c[4];
060:   } *u;
061:   uc = ((union tausch4 *)p)->c[0];
062:   ((union tausch4 *)p)->c[0] = ((union tausch4 *)p)->c[3];
063:   ((union tausch4 *)p)->c[3] = uc;
064:   uc = ((union tausch4 *)p)->c[1];
065:   ((union tausch4 *)p)->c[1] = ((union tausch4 *)p)->c[2];
066:   ((union tausch4 *)p)->c[2] = uc;
067: }
068: 
069: void swap8(unsigned __int64 *p)
070: { unsigned char uc;
071:   union tausch8 {
072:     unsigned __int64 h;
073:     unsigned char c[8];
074:   } *u;
075:   uc = ((union tausch8 *)p)->c[0];
076:   ((union tausch8 *)p)->c[0] = ((union tausch8 *)p)->c[7];
077:   ((union tausch8 *)p)->c[7] = uc;
078:   uc = ((union tausch8 *)p)->c[1];
079:   ((union tausch8 *)p)->c[1] = ((union tausch8 *)p)->c[6];
080:   ((union tausch8 *)p)->c[6] = uc;
081:   uc = ((union tausch8 *)p)->c[2];
082:   ((union tausch8 *)p)->c[2] = ((union tausch8 *)p)->c[5];
083:   ((union tausch8 *)p)->c[5] = uc;
084:   uc = ((union tausch8 *)p)->c[3];
085:   ((union tausch8 *)p)->c[3] = ((union tausch8 *)p)->c[4];
086:   ((union tausch8 *)p)->c[4] = uc;
087: }
088: 
089: void swap2x4(unsigned __int64 *p)
090: { unsigned char uc;
091:   union tausch8 {
092:     unsigned __int64 h;
093:     unsigned char c[8];
094:   } *u;
095:   uc = ((union tausch8 *)p)->c[0];
096:   ((union tausch8 *)p)->c[0] = ((union tausch8 *)p)->c[3];
097:   ((union tausch8 *)p)->c[3] = uc;
098:   uc = ((union tausch8 *)p)->c[1];
099:   ((union tausch8 *)p)->c[1] = ((union tausch8 *)p)->c[2];
100:   ((union tausch8 *)p)->c[2] = uc;
101:   uc = ((union tausch8 *)p)->c[4];
102:   ((union tausch8 *)p)->c[4] = ((union tausch8 *)p)->c[7];
103:   ((union tausch8 *)p)->c[7] = uc;
104:   uc = ((union tausch8 *)p)->c[5];
105:   ((union tausch8 *)p)->c[5] = ((union tausch8 *)p)->c[6];
106:   ((union tausch8 *)p)->c[6] = uc;
107: }
108: 
109: struct {
110:   float hx, hy, hz;
111:   unsigned long ret_val, count;
112: } Hash[HASHSIZE];
113: int in_hash_cnt = 0, hashpos_to_replace;
114: unsigned long hash_hit = 0, no_hash_hit =0;
115: unsigned long FileSize;
116: 
117: /* Extend of the model */
118: float xmin, xmax,  ymin, ymax,  zmin, zmax;
119: unsigned long total_facet_count;
120: /* options */
121: int indexed = 0, colorindexed = 0, silent = 0, swaped = 0, swap_still_allowed = 1;
122: 
123: struct Coords_accel {
124:   struct Coords_accel *X, *Y, *Z;
125:   int                 this_pos;
126:   float               *values;
127: } *BaseAccel = NULL;
128: 
129: unsigned long stored_coordinates = 0;
130: struct CoordsField {
131:   struct CoordsField *next;
132:   float               coords[MAX_COORDS];
133:   struct Coords_accel accel[MAX_COORDS / 3];
134: } *CArr = NULL, *CArrLast = NULL;
135: 
136: union NomoX {
137:   struct NomoL {
138:     unsigned long size_n_flags;
139:     wchar_t ObjectName[MAX_PATH + 10];
140:   } n;
141:   __int64 Data[1];
142: } nomo;
143: 
144: struct Nomo {
145:   unsigned long size_n_flags;
146:   wchar_t ObjectName[MINRECSZ];
147: }; /* 1/2 * 8 bytes + x */
148: 
149: struct Coloratoro {
150:   unsigned long size_n_flags;
151:   unsigned long index;
152: } coloratoro; /* 1 * 8 bytes */
153: 
154: struct Dauxrigo {
155:   unsigned long size_n_flags;
156:   void * There;
157: } dauxrigo; /* 1 * 8 bytes */
158: 
159: struct Triangulo {
160:   unsigned long size_n_flags;
161:   unsigned long repeated;
162:   double        coordinates[MINRECSZ];
163: }; /* 1 * 8 bytes + n * 8 bytes */
164: 
165: struct TrianguletoL {
166:   unsigned long size_n_flags;
167:   unsigned long repeated;
168:   union { float         coordinates[MAX_COORDS];
169:           unsigned long index[MAX_COORDS];
170:         }       d;
171: } trianguleto;
172: 
173: struct Trianguleto {
174:   unsigned long size_n_flags;
175:   unsigned long repeated;
176:   float         coordinates[MINRECSZ];
177: }; /* 1 * 8 bytes + n / 2 * 8 bytes */
178: 
179: struct Coloro {
180:   unsigned long size_n_flags;
181:   float r, g, b;
182: } coloro; /* 16 bytes = 2 * 8 bytes */
183: 
184: union Unu {
185:   struct Coloro      coloro;
186:   struct Coloratoro  coloratoro;
187:   struct Triangulo   triangulo;
188:   struct Trianguleto trianguleto;
189:   struct Dauxrigo    dauxrigo;
190:   struct Nomo        nomo;
191:   unsigned __int64   Data[1];
192: };
193: 
194: struct Memorilo {
195:   struct Memorilo *next_block;
196:   unsigned long capacity;
197:   unsigned long next_free;
198:   void *        next_free_p;
199:   unsigned __int64 Data[MINRECSZ];
200: } *TDate = NULL, *TDate_Current = NULL;
201: 
202: void free_coordinates(void)
203: { struct CoordsField *arr, *nxt;
204:   for (arr = CArr; arr != NULL; arr = nxt) {
205:     nxt = arr->next;
206:     free(arr);
207:   }
208:   CArr = CArrLast = NULL; BaseAccel = NULL;
209:   in_hash_cnt = 0;
210:   stored_coordinates = 0;
211: }
212: 
213: struct CoordsField *alloc_CoordsField(void)
214: { struct CoordsField *neu;
215:   if ((neu = malloc(sizeof(struct CoordsField))) == NULL) return NULL;
216:   neu->next = NULL;
217:   return neu;
218: }
219: 
220: unsigned long new_index(float wx, float wy, float wz, int e, struct Coords_accel *ca)
221: { unsigned long erg, idx, aidx;
222:   if ((CArr == NULL) || (stored_coordinates == 0)) {
223:     if ((CArr = alloc_CoordsField()) == NULL) return 0xffffffffL;
224:     CArrLast = CArr;
225:   }
226:   idx = stored_coordinates % MAX_COORDS;
227:   aidx = idx / 3;
228:   if ((idx == 0) && stored_coordinates) {
229:     if ((CArrLast->next = alloc_CoordsField()) == NULL) return 0xffffffffL;
230:     CArrLast = CArrLast->next;
231:   }
232:   CArrLast->coords[idx] = wx;
233:   CArrLast->coords[idx + 1] = wy;
234:   CArrLast->coords[idx + 2] = wz;
235:   CArrLast->accel[aidx].X = NULL;
236:   CArrLast->accel[aidx].Y = NULL;
237:   CArrLast->accel[aidx].Z = NULL;
238:   CArrLast->accel[aidx].this_pos = stored_coordinates;
239:   CArrLast->accel[aidx].values = &(CArrLast->coords[idx]);
240:   switch (e) {
241:     case 0: BaseAccel = &(CArrLast->accel[aidx]); break;
242:     case 1: ca->X     = &(CArrLast->accel[aidx]); break;
243:     case 2: ca->Y     = &(CArrLast->accel[aidx]); break;
244:     case 3: ca->Z     = &(CArrLast->accel[aidx]); break;
245:   }
246:   erg = stored_coordinates;
247:   stored_coordinates += 3;
248:   Hash[hashpos_to_replace].hx = wx;
249:   Hash[hashpos_to_replace].hy = wy;
250:   Hash[hashpos_to_replace].hz = wz;
251:   Hash[hashpos_to_replace].ret_val = erg;
252:   Hash[hashpos_to_replace].count = 0;
253:   if (in_hash_cnt <= hashpos_to_replace) in_hash_cnt = hashpos_to_replace + 1;
254:   return erg;
255: }
256: 
257: unsigned long coordinate_index(float wx, float wy, float wz)
258: { struct Coords_accel *p;
259:   unsigned long hmv;
260:   int ct, i;
261:   hmv = 0; hashpos_to_replace = 0;
262:   if ((CArr == NULL) || (stored_coordinates == 0) || (BaseAccel == NULL))
263:     return(new_index(wx, wy, wz, 0, NULL));
264:   /* Try, if it is one of the last used coordinates */
265:   for (ct = 0; ct < in_hash_cnt; ct++) {
266:     if ((Hash[ct].hx == wx) && (Hash[ct].hy == wy) && (Hash[ct].hz == wz)) {
267:       for (i = ct; i < in_hash_cnt; i++) Hash[i].count++;
268:       Hash[ct].count = 0;
269:       hash_hit++;
270:       return(Hash[ct].ret_val);
271:     }
272:     if (Hash[ct].count >= hmv) {
273:       hashpos_to_replace = ct;
274:       hmv = Hash[ct].count;
275:     }
276:     Hash[ct].count++;
277:   }
278:   if (in_hash_cnt < HASHSIZE) hashpos_to_replace = in_hash_cnt;
279:   /* Well, now we have to scan all coordinates im memory */
280:   p = BaseAccel;
281:   while (1) {
282:     if (wx == p->values[0]) {
283:       while (1) {
284:         if (wy == p->values[1]) {
285:           while (1) {
286:             if (wz == p->values[2]) {
287:               Hash[hashpos_to_replace].hx = wx;
288:               Hash[hashpos_to_replace].hy = wy;
289:               Hash[hashpos_to_replace].hz = wz;
290:               Hash[hashpos_to_replace].ret_val = p->this_pos;
291:               Hash[hashpos_to_replace].count = 0;
292:               /* "Um herausgefallen zu sein, muessen schon alle Pos. belegt sein!"
293:                * if (in_hash_cnt <= hashpos_to_replace)
294:                *   in_hash_cnt = hashpos_to_replace + 1;
295:                */
296:               no_hash_hit++;
297:               return p->this_pos;
298:             } else {
299:               if (p->Z == NULL) return(new_index(wx, wy, wz, 3, p));
300:               p = p->Z;
301:             }
302:           }
303:         } else {
304:           if (p->Y == NULL) return(new_index(wx, wy, wz, 2, p));
305:           p = p->Y;
306:         }
307:       }
308:     } else {
309:       if (p->X == NULL) return(new_index(wx, wy, wz, 1, p));
310:       p = p->X;
311:     }
312:   }
313: }
314: 
315: void flush_facets(FILE *aus)
316: { unsigned long QWordsToStore;
317:   unsigned long ct, swaplimit;
318:   if (!trianguleto.repeated) return;
319:   if (indexed) {
320:     QWordsToStore = 1L + 2L * trianguleto.repeated;
321:     swaplimit = 4L * trianguleto.repeated;
322:     trianguleto.size_n_flags = 0x10000000L + QWordsToStore;
323:   } else {
324:     QWordsToStore = 1L + 6L * trianguleto.repeated;
325:     swaplimit = 12L * trianguleto.repeated;
326:     trianguleto.size_n_flags = 0x20000000L + QWordsToStore;
327:   }
328:   if (swaped) {
329:     swap4(&(trianguleto.size_n_flags)); swap4(&(trianguleto.repeated));
330:     for (ct = 0; ct < swaplimit; ct++) swap4(&(trianguleto.d.index[ct]));
331:   }
332:   fwrite(&trianguleto, 8, QWordsToStore, aus);
333:   trianguleto.repeated = 0;
334: }
335: 
336: void store_endsolid(FILE *aus)
337: { unsigned long QWords_to_store;
338:   flush_facets(aus);
339:   QWords_to_store = 1;
340:   dauxrigo.size_n_flags = 0x90000001;
341:   dauxrigo.There = NULL;
342:   if (swaped) {
343:     swap4(&(dauxrigo.size_n_flags));
344:     swap4((unsigned long*)&(dauxrigo.There));
345:   }
346:   fwrite(&dauxrigo, 1, sizeof(struct Dauxrigo), aus);
347: }
348: 
349: void store_beginsolid(FILE *aus2, char *Name)
350: { unsigned long QWords_to_store;
351:   unsigned int Strlg;
352:   if (!silent) fprintf(stderr, "     Solid %s ...\n", Name);
353:   flush_facets(aus);
354:   Strlg = strlen(Name) + 3;
355:   while (Strlg & 3) Strlg++;
356:   QWords_to_store = Strlg / 4;
357:   nomo.Data[QWords_to_store - 1] = 0;
358:   nomo.n.size_n_flags = 0x80000000 + QWords_to_store;
359:   for (Strlg = 0; Name[Strlg]; Strlg++) {
360:     nomo.n.ObjectName[Strlg] = (wchar_t) ((unsigned char) Name[Strlg]);
361:     if (swaped) swap2(&(nomo.n.ObjectName[Strlg]));
362:   }
363:   if (swaped) swap4(&(nomo.n.size_n_flags));
364:   fwrite(&nomo, 8, QWords_to_store, aus2);
365: }
366: 
367: void store_set_color(FILE *aus, float r, float g, float b)
368: { unsigned long QWords_to_store;
369:   flush_facets(aus);
370:   QWords_to_store = 2;
371:   coloro.size_n_flags = 0x40000000L + QWords_to_store;
372:   coloro.r = r;
373:   coloro.g = g;
374:   coloro.b = b;
375:   if (swaped) {
376:     swap4(&(coloro.size_n_flags));
377:     swap4((unsigned long *)&(coloro.r)); swap4((unsigned long *)&(coloro.g)); swap4((unsigned long *)&(coloro.b));
378:   }
379:   fwrite(&coloro, 1, sizeof(struct Coloro), aus);
380: }
381: 
382: 
383: void store_color_indexed(FILE *aus, unsigned long p)
384: { unsigned long Words_pos;
385:   unsigned long QWords_to_store;
386:   flush_facets(aus);
387:   QWords_to_store = 1;
388:   coloratoro.size_n_flags = 1;
389:   coloratoro.index = p;
390:   if (swaped) {
391:     swap4(&(coloratoro.size_n_flags));
392:     swap4(&(coloratoro.index));
393:   }
394:   fwrite(&coloratoro, 1, sizeof(struct Coloratoro), aus);
395: }
396: 
397: 
398: void store_facet_indexed(FILE *aus, unsigned long pn, unsigned long p1, unsigned long p2, unsigned long p3)
399: { unsigned long Words_pos;
400:   if (trianguleto.repeated >= MAX_COORDS / 4) flush_facets(aus);
401:   Words_pos = 4L * trianguleto.repeated;
402:   trianguleto.d.index[Words_pos + 0] = pn;
403:   trianguleto.d.index[Words_pos + 1] = p1;
404:   trianguleto.d.index[Words_pos + 2] = p2;
405:   trianguleto.d.index[Words_pos + 3] = p3;
406:   trianguleto.repeated++;
407:   total_facet_count++;
408: }
409: 
410: 
411: void store_facet_short(FILE* aus, float Nx, float Ny, float Nz, float *vx, float *vy, float *vz)
412: { unsigned long Words_pos;
413:   int ct;
414:   if (trianguleto.repeated >= MAX_COORDS / 12) flush_facets(aus);
415:   Words_pos = 12L * trianguleto.repeated;
416:   if (!total_facet_count) {
417:     xmin = xmax = vx[0]; ymin = ymax = vy[0]; zmin = zmax = vz[0];
418:   }
419:   for (ct = 0; ct < 3; ct++) {
420:     if (vx[ct] < xmin) xmin = vx[ct]; else if (vx[ct] > xmax) xmax = vx[ct];
421:     if (vy[ct] < ymin) ymin = vy[ct]; else if (vy[ct] > ymax) ymax = vy[ct];
422:     if (vz[ct] < zmin) zmin = vz[ct]; else if (vz[ct] > zmax) zmax = vz[ct];
423:   }
424:   trianguleto.d.coordinates[Words_pos + 0] = Nx;
425:   trianguleto.d.coordinates[Words_pos + 1] = Ny;
426:   trianguleto.d.coordinates[Words_pos + 2] = Nz;
427:   trianguleto.d.coordinates[Words_pos +  3] = vx[0];
428:   trianguleto.d.coordinates[Words_pos +  4] = vy[0];
429:   trianguleto.d.coordinates[Words_pos +  5] = vz[0];
430:   trianguleto.d.coordinates[Words_pos +  6] = vx[1];
431:   trianguleto.d.coordinates[Words_pos +  7] = vy[1];
432:   trianguleto.d.coordinates[Words_pos +  8] = vz[1];
433:   trianguleto.d.coordinates[Words_pos +  9] = vx[2];
434:   trianguleto.d.coordinates[Words_pos + 10] = vy[2];
435:   trianguleto.d.coordinates[Words_pos + 11] = vz[2];
436:   trianguleto.repeated++;
437:   total_facet_count++;
438: }
439: 
440: 
441: void FlushFileIndexedSLP(FILE *ein, FILE *aus2)
442: { char Data[8192];
443:   int sz, ct;
444:   unsigned long QWords_to_store;
445:   struct Trianguleto KK;
446:   struct CoordsField *p;
447:   KK.repeated = stored_coordinates / 3;
448:   if (!silent) fprintf(stderr, "%lu Koordinaten = %lu Zahlen = 0x%lx Byte\n",
449:     (unsigned long) KK.repeated,
450:     (unsigned long) stored_coordinates,
451:     (unsigned long) stored_coordinates * sizeof(float));
452:   if (!silent) fprintf(stderr, "%lu : %lu Hashtreffer in Feldgroesse %d\n",
453:     hash_hit, no_hash_hit, HASHSIZE);
454:   QWords_to_store = (stored_coordinates + 1) / 2;
455:   KK.size_n_flags = 0x60000001 + QWords_to_store;
456:   if (swaped) { swap4(&(KK.size_n_flags)); swap4(&(KK.repeated)); }
457:   fwrite(&KK, 1, sizeof(KK), aus2);
458:   p = CArr;
459:   while (QWords_to_store) {
460:     if (p != NULL) {
461:       if (swaped) {
462:         for (ct = 0; ct < MAX_COORDS; ct++) swap4((unsigned long *)&(p->coords[ct]));
463:       }
464:       fwrite(&(p->coords[0]), 8,
465:              (QWords_to_store > MAX_COORDS / 2) ? MAX_COORDS / 2 : QWords_to_store,
466:              aus2);
467:       p = p->next;
468:     }
469:     if (QWords_to_store > MAX_COORDS / 2)
470:       QWords_to_store -= (MAX_COORDS / 2);
471:      else
472:       QWords_to_store = 0;
473:   }
474:   rewind(ein);
475:   while ((sz = fread(Data, 1, 8192, ein)) > 0)
476:     fwrite(Data, 1, sz, aus2);
477:   /* warum nicht gleich loeschen! */
478:   free_coordinates();
479: }
480: 
481: int ReadFileIndexedSLP(FILE *ein, FILE *aus2)
482: { char Zeile[MAX_PATH + 50], Kennwort[MAX_PATH + 50], Kennwort2[MAX_PATH + 50];
483:   unsigned long ZNR, pn, p1, p2, p3;
484:   int sw, stp = -1, STATE = -1, cv, cn, data_in_temp = 0;
485:   float d1, d2, d3, nx[3], ny[3], nz[3], vx[6], vy[6], vz[6], Nx, Ny, Nz, NNx, NNy, NNz; double NL;
486:   FILE *temp; char LTemp[MAX_PATH];
487:   sprintf(LTemp, "_vtf_%u.tmp", getpid());
488:   if ((temp = fopen(LTemp, "w+b"))== NULL) {
489:     fprintf(stderr, "Temporaerdatei '%s' nicht schreibbar!\n", LTemp);
490:     fclose(ein); Pause(); return 0;
491:   }
492:   trianguleto.repeated = 0;
493:   ZNR = 0;
494:   while (fgets(Zeile, MAX_PATH + 50, ein) != NULL) {
495:     if (!silent) if (!(ZNR & 0xfff)) {
496:       fprintf(stderr, " %5.1f %%\r", (float) ((100.0 * ftell(ein)) / ((float) FileSize)));
497:     }
498:     Kennwort[0] = '\0'; ZNR++;
499:     sw = sscanf(Zeile, "%s %f %f %f", Kennwort, &d1, &d2, &d3);
500:     if (!strcmp(Kennwort, "solid")) {
501:       STATE = 1;
502:       Kennwort2[0] = '\0';
503:       sscanf(Zeile, "%s %s", Kennwort, Kennwort2);
504:       if (data_in_temp) {
505:         if (!silent) fprintf(stderr, " Pass 1 ready\r");
506:         FlushFileIndexedSLP(temp, aus2);
507:         data_in_temp = 0;
508:         fclose(temp); unlink(LTemp);
509:         if ((temp = fopen(LTemp, "w+b"))== NULL) {
510:           fprintf(stderr, "Temporaerdatei '%s' nicht schreibbar!\n", LTemp);
511:           fclose(ein); Pause(); return 0;
512:         }
513:         if (!silent) fprintf(stderr, " Pass 2 ready        \n");
514:       }
515:       store_beginsolid(aus2, Kennwort2);
516:     } else
517:     if (!strcmp(Kennwort, "endsolid")) {
518:       STATE = 0;
519:       if (data_in_temp) {
520:         if (!silent) fprintf(stderr, " Pass 1 ready\r");
521:         FlushFileIndexedSLP(temp, aus2);
522:         data_in_temp = 0;
523:         fclose(temp); unlink(LTemp);
524:         if ((temp = fopen(LTemp, "w+b"))== NULL) {
525:           fprintf(stderr, "Temporaerdatei '%s' nicht schreibbar!\n", LTemp);
526:           fclose(ein); Pause(); return 0;
527:         }
528:         if (!silent) fprintf(stderr, " Pass 2 ready        \n");
529:       }
530:       store_endsolid(aus2);
531:     } else
532:     if (!strcmp(Kennwort, "color")) {
533:       if ((STATE == 1) && (sw == 4))
534:         if (colorindexed) {
535:           pn = coordinate_index(d1, d2, d3);
536:           store_color_indexed(temp, pn);
537:         } else
538:           store_set_color(temp, (float) d1, (float) d2, (float) d3);
539:         data_in_temp = 1;
540:     } else
541:     if (!strcmp(Kennwort, "facet")) {
542:       if (STATE == 1) {
543:         cn = cv = 0;
544:         STATE = 2;
545:         sw = sscanf(Zeile, "%s %s %f %f %f", Kennwort, Kennwort2, &d1, &d2, &d3);
546:         if ((sw == 5) && !strcmp(Kennwort2, "normal") && (cn < 3)) {
547:           nx[cn] = d1; ny[cn] = d2; nz[cn] = d3; cn++;
548:         }
549:       }
550:     } else
551:     if (!strcmp(Kennwort, "endfacet")) {
552:       if (STATE > 1) {
553:         if ((cv == 3) && (cn > 0)) {
554:           NNx = nx[0]; NNy = ny[0]; NNz = nz[0];
555:           for (sw = 1; sw < cn; sw++) {
556:             NNx += nx[sw]; NNy += ny[sw]; NNz += nz[sw];
557:           }
558:           vx[3] = vx[1] - vx[0]; vx[4] = vx[2] - vx[1]; vx[5] = vx[0] - vx[2];
559:           vy[3] = vy[1] - vy[0]; vy[4] = vy[2] - vy[1]; vy[5] = vy[0] - vy[2];
560:           vz[3] = vz[1] - vz[0]; vz[4] = vz[2] - vz[1]; vz[5] = vz[0] - vz[2];
561:           Nx = (vy[3] * vz[4] - vz[3] * vy[4]) + (vy[4] * vz[5] - vz[4] * vy[5]) + (vy[5] * vz[3] - vz[5] * vy[3]);
562:           Ny = (vz[3] * vx[4] - vx[3] * vz[4]) + (vz[4] * vx[5] - vx[4] * vz[5]) + (vz[5] * vx[3] - vx[5] * vz[3]);
563:           Nz = (vx[3] * vy[4] - vy[3] * vx[4]) + (vx[4] * vy[5] - vy[4] * vx[5]) + (vx[5] * vy[3] - vy[5] * vx[3]);
564:           NL = sqrt(Nx*Nx + Ny*Ny + Nz*Nz);
565:           if (NL >= 1.0e-100L) {
566:             if ((d1 = Nx * NNx + Ny * NNy + Nz * NNz) > 0.0) {
567:             } else if (d1 < 0.0) {
568:               NL *= -1.0;
569:               vx[4] = vx[1]; vx[1] = vx[2]; vx[2] = vx[4];
570:               vy[4] = vy[1]; vy[1] = vy[2]; vy[2] = vy[4];
571:               vz[4] = vz[1]; vz[1] = vz[2]; vz[2] = vz[4];
572:             }
573:             Nx /= NL; Ny /= NL; Nz /= NL;
574:           }
575:           pn = coordinate_index(Nx, Ny, Nz);
576:           p1 = coordinate_index(vx[0], vy[0], vz[0]);
577:           p2 = coordinate_index(vx[1], vy[1], vz[1]);
578:           p3 = coordinate_index(vx[2], vy[2], vz[2]);
579:           store_facet_indexed(temp, pn, p1, p2, p3);
580:           data_in_temp = 1;
581:         }
582:         STATE = 1;
583:       }
584:     } else
585:     if (!strcmp(Kennwort, "outer")) {
586:       if (STATE == 2) STATE = 3;
587:     } else
588:     if (!strcmp(Kennwort, "endloop")) {
589:       if (STATE == 3) STATE = 2;
590:     } else
591:     if (!strcmp(Kennwort, "normal")) {
592:       if ((STATE == 2) && (sw == 4) && (cn < 3)) {
593:         nx[cn] = d1; ny[cn] = d2; nz[cn] = d3; cn++;
594:       }
595:     } else
596:     if (!strcmp(Kennwort, "vertex")) {
597:       if ((STATE == 3) && (sw == 4) && (cv < 3)) {
598:         vx[cv] = d1; vy[cv] = d2; vz[cv] = d3; cv++;
599:       }
600:     }
601:   }
602:   flush_facets(temp);
603:   if (data_in_temp) {
604:     if (!silent) fprintf(stderr, " Pass 1 ready\r");
605:     FlushFileIndexedSLP(temp, aus2);
606:     data_in_temp = 0;
607:     if (!silent) fprintf(stderr, " Pass 2 ready        \n");
608:   }
609:   fclose(temp); unlink(LTemp);
610:   return 1;
611: }
612: 
613: 
614: int ReadFileSLP(FILE *ein, FILE *aus)
615: { char Zeile[MAX_PATH + 50], Kennwort[MAX_PATH + 50], Kennwort2[MAX_PATH + 50];
616:   unsigned long ZNR;
617:   int sw, stp = -1, STATE = -1, cv, cn;
618:   float d1, d2, d3, nx[3], ny[3], nz[3], vx[6], vy[6], vz[6], Nx, Ny, Nz, NNx, NNy, NNz; double NL;
619:   trianguleto.repeated = 0;
620:   ZNR = 0;
621:   while (fgets(Zeile, MAX_PATH + 50, ein) != NULL) {
622:     Kennwort[0] = '\0'; ZNR++;
623:     sw = sscanf(Zeile, "%s %f %f %f", Kennwort, &d1, &d2, &d3);
624:     if (!strcmp(Kennwort, "solid")) {
625:       STATE = 1;
626:       Kennwort2[0] = '\0';
627:       sscanf(Zeile, "%s %s", Kennwort, Kennwort2);
628:       store_beginsolid(aus, Kennwort2);
629:     } else
630:     if (!strcmp(Kennwort, "endsolid")) {
631:       STATE = 0;
632:       store_endsolid(aus);
633:     } else
634:     if (!strcmp(Kennwort, "color")) {
635:       if ((STATE == 1) && (sw == 4))
636:         store_set_color(aus, (float) d1, (float) d2, (float) d3);
637:     } else
638:     if (!strcmp(Kennwort, "facet")) {
639:       if (STATE == 1) {
640:         cn = cv = 0;
641:         STATE = 2;
642:         sw = sscanf(Zeile, "%s %s %f %f %f", Kennwort, Kennwort2, &d1, &d2, &d3);
643:         if ((sw == 5) && !strcmp(Kennwort2, "normal") && (cn < 3)) {
644:           nx[cn] = d1; ny[cn] = d2; nz[cn] = d3; cn++;
645:         }
646:       }
647:     } else
648:     if (!strcmp(Kennwort, "endfacet")) {
649:       if (STATE > 1) {
650:         if ((cv == 3) && (cn > 0)) {
651:           NNx = nx[0]; NNy = ny[0]; NNz = nz[0];
652:           for (sw = 1; sw < cn; sw++) {
653:             NNx += nx[sw]; NNy += ny[sw]; NNz += nz[sw];
654:           }
655:           // fprintf(stderr, "NN %8.3f %8.3f %8.3f\n", NNx, NNy, NNz);
656:           vx[3] = vx[1] - vx[0]; vx[4] = vx[2] - vx[1]; vx[5] = vx[0] - vx[2];
657:           vy[3] = vy[1] - vy[0]; vy[4] = vy[2] - vy[1]; vy[5] = vy[0] - vy[2];
658:           vz[3] = vz[1] - vz[0]; vz[4] = vz[2] - vz[1]; vz[5] = vz[0] - vz[2];
659:           /*
660:           { int i;
661:             for (i = 0; i < 6; i++) fprintf(stderr, " %d %8.3f %8.3f %8.3f\n", i, vx[i], vy[i], vz[i]);
662:           }
663:           */
664:           Nx = (vy[3] * vz[4] - vz[3] * vy[4]) + (vy[4] * vz[5] - vz[4] * vy[5]) + (vy[5] * vz[3] - vz[5] * vy[3]);
665:           Ny = (vz[3] * vx[4] - vx[3] * vz[4]) + (vz[4] * vx[5] - vx[4] * vz[5]) + (vz[5] * vx[3] - vx[5] * vz[3]);
666:           Nz = (vx[3] * vy[4] - vy[3] * vx[4]) + (vx[4] * vy[5] - vy[4] * vx[5]) + (vx[5] * vy[3] - vy[5] * vx[3]);
667:           // fprintf(stderr, " X %8.3f+%8.3f+%8.3f\n", vy[3] * vz[4] - vz[3] * vy[4], vy[4] * vz[5] - vz[4] * vy[5], vy[5] * vz[3] - vz[5] * vy[3]);
668:           // fprintf(stderr, " Y %8.3f+%8.3f+%8.3f\n", vz[3] * vx[4] - vx[3] * vz[4], vz[4] * vx[5] - vx[4] * vz[5], vz[5] * vx[3] - vx[5] * vz[3]);
669:           // fprintf(stderr, " Z %8.3f+%8.3f+%8.3f\n", vx[3] * vy[4] - vy[3] * vx[4], vx[4] * vy[5] - vy[4] * vx[5], vx[5] * vy[3] - vy[5] * vx[3]);
670:           NL = sqrt(Nx*Nx + Ny*Ny + Nz*Nz);
671:           // fprintf(stderr, "xN %8.3f %8.3f %8.3f - %8.3f\n", Nx, Ny, Nz, NL);
672:           if (NL >= 1.0e-100L) {
673:             if ((d1 = Nx * NNx + Ny * NNy + Nz * NNz) > 0.0) {
674:             } else if (d1 < 0.0) {
675:               NL *= -1.0;
676:               vx[4] = vx[1]; vx[1] = vx[2]; vx[2] = vx[4];
677:               vy[4] = vy[1]; vy[1] = vy[2]; vy[2] = vy[4];
678:               vz[4] = vz[1]; vz[1] = vz[2]; vz[2] = vz[4];
679:             }
680:             // fprintf(stderr, "xN %8.3f %8.3f %8.3f - %8.3f\n", Nx, Ny, Nz, NL);
681:             Nx /= NL; Ny /= NL; Nz /= NL;
682:             // fprintf(stderr, "xN %8.3f %8.3f %8.3f - %8.3f\n", Nx, Ny, Nz, NL);
683:           }
684:           // fprintf(stderr, " N %8.3f %8.3f %8.3f\n", Nx, Ny, Nz);
685:           store_facet_short(aus, Nx, Ny, Nz, vx, vy, vz);
686:         }
687:         STATE = 1;
688:       }
689:     } else
690:     if (!strcmp(Kennwort, "outer")) {
691:       if (STATE == 2) STATE = 3;
692:     } else
693:     if (!strcmp(Kennwort, "endloop")) {
694:       if (STATE == 3) STATE = 2;
695:     } else
696:     if (!strcmp(Kennwort, "normal")) {
697:       if ((STATE == 2) && (sw == 4) && (cn < 3)) {
698:         nx[cn] = d1; ny[cn] = d2; nz[cn] = d3; cn++;
699:       }
700:     } else
701:     if (!strcmp(Kennwort, "vertex")) {
702:       if ((STATE == 3) && (sw == 4) && (cv < 3)) {
703:         vx[cv] = d1; vy[cv] = d2; vz[cv] = d3; cv++;
704:       }
705:     }
706:   }
707:   flush_facets(aus);
708:   return 1;
709: }
710: 
711: 
712: int which_eoln(FILE *ein)
713: { unsigned char C;
714:   unsigned long CP;
715:   CP = ftell(ein);
716:   while (fread(&C, 1, 1, ein) > 0) {
717:     switch(C) {
718:       case '\n': case '\r': 
719:         fseek(ein, CP, SEEK_SET);
720:         return 1;
721:       case '\0':
722:         fseek(ein, CP, SEEK_SET);
723:         return 2;
724:     }
725:   }
726:   fseek(ein, CP, SEEK_SET);
727:   return -1;
728: }
729: 
730: void ReadFileIn(char *datei, char *nach)
731: { FILE *ein;
732:   char Kopf[8];
733:   total_facet_count = 0;
734:   if ((ein = fopen(datei, "rb")) == NULL) {
735:     fprintf(stderr, "Datei '%s' nicht lesbar!\n", datei);
736:     Pause();
737:     return;
738:   }
739:   Kopf[0] = '\0';
740:   fread(Kopf, 1, strlen(SLP_STL_ASCII_HEAD), ein);
741:   fseek(ein, 0L, SEEK_END); FileSize = ftell(ein); fseek(ein, 0L, SEEK_SET);
742:   Kopf[strlen(SLP_STL_ASCII_HEAD)] = '\0';
743:   if (!strcmp(Kopf, SLP_STL_ASCII_HEAD)) {
744:     switch(which_eoln(ein)) {
745:       case 1:
746:         if ((aus = aus2 = fopen(nach, "wb")) == NULL) {
747:           fprintf(stderr, "Datei '%s' nicht schreibbar!\n", nach);
748:           fclose(ein); Pause(); return;
749:         }
750:         fwrite(&head, 1, sizeof(struct HEAD), aus); swap_still_allowed = 0;
751:         ReadFileSLP(ein, aus);
752:         fclose(aus);
753:         if (!total_facet_count) unlink(nach);
754:       break;
755:       default:
756:         goto reading_unknown_type;
757:     }
758:   } else {
759:     reading_unknown_type:
760:     fprintf(stderr, "Unbekannter Datentyp!\n");
761:   }
762:   fclose(ein);
763: }
764: 
765: void ReadFileInIndexed(char *datei, char *nach)
766: { FILE *ein;
767:   char Kopf[8], Temp[MAX_PATH];
768:   Temp[0] = '\0'; ein = NULL;
769:   total_facet_count = 0;
770:   if ((ein = fopen(datei, "rb")) == NULL) {
771:     fprintf(stderr, "Datei '%s' nicht lesbar!\n", datei);
772:     Pause(); return;
773:   }
774:   // sprintf(Temp, "_vtf.%u.tmp", getpid());
775:   Kopf[0] = '\0';
776:   fread(Kopf, 1, strlen(SLP_STL_ASCII_HEAD), ein);
777:   fseek(ein, 0L, SEEK_END); FileSize = ftell(ein); fseek(ein, 0L, SEEK_SET);
778:   Kopf[strlen(SLP_STL_ASCII_HEAD)] = '\0';
779:   if (!strcmp(Kopf, SLP_STL_ASCII_HEAD)) {
780:     switch(which_eoln(ein)) {
781:       case 1:
782:         // if ((aus = fopen(Temp, "wb"))== NULL) {
783:         //   fprintf(stderr, "Temporaerdatei '%s' nicht schreibbar!\n", Temp);
784:         //   fclose(ein); Pause(); return;
785:         // }
786:         if ((aus2 = fopen(nach, "wb")) == NULL) {
787:           fprintf(stderr, "Datei '%s' nicht schreibbar!\n", nach);
788:           fclose(ein); fclose(aus); Pause(); return;
789:         }
790:         fwrite(&head, 1, sizeof(struct HEAD), aus2); swap_still_allowed = 0;
791:         ReadFileIndexedSLP(ein, aus2);
792:         fclose(ein); /* fclose(aus);
793:         if ((ein = fopen(Temp, "rb")) == NULL) {
794:           fprintf(stderr, "Temporaerdatei '%s' nicht lesbar!\n", Temp);
795:           Pause(); return;
796:         }
797:         FlushFileIndexedSLP(ein, aus2);
798:         */
799:         fclose(aus2); fclose(ein); ein = NULL;
800:         // unlink(Temp);
801:         if (!total_facet_count) unlink(nach);
802:         // if (!silent) fprintf(stderr, " Pass 2 ready        \n");
803:       break;
804:       default:
805:         goto reading_unknown_type;
806:     }
807:   } else {
808:     reading_unknown_type:
809:     fprintf(stderr, "Unbekannter Datentyp!\n");
810:   }
811:   if (ein != NULL) fclose(ein);
812: }
813: 
814: void ask_if_indexed(void)
815: { int wahl = 2;
816:   char Zeile[50];
817:   fprintf(stderr, "\nErzeugungsoptionen:         Conversion options:\n");
818:   fprintf(stderr, " 1 = einfach                 1 = simple\n");
819:   fprintf(stderr, " 2 = mit Koordinatentabelle  2 = with coordinate table\n");
820:   fprintf(stderr, " 3 = zus. Farbtabelle        3 = with color and coordinate table\n");
821:   fprintf(stderr, " 0 = ABBRUCH                 0 = ABORT\n");
822:   fprintf(stderr, " Ihre Wahl / your selection? [%d]? ", wahl);
823:   Zeile[0] = '\0'; fgets(Zeile, 50, stdin); sscanf(Zeile, "%d", &wahl);
824:   switch(wahl) {
825:     case 1: indexed = 0; colorindexed = 0; break;
826:     case 2: indexed = 1; colorindexed = 0; break;
827:     case 3: indexed = 1; colorindexed = 1; break;
828:     case 0: exit(0);
829:   }
830: }
831: 
832: int main(int argc, char **argv)
833: { int ct, argp;
834:   char Erg[MAX_PATH + 3], LongPath[MAX_PATH + 3], *FileIn;
835: #ifdef _WIN32
836:   HANDLE Find; WIN32_FIND_DATA fd;
837: #endif
838:   int auto_name = 0;
839: #ifdef _WIN32
840:   unsigned long s_time, e_time;
841:   s_time = GetTickCount();
842:   // fprintf(stderr, ">>> %s <<<\npwd = %s\n", GetCommandLine(), getcwd(NULL, MAX_PATH));
843: #endif
844:   if (argc < 3) {
845:     if (argc == 2) { /* Dialogmodus */
846: #ifdef _WIN32
847:       Find = FindFirstFile(argv[1], &fd);
848:       LongPath[0] = '\0'; GetFullPathName(argv[1], MAX_PATH + 3, LongPath, &FileIn);
849:       if (LongPath[0]) {
850:         strcpy(FileIn, fd.cFileName);
851:         FileIn = LongPath;
852:       } else FileIn = argv[1];
853: #else
854:       FileIn = argv[1];
855: #endif
856:       strcpy(Erg, FileIn);
857:       for (ct = strlen(Erg) - 1; ct >= 0; ct--) {
858:         switch (Erg[ct]) {
859:           case '.':
860:             strcpy(&(Erg[ct]), ".vtf");
861:             ct = -1;
862:           break;
863:           case '\\':
864:             strcat(Erg, ".vtf");
865:             ct = -1;
866:           break;
867:         }
868:       }
869:       if (strcmp(Erg, FileIn)) {
870:         fprintf(stderr, "  %s -> %s ...\n", FileIn, Erg);
871:         if (access(Erg, 0) >= 0) fprintf(stderr, "\nA C H T U N G ! ! !   W A R N I N G ! ! !\n"
872:             "\nDatei wird ueberschrieben!   Output file will be replaced!\n");
873:         indexed = 1; ask_if_indexed();
874:         if (indexed) ReadFileInIndexed(FileIn, Erg);
875:          else ReadFileIn(FileIn, Erg);
876:       }
877: #ifdef _WIN32
878:       FindClose(Find);
879:       e_time = GetTickCount();
880:       e_time -= s_time;
881:       s_time = e_time % 60000L;
882:       if (!silent) fprintf(stderr, "%lu Min., %lu Sek., %lu ms\n",
883:         e_time / 60000L, s_time / 1000L, s_time % 1000L);
884: #endif
885:       return 0;
886:     } else {
887:       fprintf(stderr, "Zu wenig Argumente!\n");
888:       fprintf(stderr, "Gebrauch:\n"
889:                       "  slp2vtf [-index] [-silent] [-swap] <SLP-Datei-'von'> <VTF-Datei-'nach'>\n"
890:                       "  slp2vtf [-colorindex] [-silent] [-swap] <SLP-Datei-'von'> <VTF-Datei-'nach'>\n"
891:                       "  slp2vtf [-auto] [-index] [-silent] [-swap] <SLP-Datei(en)-'von'>\n"
892:                       "  slp2vtf [-auto] [-colorindex] [-silent] [-swap] <SLP-Datei(en)-'von'>\n");
893:       Pause(); return 1;
894:     }
895:   }
896:   for (argp = 1; argp < argc; argp++) {
897:     if (argv[argp][0] == '-') {
898:       if (!strcmp(argv[argp], "-auto"))   auto_name = 1;
899:       if (!strcmp(argv[argp], "-index"))  indexed = 1;
900:       if (!strcmp(argv[argp], "-silent")) silent = 1;
901:       if (!strcmp(argv[argp], "-swap") && swap_still_allowed) { swaped = 1 - swaped;
902:         swap2(&(head.us)); swap4(&(head.ul));
903:         swap4((unsigned long *)&(head.f)); swap8((unsigned __int64 *)&(head.d));
904:       }
905:       if (!strcmp(argv[argp], "-colorindex")) { indexed = 1, colorindexed = 1; }
906:     } else {
907:       if (auto_name) {
908: #ifdef _WIN32
909:         Find = FindFirstFile(argv[argp], &fd);
910:         LongPath[0] = '\0'; GetFullPathName(argv[argp], MAX_PATH + 3, LongPath, &FileIn);
911:         if (LongPath[0]) {
912:           strcpy(FileIn, fd.cFileName);
913:           FileIn = LongPath;
914:         } else FileIn = argv[argp];
915: #else
916:         FileIn = argv[argp];
917: #endif
918:         strcpy(Erg, FileIn);
919:         for (ct = strlen(Erg) - 1; ct >= 0; ct--) {
920:           switch (Erg[ct]) {
921:             case '.':
922:               strcpy(&(Erg[ct]), ".vtf");
923:               ct = -1;
924:             break;
925:             case '\\': case '/': case ':':
926:               strcat(Erg, ".vtf");
927:               ct = -1;
928:             break;
929:           }
930:         }
931:         if (strcmp(Erg, FileIn)) {
932:           if (!silent) fprintf(stderr, "  %s -> %s ...\n", FileIn, Erg);
933:           if (indexed) ReadFileInIndexed(FileIn, Erg);
934:            else ReadFileIn(FileIn, Erg);
935:         }
936: #ifdef _WIN32
937:         FindClose(Find);
938: #endif
939:       } else {
940:         if (indexed) ReadFileInIndexed(argv[argp], argv[argp + 1]);
941:           else ReadFileIn(argv[argp], argv[argp + 1]);
942: #ifdef _WIN32
943:   e_time = GetTickCount();
944:   e_time -= s_time;
945:   s_time = e_time % 60000L;
946:   if (!silent) fprintf(stderr, "%lu Min., %lu Sek., %lu ms\n",
947:     e_time / 60000L, s_time / 1000L, s_time % 1000L);
948: #endif
949:         return 0;
950:       }
951:     }
952:   }
953: #ifdef _WIN32
954:   e_time = GetTickCount();
955:   e_time -= s_time;
956:   s_time = e_time % 60000L;
957:   if (!silent) fprintf(stderr, "%lu Min., %lu Sek., %lu ms\n",
958:     e_time / 60000L, s_time / 1000L, s_time % 1000L);
959: #endif
960:   return 0;
961: }
962: