root/OpenSceneGraph/trunk/src/osgPlugins/lwo/old_lw.cpp @ 13041

Revision 13041, 11.8 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * Copyright (C) 1998,1999 Janne Löf <jlof@mail.student.oulu.fi>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18
19#include "old_lw.h"
20
21#include "lwo2read.h"
22
23#include <stdio.h>
24#include <math.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include <osgDB/FileUtils>
29
30#define MK_ID(a,b,c,d) ((((guint32)(a))<<24)| \
31            (((guint32)(b))<<16)| \
32            (((guint32)(c))<< 8)| \
33            (((guint32)(d))    ))
34
35#define ID_FORM MK_ID('F','O','R','M')
36#define ID_LWOB MK_ID('L','W','O','B')
37#define ID_PNTS MK_ID('P','N','T','S')
38#define ID_SRFS MK_ID('S','R','F','S')
39#define ID_SURF MK_ID('S','U','R','F')
40#define ID_POLS MK_ID('P','O','L','S')
41#define ID_COLR MK_ID('C','O','L','R')
42
43#define ID_CTEX MK_ID('C','T','E','X')
44#define ID_DTEX MK_ID('D','T','E','X')
45#define ID_STEX MK_ID('S','T','E','X')
46#define ID_RTEX MK_ID('R','T','E','X')
47#define ID_TTEX MK_ID('T','T','E','X')
48#define ID_BTEX MK_ID('B','T','E','X')
49
50#define ID_TIMG MK_ID('T','I','M','G')
51#define ID_TFLG MK_ID('T','F','L','G')
52#define ID_TSIZ MK_ID('T','S','I','Z')
53#define ID_TCTR MK_ID('T','C','T','R')
54#define ID_TFAL MK_ID('T','F','A','L')
55#define ID_TVEL MK_ID('T','V','E','L')
56#define ID_TWRP MK_ID('T','W','R','P')
57
58
59#define FALSE 0
60#define TRUE  1
61
62#define g_return_val_if_fail(expr,val) if (!(expr)) return val;
63#define g_return_if_fail(expr) if (!(expr)) return;
64#define g_realloc(exp1,exp2) realloc(exp1,exp2)
65#define g_malloc0(exp) malloc(exp)
66#define g_warning printf
67#define g_free free
68
69static gint32 read_char(FILE *f)
70{
71  int c = fgetc(f);
72  g_return_val_if_fail(c != EOF, 0);
73  return c;
74}
75
76static gint32 read_short(FILE *f)
77{
78  return (read_char(f)<<8) | read_char(f);
79}
80
81static gint32 read_long(FILE *f)
82{
83  return (read_char(f)<<24) | (read_char(f)<<16) | (read_char(f)<<8) | read_char(f);
84}
85
86
87static GLfloat read_float(FILE *f)
88{
89  return lwo2::changeType4<GLfloat, gint32>(read_long(f));
90}
91
92static gint read_string(FILE *f, char *s)
93{
94  gint c;
95  gint cnt = 0;
96  do {
97    c = read_char(f);
98    if (cnt < LW_MAX_NAME_LEN)
99      s[cnt] = c;
100    else
101      s[LW_MAX_NAME_LEN-1] = 0;
102    cnt++;
103  } while (c != 0);
104  /* if length of string (including \0) is odd skip another byte */
105  if (cnt%2) {
106    read_char(f);
107    cnt++;
108  }
109  return cnt;
110}
111
112static void read_srfs(FILE *f, gint nbytes, lwObject *lwo)
113{
114  int guess_cnt = lwo->material_cnt;
115
116  while (nbytes > 0) {
117    lwMaterial *material;
118
119    /* allocate more memory for materials if needed */
120    if (guess_cnt <= lwo->material_cnt) {
121      guess_cnt += guess_cnt/2 + 4;
122      lwo->material = (lwMaterial*) g_realloc(lwo->material, sizeof(lwMaterial)*guess_cnt);
123    }
124    material = lwo->material + lwo->material_cnt++;
125
126    /* read name */
127    nbytes -= read_string(f,material->name);
128
129    /* defaults */
130    material->r = 0.7f;
131    material->g = 0.7f;
132    material->b = 0.7f;
133  }
134  lwo->material = (lwMaterial*) g_realloc(lwo->material, sizeof(lwMaterial)*lwo->material_cnt);
135}
136
137
138static void read_surf(FILE *f, gint nbytes, lwObject *lwo)
139{
140  int i;
141  char name[LW_MAX_NAME_LEN];
142  lwMaterial *material = NULL;
143
144  /* read surface name */
145  nbytes -= read_string(f,name);
146
147  /* find material */
148  for (i=0; i< lwo->material_cnt; i++) {
149    if (strcmp(lwo->material[i].name,name) == 0) {
150      material = &lwo->material[i];
151      break;
152    }
153  }
154  g_return_if_fail(material != NULL);
155
156  lwTexture* tex = NULL;
157
158  /* read values */
159  while (nbytes > 0) {
160    gint id = read_long(f);
161    gint len = read_short(f);
162    nbytes -= 6 + len + (len%2);
163
164    switch (id) {
165    case ID_COLR:
166      material->r = read_char(f) / 255.0f;
167      material->g = read_char(f) / 255.0f;
168      material->b = read_char(f) / 255.0f;
169      read_char(f); /* dummy */
170      break;
171    case ID_CTEX:
172    case ID_DTEX:
173    case ID_STEX:
174    case ID_RTEX:
175    case ID_TTEX:
176    case ID_BTEX:
177      len -= read_string(f, name);
178      if (id == ID_CTEX) {
179        tex = &material->ctex;
180      }
181      else
182        tex = NULL;
183      break;
184    case ID_TIMG: {
185      len -= read_string(f, name);
186      if (tex) {
187        /* last component of path */
188        char* slash = strrchr(name, '/');
189        if (!slash)
190          slash = strrchr(name, '\\');
191        if (slash)
192          strcpy(tex->name, slash+1);
193        else
194          strcpy(tex->name, name);
195        //printf("tex name=%s\n", tex->name);
196      }
197    } break;
198    case ID_TFLG:
199      if (tex) {
200        tex->flags = read_short(f);
201      }
202      else
203        fseek(f, len+(len%2), SEEK_CUR);
204      break;
205    case ID_TSIZ:
206      if (tex) {
207        tex->sx = read_float(f);
208        tex->sy = read_float(f);
209        tex->sz = read_float(f);
210      }
211      else
212        fseek(f, len+(len%2), SEEK_CUR);
213      break;
214    case ID_TCTR:
215      if (tex) {
216        tex->cx = read_float(f);
217        tex->cy = read_float(f);
218        tex->cz = read_float(f);
219      }
220      else
221        fseek(f, len+(len%2), SEEK_CUR);
222      break;
223    case ID_TFAL:
224        if (tex) {
225            //float vx,vy,vz;
226            /*vx =*/ read_float(f);
227            /*vy =*/ read_float(f);
228            /*vz =*/ read_float(f);
229            //printf("fal %.2f %.2f %.2f\n", vx,vy,vz);
230        }
231        else
232            fseek(f, len+(len%2), SEEK_CUR);
233        break;
234    case ID_TVEL:
235        if (tex) {
236            //float vx,vy,vz;
237            /*vx =*/ read_float(f);
238            /*vy =*/ read_float(f);
239            /*vz =*/ read_float(f);
240            //printf("vel %.2f %.2f %.2f\n", vx,vy,vz);
241        }
242        else
243            fseek(f, len+(len%2), SEEK_CUR);
244        break;
245    case ID_TWRP:
246      if (tex) {
247        tex->u_wrap = (lwTextureWrap) read_short(f);
248        tex->v_wrap = (lwTextureWrap) read_short(f);
249      }
250      else
251        fseek(f, len+(len%2), SEEK_CUR);
252      break;
253    default:
254      fseek(f, len+(len%2), SEEK_CUR);
255    }
256  }
257}
258
259
260static void read_pols(FILE *f, int nbytes, lwObject *lwo)
261{
262  int guess_cnt = lwo->face_cnt;
263
264  while (nbytes > 0) {
265    lwFace *face;
266    int i;
267
268    /* allocate more memory for polygons if necessary */
269    if (guess_cnt <= lwo->face_cnt) {
270      guess_cnt += guess_cnt + 4;
271      lwo->face = (lwFace*) g_realloc(lwo->face, sizeof(lwFace)*guess_cnt);
272    }
273    face = lwo->face + lwo->face_cnt++;
274
275    face->init();
276
277    /* number of points in this face */
278    face->index_cnt = read_short(f);
279    nbytes -= 2;
280
281    /* allocate space for points */
282    face->index = (int*) g_malloc0(sizeof(int)*face->index_cnt);
283
284    /* read points in */
285    for (i=0; i<face->index_cnt; i++) {
286      face->index[i] = read_short(f);
287      nbytes -= 2;
288    }
289
290    /* read surface material */
291    face->material = read_short(f);
292    nbytes -= 2;
293
294    /* skip over detail  polygons */
295    if (face->material < 0) {
296      printf("face->material=%i    ",face->material);
297      int det_cnt;
298      face->material = -face->material;
299      det_cnt = read_short(f);
300      nbytes -= 2;
301      while (det_cnt-- > 0) {
302    int cnt = read_short(f);
303    fseek(f, cnt*2+2, SEEK_CUR);
304    nbytes -= cnt*2+2;
305      }
306    }
307    face->material -= 1;
308  }
309  /* readjust to true size */
310  lwo->face = (lwFace*) g_realloc(lwo->face, sizeof(lwFace)*lwo->face_cnt);
311}
312
313
314
315static void read_pnts(FILE *f, gint nbytes, lwObject *lwo)
316{
317  int i;
318  lwo->vertex_cnt = nbytes / 12;
319  lwo->vertex = (GLfloat*) g_malloc0(sizeof(GLfloat)*lwo->vertex_cnt*3);
320  for (i=0; i<lwo->vertex_cnt; i++) {
321    lwo->vertex[i*3+0] = read_float(f);
322    lwo->vertex[i*3+1] = read_float(f);
323    lwo->vertex[i*3+2] = read_float(f);
324  }
325}
326
327
328
329
330
331
332gint lw_is_lwobject(const char *lw_file)
333{
334  FILE *f = osgDB::fopen(lw_file, "rb");
335  if (f) {
336    gint32 form = read_long(f);
337    gint32 nlen = read_long(f);
338    gint32 lwob = read_long(f);
339    fclose(f);
340    if (form == ID_FORM && nlen != 0 && lwob == ID_LWOB)
341      return TRUE;
342  }
343  return FALSE;
344}
345
346
347lwObject *lw_object_read(const char *lw_file, std::ostream& output)
348{
349  FILE *f = NULL;
350  lwObject *lw_object = NULL;
351
352  gint32 form_bytes = 0;
353  gint32 read_bytes = 0;
354
355  /* open file */
356  f = osgDB::fopen(lw_file, "rb");
357  if (f == NULL) {
358    output << "can't open file "<<lw_file<<std::endl;
359    return NULL;
360  }
361
362  /* check for headers */
363  if (read_long(f) != ID_FORM) {
364    output << "file "<<lw_file<<" is not an IFF file"<<std::endl;
365    fclose(f);
366    return NULL;
367  }
368  form_bytes = read_long(f);
369  read_bytes += 4;
370
371  if (read_long(f) != ID_LWOB) {
372    output << "file "<<lw_file<<" is not a LWOB file"<<std::endl;
373    fclose(f);
374    return NULL;
375  }
376
377  /* create new lwObject */
378  lw_object = (lwObject*) g_malloc0(sizeof(lwObject));
379  lw_object->init();
380
381  /* read chunks */
382  while (read_bytes < form_bytes) {
383    gint32  id     = read_long(f);
384    gint32  nbytes = read_long(f);
385    read_bytes += 8 + nbytes + (nbytes%2);
386
387    switch (id) {
388    case ID_PNTS:
389      read_pnts(f, nbytes, lw_object);
390      break;
391    case ID_POLS:
392      read_pols(f, nbytes, lw_object);
393      break;
394    case ID_SRFS:
395      read_srfs(f, nbytes, lw_object);
396      break;
397    case ID_SURF:
398      read_surf(f, nbytes, lw_object);
399      break;
400    default:
401      fseek(f, nbytes + (nbytes%2), SEEK_CUR);
402    }
403  }
404
405  fclose(f);
406
407  for (int i = 0; i < lw_object->face_cnt; i++) {
408      int mati = lw_object->face[i].material;
409      if (mati == 0)
410          continue;
411
412      /* fetch material */
413      lwMaterial* mat = &lw_object->material[mati];
414      unsigned int flags = mat->ctex.flags;
415      if (flags == 0)
416          continue;
417
418      /* calculate texture coordinates */
419      lwFace* face = &lw_object->face[i];
420      face->texcoord = (float*) g_malloc0(face->index_cnt * sizeof(float) * 2);
421      for (int j = 0; j < face->index_cnt; j++) {
422          int vi = face->index[j];
423          GLfloat* vtx = &lw_object->vertex[vi*3];
424
425          GLfloat u,v;
426          u = v = 0.0f;
427          if (flags & X_AXIS) {
428              u = (vtx[1] - mat->ctex.cy) / mat->ctex.sy;
429              v = (vtx[2] - mat->ctex.cz) / mat->ctex.sz;
430          }
431          else if (flags & Y_AXIS) {
432              u = (vtx[0] - mat->ctex.cx) / mat->ctex.sx;
433              v = (vtx[2] - mat->ctex.cz) / mat->ctex.sz;
434          }
435          else if (flags & Z_AXIS) {
436              u = (vtx[0] - mat->ctex.cx) / mat->ctex.sx;
437              v = (vtx[1] - mat->ctex.cy) / mat->ctex.sy;
438          }
439          face->texcoord[j*2] = u + 0.5f;
440          face->texcoord[j*2+1] = v + 0.5f;
441          //printf("%.2f %.2f\n", u,v);
442      }
443  }
444
445  return lw_object;
446}
447
448
449
450
451
452
453
454void lw_object_free(lwObject *lw_object)
455{
456  g_return_if_fail(lw_object != NULL);
457
458  if (lw_object->face) {
459    int i;
460    for (i=0; i<lw_object->face_cnt; i++) {
461      g_free(lw_object->face[i].index);
462      if (lw_object->face[i].texcoord)
463          g_free(lw_object->face[i].texcoord);
464    }
465    g_free(lw_object->face);
466  }
467  g_free(lw_object->material);
468  g_free(lw_object->vertex);
469  g_free(lw_object);
470}
471
472
473GLfloat lw_object_radius(const lwObject *lwo)
474{
475  int i;
476  double max_radius = 0.0;
477
478  g_return_val_if_fail(lwo != NULL, 0.0);
479
480  for (i=0; i<lwo->vertex_cnt; i++) {
481    GLfloat *v = &lwo->vertex[i*3];
482    double r = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
483    if (r > max_radius)
484      max_radius = r;
485  }
486  return (float)sqrt(max_radius);
487}
488
489void lw_object_scale(lwObject *lwo, GLfloat scale)
490{
491  int i;
492
493  g_return_if_fail(lwo != NULL);
494
495  for (i=0; i<lwo->vertex_cnt; i++) {
496    lwo->vertex[i*3+0] *= scale;
497    lwo->vertex[i*3+1] *= scale;
498    lwo->vertex[i*3+2] *= scale;
499  }
500}
501
Note: See TracBrowser for help on using the browser.