home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / samples / opengl / penguin / lw.cpp next >
C/C++ Source or Header  |  2002-05-12  |  10KB  |  439 lines

  1. /*
  2.  * Copyright (C) 1998 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 Library 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.  * Library General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU Library General Public
  15.  * License along with this library; if not, write to the Free
  16.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. // For compilers that support precompilation, includes "wx.h".
  20. #include "wx/wxprec.h"
  21.  
  22. #ifdef __BORLANDC__
  23. #pragma hdrstop
  24. #endif
  25.  
  26. #ifndef WX_PRECOMP
  27. #include "wx/wx.h"
  28. #endif
  29.  
  30. #ifdef __WXMSW__
  31. #include <windows.h>
  32. #endif
  33.  
  34. #include "lw.h"
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <math.h>
  38.  
  39. #define MK_ID(a,b,c,d) ((((wxUint32)(a))<<24)| \
  40.             (((wxUint32)(b))<<16)| \
  41.             (((wxUint32)(c))<< 8)| \
  42.             (((wxUint32)(d))    ))
  43.  
  44. #define ID_FORM MK_ID('F','O','R','M')
  45. #define ID_LWOB MK_ID('L','W','O','B')
  46. #define ID_PNTS MK_ID('P','N','T','S')
  47. #define ID_SRFS MK_ID('S','R','F','S')
  48. #define ID_SURF MK_ID('S','U','R','F')
  49. #define ID_POLS MK_ID('P','O','L','S')
  50. #define ID_COLR MK_ID('C','O','L','R')
  51.  
  52. static wxInt32 read_char(FILE *f)
  53. {
  54.   int c = fgetc(f);
  55.   return c;
  56. }
  57.  
  58. static wxInt32 read_short(FILE *f)
  59. {
  60.     // the execution path was not always correct
  61.     // when using the direct evaluation in the return statement
  62.     wxInt32 first = read_char(f) ;
  63.     wxInt32 second = read_char(f) ;
  64.     
  65.   return (first<<8) | second ;
  66. }
  67.  
  68. static wxInt32 read_long(FILE *f)
  69. {
  70.     // the execution path was not always correct
  71.     // when using the direct evaluation in the return statement
  72.     wxInt32 first = read_char(f) ;
  73.     wxInt32 second = read_char(f) ;
  74.     wxInt32 third = read_char(f) ;
  75.     wxInt32 fourth = read_char(f) ;
  76.   return (first<<24) | (second<<16) | (third<<8) | fourth ;
  77. }
  78.  
  79. static GLfloat read_float(FILE *f)
  80. {
  81.   wxInt32 x = read_long(f);
  82.   return *(GLfloat*)&x;
  83. }
  84.  
  85. static int read_string(FILE *f, char *s)
  86. {
  87.   int c;
  88.   int cnt = 0;
  89.   do {
  90.     c = read_char(f);
  91.     if (cnt < LW_MAX_NAME_LEN)
  92.       s[cnt] = c;
  93.     else
  94.       s[LW_MAX_NAME_LEN-1] = 0;
  95.     cnt++;
  96.   } while (c != 0);
  97.   /* if length of string (including \0) is odd skip another byte */
  98.   if (cnt%2) {
  99.     read_char(f);
  100.     cnt++;
  101.   }
  102.   return cnt;
  103. }
  104.  
  105. static void read_srfs(FILE *f, int nbytes, lwObject *lwo)
  106. {
  107.   int guess_cnt = lwo->material_cnt;
  108.  
  109.   while (nbytes > 0) {
  110.     lwMaterial *material;
  111.  
  112.     /* allocate more memory for materials if needed */
  113.     if (guess_cnt <= lwo->material_cnt) {
  114.       guess_cnt += guess_cnt/2 + 4;
  115.       lwo->material = (lwMaterial*) realloc(lwo->material, sizeof(lwMaterial)*guess_cnt);
  116.     }
  117.     material = lwo->material + lwo->material_cnt++;
  118.  
  119.     /* read name */
  120.     nbytes -= read_string(f,material->name);
  121.  
  122.     /* defaults */
  123.     material->r = 0.7f;
  124.     material->g = 0.7f;
  125.     material->b = 0.7f;
  126.   }
  127.   lwo->material = (lwMaterial*) realloc(lwo->material, sizeof(lwMaterial)*lwo->material_cnt);
  128. }
  129.  
  130.  
  131. static void read_surf(FILE *f, int nbytes, lwObject *lwo)
  132. {
  133.   int i;
  134.   char name[LW_MAX_NAME_LEN];
  135.   lwMaterial *material = NULL;
  136.  
  137.   /* read surface name */
  138.   nbytes -= read_string(f,name);
  139.  
  140.   /* find material */
  141.   for (i=0; i< lwo->material_cnt; i++) {
  142.     if (strcmp(lwo->material[i].name,name) == 0) {
  143.       material = &lwo->material[i];
  144.       break;
  145.     }
  146.   }
  147.  
  148.   /* read values */
  149.   while (nbytes > 0) {
  150.     int id = read_long(f);
  151.     int len = read_short(f);
  152.     nbytes -= 6 + len + (len%2);
  153.  
  154.     switch (id) {
  155.     case ID_COLR:
  156.       material->r = read_char(f) / 255.0;
  157.       material->g = read_char(f) / 255.0;
  158.       material->b = read_char(f) / 255.0;
  159.       read_char(f); /* dummy */
  160.       break;
  161.     default:
  162.       fseek(f, len+(len%2), SEEK_CUR);
  163.     }
  164.   }
  165. }
  166.  
  167.  
  168. static void read_pols(FILE *f, int nbytes, lwObject *lwo)
  169. {
  170.   int guess_cnt = lwo->face_cnt;
  171.   
  172.   while (nbytes > 0) {
  173.     lwFace *face;
  174.     int i;
  175.  
  176.     /* allocate more memory for polygons if necessary */
  177.     if (guess_cnt <= lwo->face_cnt) {
  178.       guess_cnt += guess_cnt + 4;
  179.       lwo->face = (lwFace*) realloc((void*) lwo->face, sizeof(lwFace)*guess_cnt);
  180.     }
  181.     face = lwo->face + lwo->face_cnt++;
  182.  
  183.     /* number of points in this face */
  184.     face->index_cnt = read_short(f);
  185.     nbytes -= 2;
  186.  
  187.     /* allocate space for points */
  188.     face->index = (int*) calloc(sizeof(int)*face->index_cnt,1);
  189.     
  190.     /* read points in */
  191.     for (i=0; i<face->index_cnt; i++) {
  192.       face->index[i] = read_short(f);
  193.       nbytes -= 2;
  194.     }
  195.     
  196.     /* read surface material */
  197.     face->material = read_short(f);
  198.     nbytes -= 2;
  199.     
  200.     /* skip over detail  polygons */
  201.     if (face->material < 0) {
  202.       int det_cnt;
  203.       face->material = -face->material;
  204.       det_cnt = read_short(f);
  205.       nbytes -= 2;
  206.       while (det_cnt-- > 0) {
  207.     int cnt = read_short(f);
  208.     fseek(f, cnt*2+2, SEEK_CUR);
  209.     nbytes -= cnt*2+2;
  210.       }
  211.     }
  212.     face->material -= 1;
  213.   }
  214.   /* readjust to true size */
  215.   lwo->face = (lwFace*) realloc(lwo->face, sizeof(lwFace)*lwo->face_cnt);
  216. }
  217.  
  218.  
  219.  
  220. static void read_pnts(FILE *f, int nbytes, lwObject *lwo)
  221. {
  222.   int i;
  223.   lwo->vertex_cnt = nbytes / 12;
  224.   lwo->vertex = (float*) calloc(sizeof(GLfloat)*lwo->vertex_cnt*3, 1);
  225.   for (i=0; i<lwo->vertex_cnt; i++) {
  226.     lwo->vertex[i*3+0] = read_float(f);
  227.     lwo->vertex[i*3+1] = read_float(f);
  228.     lwo->vertex[i*3+2] = read_float(f);
  229.   }
  230. }
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237. int lw_is_lwobject(const char *lw_file)
  238. {
  239.   FILE *f = fopen(lw_file, "rb");
  240.   if (f) {
  241.     wxInt32 form = read_long(f);
  242.     wxInt32 nlen = read_long(f);
  243.     wxInt32 lwob = read_long(f);
  244.     fclose(f);
  245.     if (form == ID_FORM && nlen != 0 && lwob == ID_LWOB)
  246.       return TRUE;
  247.   }
  248.   return FALSE;
  249. }
  250.  
  251.  
  252. lwObject *lw_object_read(const char *lw_file)
  253. {
  254.   FILE *f = NULL;
  255.   lwObject *lw_object = NULL;
  256.  
  257.   wxInt32 form_bytes = 0;
  258.   wxInt32 read_bytes = 0;
  259.  
  260.   /* open file */
  261.   f = fopen(lw_file, "rb");
  262.   if (f == NULL) {
  263.     return NULL;
  264.   }
  265.  
  266.   /* check for headers */
  267.   if (read_long(f) != ID_FORM) {
  268.     fclose(f);
  269.     return NULL;
  270.   }
  271.   form_bytes = read_long(f);
  272.   read_bytes += 4;
  273.  
  274.   if (read_long(f) != ID_LWOB) {
  275.     fclose(f);
  276.     return NULL;
  277.   }
  278.  
  279.   /* create new lwObject */
  280.   lw_object = (lwObject*) calloc(sizeof(lwObject),1);
  281.  
  282.   /* read chunks */
  283.   while (read_bytes < form_bytes) {
  284.     wxInt32  id     = read_long(f);
  285.     wxInt32  nbytes = read_long(f);
  286.     read_bytes += 8 + nbytes + (nbytes%2);
  287.  
  288.     switch (id) {
  289.     case ID_PNTS:
  290.       read_pnts(f, nbytes, lw_object);
  291.       break;
  292.     case ID_POLS:
  293.       read_pols(f, nbytes, lw_object);
  294.       break;
  295.     case ID_SRFS:
  296.       read_srfs(f, nbytes, lw_object);
  297.       break;
  298.     case ID_SURF:
  299.       read_surf(f, nbytes, lw_object);
  300.       break;
  301.     default:
  302.       fseek(f, nbytes + (nbytes%2), SEEK_CUR);
  303.     }
  304.   }
  305.  
  306.   fclose(f);
  307.   return lw_object;
  308. }
  309.  
  310.  
  311.  
  312. void lw_object_free(lwObject *lw_object)
  313. {
  314.   if (lw_object->face) {
  315.     int i;
  316.     for (i=0; i<lw_object->face_cnt; i++)
  317.       free(lw_object->face[i].index);
  318.     free(lw_object->face);
  319.   }
  320.   free(lw_object->material);
  321.   free(lw_object->vertex);
  322.   free(lw_object);
  323. }
  324.  
  325.  
  326.  
  327.  
  328.  
  329. #define PX(i) (lw_object->vertex[face->index[i]*3+0])
  330. #define PY(i) (lw_object->vertex[face->index[i]*3+1])
  331. #define PZ(i) (lw_object->vertex[face->index[i]*3+2])
  332. void lw_object_show(const lwObject *lw_object)
  333. {
  334.   int i,j;
  335.   int prev_index_cnt = -1;
  336.   int prev_material  = -1;
  337.   GLfloat prev_nx = 0;
  338.   GLfloat prev_ny = 0;
  339.   GLfloat prev_nz = 0;
  340.  
  341.   for (i=0; i<lw_object->face_cnt; i++) {
  342.     GLfloat ax,ay,az,bx,by,bz,nx,ny,nz,r;
  343.     const lwFace *face = lw_object->face+i;
  344.  
  345.     /* ignore faces with less than 3 points */
  346.     if (face->index_cnt < 3)
  347.       continue;
  348.  
  349.     /* calculate normal */
  350.     ax = PX(1) - PX(0);
  351.     ay = PY(1) - PY(0);
  352.     az = PZ(1) - PZ(0);
  353.  
  354.     bx = PX(face->index_cnt-1) - PX(0);
  355.     by = PY(face->index_cnt-1) - PY(0);
  356.     bz = PZ(face->index_cnt-1) - PZ(0);
  357.  
  358.     nx = ay * bz - az * by;
  359.     ny = az * bx - ax * bz;
  360.     nz = ax * by - ay * bx;
  361.  
  362.     r = sqrt(nx*nx + ny*ny + nz*nz);
  363.     if (r < 0.000001) /* avoid division by zero */
  364.       continue;
  365.     nx /= r;
  366.     ny /= r;
  367.     nz /= r;
  368.  
  369.     /* glBegin/glEnd */
  370.     if (prev_index_cnt != face->index_cnt || prev_index_cnt > 4) {
  371.       if (prev_index_cnt > 0) glEnd();
  372.       prev_index_cnt = face->index_cnt;
  373.       switch (face->index_cnt) {
  374.       case 3:
  375.     glBegin(GL_TRIANGLES);
  376.     break;
  377.       case 4:
  378.     glBegin(GL_QUADS);
  379.     break;
  380.       default:
  381.     glBegin(GL_POLYGON);
  382.       }
  383.     }
  384.  
  385.     /* update material if necessary */
  386.     if (prev_material != face->material) {
  387.       prev_material = face->material;
  388.       glColor3f(lw_object->material[face->material].r,
  389.         lw_object->material[face->material].g,
  390.         lw_object->material[face->material].b);
  391.     }
  392.  
  393.     /* update normal if necessary */
  394.     if (nx != prev_nx || ny != prev_ny || nz != prev_nz) {
  395.       prev_nx = nx;
  396.       prev_ny = ny;
  397.       prev_nz = nz;
  398.       glNormal3f(nx,ny,nz);
  399.     }
  400.  
  401.     /* draw polygon/triangle/quad */
  402.     for (j=0; j<face->index_cnt; j++)
  403.       glVertex3f(PX(j),PY(j),PZ(j));
  404.  
  405.   }
  406.  
  407.   /* if glBegin was called call glEnd */
  408.   if (prev_index_cnt > 0)
  409.     glEnd();
  410. }
  411.  
  412.  
  413. GLfloat lw_object_radius(const lwObject *lwo)
  414. {
  415.   int i;
  416.   double max_radius = 0.0;
  417.  
  418.   for (i=0; i<lwo->vertex_cnt; i++) {
  419.     GLfloat *v = &lwo->vertex[i*3];
  420.     double r = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  421.     if (r > max_radius)
  422.       max_radius = r;
  423.   }
  424.   return sqrt(max_radius);
  425. }
  426.  
  427. void lw_object_scale(lwObject *lwo, GLfloat scale)
  428. {
  429.   int i;
  430.  
  431.   for (i=0; i<lwo->vertex_cnt; i++) {
  432.     lwo->vertex[i*3+0] *= scale;
  433.     lwo->vertex[i*3+1] *= scale;
  434.     lwo->vertex[i*3+2] *= scale;
  435.   }
  436. }
  437.  
  438.  
  439.