]>
git.saurik.com Git - wxWidgets.git/blob - samples/opengl/penguin/lw.cpp
c2875d58875b972e45b68dbe54bdb5fad1a7b8ab
2 * Copyright (C) 1998 Janne Löf <jlof@mail.student.oulu.fi>
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.
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.
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.
30 #if !defined(__WXMAC__)
31 // these must be defined in the precompiled headers under CodeWarrior
33 #define wxUint32 unsigned int
44 #define MK_ID(a,b,c,d) ((((wxUint32)(a))<<24)| \
45 (((wxUint32)(b))<<16)| \
46 (((wxUint32)(c))<< 8)| \
49 #define ID_FORM MK_ID('F','O','R','M')
50 #define ID_LWOB MK_ID('L','W','O','B')
51 #define ID_PNTS MK_ID('P','N','T','S')
52 #define ID_SRFS MK_ID('S','R','F','S')
53 #define ID_SURF MK_ID('S','U','R','F')
54 #define ID_POLS MK_ID('P','O','L','S')
55 #define ID_COLR MK_ID('C','O','L','R')
57 static wxInt32
read_char(FILE *f
)
63 static wxInt32
read_short(FILE *f
)
65 // the execution path was not always correct
66 // when using the direct evaluation in the return statement
67 wxInt32 first
= read_char(f
) ;
68 wxInt32 second
= read_char(f
) ;
70 return (first
<<8) | second
;
73 static wxInt32
read_long(FILE *f
)
75 // the execution path was not always correct
76 // when using the direct evaluation in the return statement
77 wxInt32 first
= read_char(f
) ;
78 wxInt32 second
= read_char(f
) ;
79 wxInt32 third
= read_char(f
) ;
80 wxInt32 fourth
= read_char(f
) ;
81 return (first
<<24) | (second
<<16) | (third
<<8) | fourth
;
84 static GLfloat
read_float(FILE *f
)
86 wxInt32 x
= read_long(f
);
90 static int read_string(FILE *f
, char *s
)
96 if (cnt
< LW_MAX_NAME_LEN
)
99 s
[LW_MAX_NAME_LEN
-1] = 0;
102 /* if length of string (including \0) is odd skip another byte */
110 static void read_srfs(FILE *f
, int nbytes
, lwObject
*lwo
)
112 int guess_cnt
= lwo
->material_cnt
;
115 lwMaterial
*material
;
117 /* allocate more memory for materials if needed */
118 if (guess_cnt
<= lwo
->material_cnt
) {
119 guess_cnt
+= guess_cnt
/2 + 4;
120 lwo
->material
= (lwMaterial
*) realloc(lwo
->material
, sizeof(lwMaterial
)*guess_cnt
);
122 material
= lwo
->material
+ lwo
->material_cnt
++;
125 nbytes
-= read_string(f
,material
->name
);
132 lwo
->material
= (lwMaterial
*) realloc(lwo
->material
, sizeof(lwMaterial
)*lwo
->material_cnt
);
136 static void read_surf(FILE *f
, int nbytes
, lwObject
*lwo
)
139 char name
[LW_MAX_NAME_LEN
];
140 lwMaterial
*material
= NULL
;
142 /* read surface name */
143 nbytes
-= read_string(f
,name
);
146 for (i
=0; i
< lwo
->material_cnt
; i
++) {
147 if (strcmp(lwo
->material
[i
].name
,name
) == 0) {
148 material
= &lwo
->material
[i
];
155 int id
= read_long(f
);
156 int len
= read_short(f
);
157 nbytes
-= 6 + len
+ (len%2
);
161 material
->r
= read_char(f
) / 255.0;
162 material
->g
= read_char(f
) / 255.0;
163 material
->b
= read_char(f
) / 255.0;
164 read_char(f
); /* dummy */
167 fseek(f
, len
+(len%2
), SEEK_CUR
);
173 static void read_pols(FILE *f
, int nbytes
, lwObject
*lwo
)
175 int guess_cnt
= lwo
->face_cnt
;
181 /* allocate more memory for polygons if necessary */
182 if (guess_cnt
<= lwo
->face_cnt
) {
183 guess_cnt
+= guess_cnt
+ 4;
184 lwo
->face
= (lwFace
*) realloc((void*) lwo
->face
, sizeof(lwFace
)*guess_cnt
);
186 face
= lwo
->face
+ lwo
->face_cnt
++;
188 /* number of points in this face */
189 face
->index_cnt
= read_short(f
);
192 /* allocate space for points */
193 face
->index
= (int*) calloc(sizeof(int)*face
->index_cnt
,1);
196 for (i
=0; i
<face
->index_cnt
; i
++) {
197 face
->index
[i
] = read_short(f
);
201 /* read surface material */
202 face
->material
= read_short(f
);
205 /* skip over detail polygons */
206 if (face
->material
< 0) {
208 face
->material
= -face
->material
;
209 det_cnt
= read_short(f
);
211 while (det_cnt
-- > 0) {
212 int cnt
= read_short(f
);
213 fseek(f
, cnt
*2+2, SEEK_CUR
);
219 /* readjust to true size */
220 lwo
->face
= (lwFace
*) realloc(lwo
->face
, sizeof(lwFace
)*lwo
->face_cnt
);
225 static void read_pnts(FILE *f
, int nbytes
, lwObject
*lwo
)
228 lwo
->vertex_cnt
= nbytes
/ 12;
229 lwo
->vertex
= (float*) calloc(sizeof(GLfloat
)*lwo
->vertex_cnt
*3, 1);
230 for (i
=0; i
<lwo
->vertex_cnt
; i
++) {
231 lwo
->vertex
[i
*3+0] = read_float(f
);
232 lwo
->vertex
[i
*3+1] = read_float(f
);
233 lwo
->vertex
[i
*3+2] = read_float(f
);
242 int lw_is_lwobject(const char *lw_file
)
244 FILE *f
= fopen(lw_file
, "rb");
246 wxInt32 form
= read_long(f
);
247 wxInt32 nlen
= read_long(f
);
248 wxInt32 lwob
= read_long(f
);
250 if (form
== ID_FORM
&& nlen
!= 0 && lwob
== ID_LWOB
)
257 lwObject
*lw_object_read(const char *lw_file
)
260 lwObject
*lw_object
= NULL
;
262 wxInt32 form_bytes
= 0;
263 wxInt32 read_bytes
= 0;
266 f
= fopen(lw_file
, "rb");
271 /* check for headers */
272 if (read_long(f
) != ID_FORM
) {
276 form_bytes
= read_long(f
);
279 if (read_long(f
) != ID_LWOB
) {
284 /* create new lwObject */
285 lw_object
= (lwObject
*) calloc(sizeof(lwObject
),1);
288 while (read_bytes
< form_bytes
) {
289 wxInt32 id
= read_long(f
);
290 wxInt32 nbytes
= read_long(f
);
291 read_bytes
+= 8 + nbytes
+ (nbytes%2
);
295 read_pnts(f
, nbytes
, lw_object
);
298 read_pols(f
, nbytes
, lw_object
);
301 read_srfs(f
, nbytes
, lw_object
);
304 read_surf(f
, nbytes
, lw_object
);
307 fseek(f
, nbytes
+ (nbytes%2
), SEEK_CUR
);
317 void lw_object_free(lwObject
*lw_object
)
319 if (lw_object
->face
) {
321 for (i
=0; i
<lw_object
->face_cnt
; i
++)
322 free(lw_object
->face
[i
].index
);
323 free(lw_object
->face
);
325 free(lw_object
->material
);
326 free(lw_object
->vertex
);
334 #define PX(i) (lw_object->vertex[face->index[i]*3+0])
335 #define PY(i) (lw_object->vertex[face->index[i]*3+1])
336 #define PZ(i) (lw_object->vertex[face->index[i]*3+2])
337 void lw_object_show(const lwObject
*lw_object
)
340 int prev_index_cnt
= -1;
341 int prev_material
= -1;
346 for (i
=0; i
<lw_object
->face_cnt
; i
++) {
347 GLfloat ax
,ay
,az
,bx
,by
,bz
,nx
,ny
,nz
,r
;
348 const lwFace
*face
= lw_object
->face
+i
;
350 /* ignore faces with less than 3 points */
351 if (face
->index_cnt
< 3)
354 /* calculate normal */
359 bx
= PX(face
->index_cnt
-1) - PX(0);
360 by
= PY(face
->index_cnt
-1) - PY(0);
361 bz
= PZ(face
->index_cnt
-1) - PZ(0);
363 nx
= ay
* bz
- az
* by
;
364 ny
= az
* bx
- ax
* bz
;
365 nz
= ax
* by
- ay
* bx
;
367 r
= sqrt(nx
*nx
+ ny
*ny
+ nz
*nz
);
368 if (r
< 0.000001) /* avoid division by zero */
375 if (prev_index_cnt
!= face
->index_cnt
|| prev_index_cnt
> 4) {
376 if (prev_index_cnt
> 0) glEnd();
377 prev_index_cnt
= face
->index_cnt
;
378 switch (face
->index_cnt
) {
380 glBegin(GL_TRIANGLES
);
390 /* update material if necessary */
391 if (prev_material
!= face
->material
) {
392 prev_material
= face
->material
;
393 glColor3f(lw_object
->material
[face
->material
].r
,
394 lw_object
->material
[face
->material
].g
,
395 lw_object
->material
[face
->material
].b
);
398 /* update normal if necessary */
399 if (nx
!= prev_nx
|| ny
!= prev_ny
|| nz
!= prev_nz
) {
403 glNormal3f(nx
,ny
,nz
);
406 /* draw polygon/triangle/quad */
407 for (j
=0; j
<face
->index_cnt
; j
++)
408 glVertex3f(PX(j
),PY(j
),PZ(j
));
412 /* if glBegin was called call glEnd */
413 if (prev_index_cnt
> 0)
418 GLfloat
lw_object_radius(const lwObject
*lwo
)
421 double max_radius
= 0.0;
423 for (i
=0; i
<lwo
->vertex_cnt
; i
++) {
424 GLfloat
*v
= &lwo
->vertex
[i
*3];
425 double r
= v
[0]*v
[0] + v
[1]*v
[1] + v
[2]*v
[2];
429 return sqrt(max_radius
);
432 void lw_object_scale(lwObject
*lwo
, GLfloat scale
)
436 for (i
=0; i
<lwo
->vertex_cnt
; i
++) {
437 lwo
->vertex
[i
*3+0] *= scale
;
438 lwo
->vertex
[i
*3+1] *= scale
;
439 lwo
->vertex
[i
*3+2] *= scale
;