1 //********************************************************************************************
2 //*
3 //*    This file is part of Egoboo.
4 //*
5 //*    Egoboo is free software: you can redistribute it and/or modify it
6 //*    under the terms of the GNU General Public License as published by
7 //*    the Free Software Foundation, either version 3 of the License, or
8 //*    (at your option) any later version.
9 //*
10 //*    Egoboo is distributed in the hope that it will be useful, but
11 //*    WITHOUT ANY WARRANTY; without even the implied warranty of
12 //*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 //*    General Public License for more details.
14 //*
15 //*    You should have received a copy of the GNU General Public License
16 //*    along with Egoboo.  If not, see <http://www.gnu.org/licenses/>.
17 //*
18 //********************************************************************************************
19 
20 /// @file file_formats/mpd_file.c
21 /// @brief Functions for raw read and write access to the .mpd file type
22 /// @details
23 
24 #include "mpd_file.h"
25 #include "log.h"
26 
27 #include "egoboo_math.inl"
28 #include "egoboo_endian.h"
29 #include "egoboo_fileutil.h"
30 #include "egoboo_strutil.h"
31 #include "egoboo.h"
32 
33 //--------------------------------------------------------------------------------------------
34 //--------------------------------------------------------------------------------------------
35 
36 static mpd_info_t * mpd_info_ctor( mpd_info_t * pinfo );
37 static mpd_info_t * mpd_info_dtor( mpd_info_t * pinfo );
38 
39 static mpd_mem_t *  mpd_mem_ctor( mpd_mem_t * pmem );
40 static mpd_mem_t *  mpd_mem_dtor( mpd_mem_t * pmem );
41 static bool_t       mpd_mem_free( mpd_mem_t * pmem );
42 static bool_t       mpd_mem_alloc( mpd_mem_t * pmem, mpd_info_t * pinfo );
43 
44 //--------------------------------------------------------------------------------------------
45 //--------------------------------------------------------------------------------------------
46 
47 fvec3_t   map_twist_nrm[256];
48 Uint32    map_twist_y[256];            // For surface normal of mesh
49 Uint32    map_twist_x[256];
50 float     map_twistvel_x[256];            // For sliding down steep hills
51 float     map_twistvel_y[256];
52 float     map_twistvel_z[256];
53 Uint8     map_twist_flat[256];
54 
55 tile_definition_t tile_dict[MAXMESHTYPE];
56 
57 //--------------------------------------------------------------------------------------------
58 //--------------------------------------------------------------------------------------------
tile_dictionary_load_vfs(const char * filename,tile_definition_t dict[],size_t dict_size)59 void tile_dictionary_load_vfs( const char * filename, tile_definition_t dict[], size_t dict_size )
60 {
61     /// @details ZZ@> This function loads fan types for the terrain
62 
63     Uint32 cnt, entry, vertices, commandsize;
64     int numfantype, fantype, bigfantype;
65     int numcommand, command;
66     int itmp;
67     float ftmp;
68     vfs_FILE* fileread;
69 
70     if ( !VALID_CSTR( filename ) || NULL == dict || dict_size < 2 ) return;
71 
72     // Initialize all mesh types to 0
73     for ( entry = 0; entry < dict_size; entry++ )
74     {
75         dict[entry].numvertices = 0;
76         dict[entry].command_count = 0;
77     }
78 
79     // Open the file and go to it
80     fileread = vfs_openRead( filename );
81     if ( NULL == fileread )
82     {
83         log_error( "Cannot load the tile definitions \"%s\".\n", filename );
84         return;
85     }
86 
87     numfantype = fget_next_int( fileread );
88 
89     for ( fantype = 0; fantype < numfantype; fantype++ )
90     {
91         bigfantype = fantype + dict_size / 2;  // Duplicate for 64x64 tiles
92 
93         vertices = fget_next_int( fileread );
94         dict[fantype].numvertices = vertices;
95         dict[bigfantype].numvertices = vertices;  // Dupe
96 
97         for ( cnt = 0; cnt < vertices; cnt++ )
98         {
99             itmp = fget_next_int( fileread );
100 
101             ftmp = fget_next_float( fileread );
102             dict[fantype].u[cnt] = ftmp;
103             dict[bigfantype].u[cnt] = ftmp;  // Dupe
104 
105             ftmp = fget_next_float( fileread );
106             dict[fantype].v[cnt] = ftmp;
107             dict[bigfantype].v[cnt] = ftmp;  // Dupe
108         }
109 
110         numcommand = fget_next_int( fileread );
111         dict[fantype].command_count = numcommand;
112         dict[bigfantype].command_count = numcommand;  // Dupe
113 
114         for ( entry = 0, command = 0; command < numcommand; command++ )
115         {
116             commandsize = fget_next_int( fileread );
117             dict[fantype].command_entries[command] = commandsize;
118             dict[bigfantype].command_entries[command] = commandsize;  // Dupe
119 
120             for ( cnt = 0; cnt < commandsize; cnt++ )
121             {
122                 itmp = fget_next_int( fileread );
123                 dict[fantype].command_verts[entry] = itmp;
124                 dict[bigfantype].command_verts[entry] = itmp;  // Dupe
125 
126                 entry++;
127             }
128         }
129     }
130 
131     vfs_close( fileread );
132 
133     // Correct all of them silly texture positions for seamless tiling
134     for ( entry = 0; entry < dict_size / 2; entry++ )
135     {
136         for ( cnt = 0; cnt < dict[entry].numvertices; cnt++ )
137         {
138             dict[entry].u[cnt] = (( 0.6f / 32 ) + ( dict[entry].u[cnt] * 30.8f / 32 ) ) / 8;
139             dict[entry].v[cnt] = (( 0.6f / 32 ) + ( dict[entry].v[cnt] * 30.8f / 32 ) ) / 8;
140         }
141     }
142 
143     // Do for big tiles too
144     for ( /* nothing */; entry < dict_size; entry++ )
145     {
146         for ( cnt = 0; cnt < dict[entry].numvertices; cnt++ )
147         {
148             dict[entry].u[cnt] = (( 0.6f / 64 ) + ( dict[entry].u[cnt] * 62.8f / 64 ) ) / 4;
149             dict[entry].v[cnt] = (( 0.6f / 64 ) + ( dict[entry].v[cnt] * 62.8f / 64 ) ) / 4;
150         }
151     }
152 }
153 
154 //--------------------------------------------------------------------------------------------
155 //--------------------------------------------------------------------------------------------
mpd_ctor(mpd_t * pmesh)156 mpd_t * mpd_ctor( mpd_t * pmesh )
157 {
158     if ( NULL == pmesh ) return NULL;
159 
160     memset( pmesh, 0, sizeof( *pmesh ) );
161 
162     if ( NULL == mpd_mem_ctor( &( pmesh->mem ) ) ) return NULL;
163     if ( NULL == mpd_info_ctor( &( pmesh->info ) ) ) return NULL;
164 
165     return pmesh;
166 }
167 
168 //--------------------------------------------------------------------------------------------
mpd_dtor(mpd_t * pmesh)169 mpd_t * mpd_dtor( mpd_t * pmesh )
170 {
171     if ( NULL == pmesh ) return NULL;
172 
173     if ( NULL == mpd_mem_dtor( &( pmesh->mem ) ) ) return NULL;
174     if ( NULL == mpd_info_dtor( &( pmesh->info ) ) ) return NULL;
175 
176     return pmesh;
177 }
178 
179 //--------------------------------------------------------------------------------------------
mpd_free(mpd_t * pmesh)180 bool_t mpd_free( mpd_t * pmesh )
181 {
182     if ( NULL == pmesh ) return bfalse;
183 
184     mpd_mem_free( &( pmesh->mem ) );
185 
186     return btrue;
187 }
188 
189 //--------------------------------------------------------------------------------------------
mpd_load(const char * loadname,mpd_t * pmesh)190 mpd_t * mpd_load( const char *loadname, mpd_t * pmesh )
191 {
192     ///// @details ZZ@> This function loads the level.mpd file
193     FILE* fileread;
194     int itmp;
195     float ftmp;
196     Uint32 fan, cnt;
197     Uint32 tiles_count;
198     Uint8 btemp;
199 
200     mpd_info_t * pinfo;
201     mpd_mem_t  * pmem;
202 
203     if ( NULL == pmesh || INVALID_CSTR( loadname ) ) return pmesh;
204 
205     printf( "---- mpd_load(\"%s\",%p)\n", loadname, pmesh );
206 
207     pinfo = &( pmesh->info );
208     pmem  = &( pmesh->mem );
209 
210     fileread = fopen( loadname, "rb" );
211     if ( NULL == fileread )
212     {
213         log_warning( "mpd_load() - cannot find \"%s\"!!\n", loadname );
214         return NULL;
215     }
216 
217     fread( &itmp, 4, 1, fileread );
218     if ( MAPID != ( Uint32 )ENDIAN_INT32( itmp ) )
219     {
220         log_warning( "mpd_load() - this is not a valid level.mpd!!\n" );
221         fclose( fileread );
222         return NULL;
223     }
224 
225     // Read the number of vertices
226     fread( &itmp, 4, 1, fileread );  pinfo->vertcount   = ( int )ENDIAN_INT32( itmp );
227 
228     // grab the tiles in x and y
229     fread( &itmp, 4, 1, fileread );  pinfo->tiles_x = ( int )ENDIAN_INT32( itmp );
230     if ( pinfo->tiles_x >= MAXMESHTILEY )
231     {
232         mpd_dtor( pmesh );
233         log_warning( "mpd_load() - invalid mpd size. Mesh too large in x direction.\n" );
234         fclose( fileread );
235         return NULL;
236     }
237 
238     fread( &itmp, 4, 1, fileread );  pinfo->tiles_y = ( int )ENDIAN_INT32( itmp );
239     if ( pinfo->tiles_y >= MAXMESHTILEY )
240     {
241         mpd_dtor( pmesh );
242         log_warning( "mpd_load() - invalid mpd size. Mesh too large in y direction.\n" );
243         fclose( fileread );
244         return NULL;
245     }
246 
247     // allocate the mesh memory
248     if ( !mpd_mem_alloc( pmem, pinfo ) )
249     {
250         mpd_dtor( pmesh );
251         fclose( fileread );
252         log_warning( "mpd_load() - could not allocate memory for the mesh!!\n" );
253         return NULL;
254     }
255 
256     tiles_count = pinfo->tiles_x * pinfo->tiles_y;
257 
258     // Load fan data
259     for ( fan = 0; fan < tiles_count; fan++ )
260     {
261         fread( &itmp, 4, 1, fileread );
262         pmem->tile_list[fan].type = CLIP_TO_08BITS( ENDIAN_INT32( itmp ) >> 24 );
263         pmem->tile_list[fan].fx   = CLIP_TO_08BITS( ENDIAN_INT32( itmp ) >> 16 );
264         pmem->tile_list[fan].img  = CLIP_TO_16BITS( ENDIAN_INT32( itmp ) >>  0 );
265     }
266 
267     // Load twist data
268     for ( fan = 0; fan < tiles_count; fan++ )
269     {
270         fread( &itmp, 1, 1, fileread );
271         pmem->tile_list[fan].twist = ENDIAN_INT32( itmp );
272     }
273 
274     // Load vertex x data
275     for ( cnt = 0; cnt < pmem->vcount; cnt++ )
276     {
277         fread( &ftmp, 4, 1, fileread );
278         pmem->vlst[cnt].pos.x = ENDIAN_FLOAT( ftmp );
279     }
280 
281     // Load vertex y data
282     for ( cnt = 0; cnt < pmem->vcount; cnt++ )
283     {
284         fread( &ftmp, 4, 1, fileread );
285         pmem->vlst[cnt].pos.y = ENDIAN_FLOAT( ftmp );
286     }
287 
288     // Load vertex z data
289     for ( cnt = 0; cnt < pmem->vcount; cnt++ )
290     {
291         fread( &ftmp, 4, 1, fileread );
292         pmem->vlst[cnt].pos.z = ENDIAN_FLOAT( ftmp ) / 16.0f;  // Cartman uses 4 bit fixed point for Z
293     }
294 
295     // Load vertex a data
296     for ( cnt = 0; cnt < pmem->vcount; cnt++ )
297     {
298         fread( &btemp, 1, 1, fileread );
299         pmem->vlst[cnt].a = 0; // btemp;
300     }
301 
302     fclose( fileread );
303 
304     return pmesh;
305 }
306 
307 //--------------------------------------------------------------------------------------------
308 //--------------------------------------------------------------------------------------------
mpd_info_ctor(mpd_info_t * pinfo)309 mpd_info_t * mpd_info_ctor( mpd_info_t * pinfo )
310 {
311     if ( NULL == pinfo ) return pinfo;
312 
313     memset( pinfo, 0, sizeof( *pinfo ) );
314 
315     return pinfo;
316 }
317 
318 //--------------------------------------------------------------------------------------------
mpd_info_dtor(mpd_info_t * pinfo)319 mpd_info_t * mpd_info_dtor( mpd_info_t * pinfo )
320 {
321     if ( NULL == pinfo ) return NULL;
322 
323     memset( pinfo, 0, sizeof( *pinfo ) );
324 
325     return pinfo;
326 }
327 
328 //--------------------------------------------------------------------------------------------
329 //--------------------------------------------------------------------------------------------
mpd_mem_ctor(mpd_mem_t * pmem)330 mpd_mem_t * mpd_mem_ctor( mpd_mem_t * pmem )
331 {
332     if ( NULL == pmem ) return pmem;
333 
334     memset( pmem, 0, sizeof( *pmem ) );
335 
336     return pmem;
337 }
338 
339 //--------------------------------------------------------------------------------------------
mpd_mem_dtor(mpd_mem_t * pmem)340 mpd_mem_t * mpd_mem_dtor( mpd_mem_t * pmem )
341 {
342     if ( NULL == pmem ) return NULL;
343 
344     mpd_mem_free( pmem );
345     memset( pmem, 0, sizeof( *pmem ) );
346 
347     return pmem;
348 }
349 
350 //--------------------------------------------------------------------------------------------
mpd_mem_alloc(mpd_mem_t * pmem,mpd_info_t * pinfo)351 bool_t mpd_mem_alloc( mpd_mem_t * pmem, mpd_info_t * pinfo )
352 {
353     int tile_count;
354 
355     if ( NULL == pmem || NULL == pinfo || 0 == pinfo->vertcount ) return bfalse;
356 
357     // free any memory already allocated
358     if ( !mpd_mem_free( pmem ) ) return bfalse;
359 
360     if ( pinfo->vertcount > MESH_MAXTOTALVERTRICES )
361     {
362         log_warning( "mpd_mem_alloc() - mesh requires too much memory ( %d requested, but max is %d ). \n", pinfo->vertcount, MESH_MAXTOTALVERTRICES );
363         return bfalse;
364     }
365 
366     // allocate new memory
367     pmem->vlst = EGOBOO_NEW_ARY( mpd_vertex_t, pinfo->vertcount );
368     if ( NULL == pmem->vlst )
369     {
370         mpd_mem_free( pmem );
371         log_error( "mpd_mem_alloc() - reduce the maximum number of vertices! (Check MESH_MAXTOTALVERTRICES)\n" );
372         return bfalse;
373     }
374     pmem->vcount = pinfo->vertcount;
375 
376     tile_count = pinfo->tiles_x * pinfo->tiles_y;
377     pmem->tile_list  = EGOBOO_NEW_ARY( tile_info_t, tile_count );
378     if ( NULL == pmem->tile_list )
379     {
380         mpd_mem_free( pmem );
381         log_error( "mpd_mem_alloc() - not enough memory to allocate the tile info\n" );
382         return bfalse;
383     }
384     pmem->tile_count = tile_count;
385 
386     return btrue;
387 }
388 
389 //--------------------------------------------------------------------------------------------
mpd_mem_free(mpd_mem_t * pmem)390 bool_t mpd_mem_free( mpd_mem_t * pmem )
391 {
392     if ( NULL == pmem ) return bfalse;
393 
394     // free the memory
395     EGOBOO_DELETE_ARY( pmem->vlst );
396     pmem->vcount = 0;
397 
398     EGOBOO_DELETE_ARY( pmem->tile_list );
399     pmem->tile_count = 0;
400 
401     return btrue;
402 }
403 
404 //--------------------------------------------------------------------------------------------
405 //--------------------------------------------------------------------------------------------
cartman_get_twist(int x,int y)406 Uint8 cartman_get_twist( int x, int y )
407 {
408     Uint8 twist;
409 
410     // x and y should be from -7 to 8
411     if ( x < -7 ) x = -7;
412     if ( x > 8 ) x = 8;
413     if ( y < -7 ) y = -7;
414     if ( y > 8 ) y = 8;
415 
416     // Now between 0 and 15
417     x = x + 7;
418     y = y + 7;
419     twist = ( y << 4 ) + x;
420 
421     return twist;
422 }
423 
424 //--------------------------------------------------------------------------------------------
twist_to_normal(Uint8 twist,float v[],float slide)425 bool_t twist_to_normal( Uint8 twist, float v[], float slide )
426 {
427     int ix, iy;
428     float dx, dy;
429     float nx, ny, nz, nz2;
430     float diff_xy;
431 
432     if ( NULL == v ) return bfalse;
433 
434     diff_xy = 128.0f / slide;
435 
436     ix = ( twist >> 0 ) & 0x0f;
437     iy = ( twist >> 4 ) & 0x0f;
438     ix -= 7;
439     iy -= 7;
440 
441     dx = -ix / ( float )CARTMAN_FIXNUM * ( float )CARTMAN_SLOPE;
442     dy = iy / ( float )CARTMAN_FIXNUM * ( float )CARTMAN_SLOPE;
443 
444     // determine the square of the z normal
445     nz2 =  diff_xy * diff_xy / ( dx * dx + dy * dy + diff_xy * diff_xy );
446 
447     // determine the z normal
448     nz = 0.0f;
449     if ( nz2 > 0.0f )
450     {
451         nz = SQRT( nz2 );
452     }
453 
454     nx = - dx * nz / diff_xy;
455     ny = - dy * nz / diff_xy;
456 
457     v[0] = nx;
458     v[1] = ny;
459     v[2] = nz;
460 
461     return btrue;
462 }
463