fix remaining polymodel alignment issues. Courtesy of Martin Schaffner <martin.schaffner@epfl.ch>
This commit is contained in:
parent
c5b5533fa0
commit
bd362aaebb
130
3d/interp.c
130
3d/interp.c
|
@ -1,4 +1,4 @@
|
|||
/* $Id: interp.c,v 1.11 2003-01-03 00:57:00 btb Exp $ */
|
||||
/* $Id: interp.c,v 1.12 2003-02-13 22:02:29 btb Exp $ */
|
||||
/*
|
||||
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
||||
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
||||
|
@ -40,7 +40,7 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#endif
|
||||
|
||||
#ifdef RCS
|
||||
static char rcsid[] = "$Id: interp.c,v 1.11 2003-01-03 00:57:00 btb Exp $";
|
||||
static char rcsid[] = "$Id: interp.c,v 1.12 2003-02-13 22:02:29 btb Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -222,63 +222,22 @@ void swap_polygon_model_data(ubyte *data)
|
|||
#endif
|
||||
|
||||
#ifdef WORDS_NEED_ALIGNMENT
|
||||
|
||||
#include <string.h> // for memcpy
|
||||
|
||||
typedef struct chunk { // pointer-thing to next chunk of model_data
|
||||
ubyte *old_base; // where the offset sets off from (relative to beginning of model_data)
|
||||
ubyte *new_base; // where the base is in the aligned structure
|
||||
short offset; // how much to add to base to get the address of the offset
|
||||
short correction; // how much the value of the offset must be shifted for alignment
|
||||
} chunk;
|
||||
|
||||
ubyte * old_dest(chunk o) // return where the chunk is (in unaligned structure)
|
||||
void add_chunk(ubyte *old_base, ubyte *new_base, int offset,
|
||||
chunk *chunk_list, int *no_chunks)
|
||||
{
|
||||
return o.old_base + INTEL_SHORT(w(o.old_base + o.offset));
|
||||
}
|
||||
|
||||
ubyte * new_dest(chunk o) // return where the chunk is (in aligned structure)
|
||||
{
|
||||
return o.new_base + INTEL_SHORT(w(o.old_base + o.offset)) + o.correction;
|
||||
}
|
||||
|
||||
#define MAX_CHUNKS 100 // increase if insufficent
|
||||
|
||||
int no_chunks; // the number of chunks currently in array
|
||||
chunk *chunk_list;
|
||||
|
||||
void add_chunk(ubyte *old_base, ubyte *new_base, int offset) {
|
||||
Assert(no_chunks + 1 < MAX_CHUNKS); //increase MAX_CHUNKS if you get this
|
||||
chunk_list[no_chunks].old_base = old_base;
|
||||
chunk_list[no_chunks].new_base = new_base;
|
||||
chunk_list[no_chunks].offset = offset;
|
||||
chunk_list[no_chunks].correction = 0;
|
||||
no_chunks++;
|
||||
}
|
||||
|
||||
chunk get_first_chunk() // return chunk (from old structure) with smallest address, removing it from array
|
||||
{
|
||||
int i, first_index = 0;
|
||||
chunk first;
|
||||
|
||||
Assert(no_chunks >= 1);
|
||||
// find index of chunk with smallest address:
|
||||
for (i = 1; i < no_chunks; i++)
|
||||
if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index]))
|
||||
first_index = i;
|
||||
// assign it:
|
||||
first = chunk_list[first_index];
|
||||
// remove it from array:
|
||||
no_chunks--;
|
||||
for (i = first_index; i < no_chunks; i++)
|
||||
chunk_list[i] = chunk_list[i + 1];
|
||||
return first;
|
||||
Assert(*no_chunks + 1 < MAX_CHUNKS); //increase MAX_CHUNKS if you get this
|
||||
chunk_list[*no_chunks].old_base = old_base;
|
||||
chunk_list[*no_chunks].new_base = new_base;
|
||||
chunk_list[*no_chunks].offset = offset;
|
||||
chunk_list[*no_chunks].correction = 0;
|
||||
(*no_chunks)++;
|
||||
}
|
||||
|
||||
/*
|
||||
* find out what chunks the chunk "data" points to, return length of current chunk
|
||||
* finds what chunks the data points to, adds them to the chunk_list,
|
||||
* and returns the length of the current chunk
|
||||
*/
|
||||
int get_chunks(ubyte *data, ubyte *new_data)
|
||||
int get_chunks(ubyte *data, ubyte *new_data, chunk *list, int *no)
|
||||
{
|
||||
short n;
|
||||
ubyte *p = data;
|
||||
|
@ -302,15 +261,15 @@ int get_chunks(ubyte *data, ubyte *new_data)
|
|||
p += 30 + ((n&~1)+1)*2 + n*12;
|
||||
break;
|
||||
case OP_SORTNORM:
|
||||
add_chunk(p, p - data + new_data, 28);
|
||||
add_chunk(p, p - data + new_data, 30);
|
||||
add_chunk(p, p - data + new_data, 28, list, no);
|
||||
add_chunk(p, p - data + new_data, 30, list, no);
|
||||
p += 32;
|
||||
break;
|
||||
case OP_RODBM:
|
||||
p+=36;
|
||||
break;
|
||||
case OP_SUBCALL:
|
||||
add_chunk(p, p - data + new_data, 16);
|
||||
add_chunk(p, p - data + new_data, 16, list, no);
|
||||
p+=20;
|
||||
break;
|
||||
case OP_GLOW:
|
||||
|
@ -322,63 +281,6 @@ int get_chunks(ubyte *data, ubyte *new_data)
|
|||
}
|
||||
return p + 2 - data;
|
||||
}
|
||||
|
||||
#define SHIFT_SPACE 500 // increase if insufficent
|
||||
|
||||
void align_polygon_model_data(polymodel *pm)
|
||||
{
|
||||
int i, chunk_len;
|
||||
int total_correction = 0;
|
||||
ubyte *cur_old, *cur_new;
|
||||
chunk cur_ch;
|
||||
chunk cl[MAX_CHUNKS]; // we need the chunk_list only in this function
|
||||
int tmp_size = pm->model_data_size + SHIFT_SPACE;
|
||||
ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data
|
||||
|
||||
Assert(tmp != NULL);
|
||||
chunk_list = cl; // so other functions can access it
|
||||
no_chunks = 0;
|
||||
//start with first chunk (is always aligned!)
|
||||
cur_old = pm->model_data;
|
||||
cur_new = tmp;
|
||||
chunk_len = get_chunks(cur_old, cur_new);
|
||||
memcpy(cur_new, cur_old, chunk_len);
|
||||
while (no_chunks > 0) {
|
||||
cur_ch = get_first_chunk();
|
||||
if ((u_int32_t)new_dest(cur_ch) % 4L != 0) { // if (new) address unaligned
|
||||
short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L; // how much to align
|
||||
|
||||
// correct chunks' addresses
|
||||
cur_ch.correction += to_shift;
|
||||
for (i = 0; i < no_chunks; i++)
|
||||
chunk_list[i].correction += to_shift;
|
||||
total_correction += to_shift;
|
||||
Assert((u_int32_t)new_dest(cur_ch) % 4L == 0);
|
||||
Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE
|
||||
}
|
||||
//write (corrected) chunk for current chunk:
|
||||
w(cur_ch.new_base + cur_ch.offset)
|
||||
= INTEL_SHORT(cur_ch.correction
|
||||
+ INTEL_SHORT(w(cur_ch.old_base + cur_ch.offset)));
|
||||
//write (correctly aligned) chunk:
|
||||
cur_old = old_dest(cur_ch);
|
||||
cur_new = new_dest(cur_ch);
|
||||
chunk_len = get_chunks(cur_old, cur_new);
|
||||
memcpy(cur_new, cur_old, chunk_len);
|
||||
//correct submodel_ptr's for pm, too
|
||||
for (i = 0; i < MAX_SUBMODELS; i++)
|
||||
if (pm->model_data + pm->submodel_ptrs[i] >= cur_old
|
||||
&& pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len)
|
||||
pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data);
|
||||
}
|
||||
d_free(pm->model_data);
|
||||
pm->model_data_size += total_correction;
|
||||
pm->model_data = d_malloc(pm->model_data_size);
|
||||
Assert(pm->model_data != NULL);
|
||||
memcpy(pm->model_data, tmp, pm->model_data_size);
|
||||
d_free(tmp);
|
||||
}
|
||||
|
||||
#endif //def WORDS_NEED_ALIGNMENT
|
||||
|
||||
void verify(ubyte *data)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: interp.h,v 1.4 2003-01-22 00:54:13 btb Exp $ */
|
||||
/* $Id: interp.h,v 1.5 2003-02-13 22:02:29 btb Exp $ */
|
||||
/*
|
||||
*
|
||||
* took out functions declarations from include/3d.h
|
||||
|
@ -42,4 +42,27 @@ void g3_remap_interp_colors(void);
|
|||
void swap_polygon_model_data(ubyte *data);
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_NEED_ALIGNMENT
|
||||
/*
|
||||
* A chunk struct (as used for alignment) contains all relevant data
|
||||
* concerning a piece of data that may need to be aligned.
|
||||
* To align it, we need to copy it to an aligned position,
|
||||
* and update all pointers to it.
|
||||
* (Those pointers are actually offsets
|
||||
* relative to start of model_data) to it.
|
||||
*/
|
||||
typedef struct chunk {
|
||||
ubyte *old_base; // where the offset sets off from (relative to beginning of model_data)
|
||||
ubyte *new_base; // where the base is in the aligned structure
|
||||
short offset; // how much to add to base to get the address of the offset
|
||||
short correction; // how much the value of the offset must be shifted for alignment
|
||||
} chunk;
|
||||
#define MAX_CHUNKS 100 // increase if insufficent
|
||||
/*
|
||||
* finds what chunks the data points to, adds them to the chunk_list,
|
||||
* and returns the length of the current chunk
|
||||
*/
|
||||
int get_chunks(ubyte *data, ubyte *new_data, chunk *list, int *no);
|
||||
#endif //def WORDS_NEED_ALIGNMENT
|
||||
|
||||
#endif //_INTERP_H
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: polyobj.c,v 1.10 2003-01-03 00:56:33 btb Exp $ */
|
||||
/* $Id: polyobj.c,v 1.11 2003-02-13 22:02:29 btb Exp $ */
|
||||
/*
|
||||
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
|
||||
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
|
||||
|
@ -17,7 +17,7 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#endif
|
||||
|
||||
#ifdef RCS
|
||||
static char rcsid[] = "$Id: polyobj.c,v 1.10 2003-01-03 00:56:33 btb Exp $";
|
||||
static char rcsid[] = "$Id: polyobj.c,v 1.11 2003-02-13 22:02:29 btb Exp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -226,6 +226,89 @@ void robot_set_angles(robot_info *r,polymodel *pm,vms_angvec angs[N_ANIM_STATES]
|
|||
|
||||
#define DEBUG_LEVEL CON_NORMAL
|
||||
|
||||
#ifdef WORDS_NEED_ALIGNMENT
|
||||
ubyte * old_dest(chunk o) // return where chunk is (in unaligned struct)
|
||||
{
|
||||
return o.old_base + INTEL_SHORT(*((short *)(o.old_base + o.offset)));
|
||||
}
|
||||
ubyte * new_dest(chunk o) // return where chunk is (in aligned struct)
|
||||
{
|
||||
return o.new_base + INTEL_SHORT(*((short *)(o.old_base + o.offset))) + o.correction;
|
||||
}
|
||||
/*
|
||||
* find chunk with smallest address
|
||||
*/
|
||||
int get_first_chunks_index(chunk *chunk_list, int no_chunks)
|
||||
{
|
||||
int i, first_index = 0;
|
||||
Assert(no_chunks >= 1);
|
||||
for (i = 1; i < no_chunks; i++)
|
||||
if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index]))
|
||||
first_index = i;
|
||||
return first_index;
|
||||
}
|
||||
#define SHIFT_SPACE 500 // increase if insufficent
|
||||
|
||||
void align_polygon_model_data(polymodel *pm)
|
||||
{
|
||||
int i, chunk_len;
|
||||
int total_correction = 0;
|
||||
ubyte *cur_old, *cur_new;
|
||||
chunk cur_ch;
|
||||
chunk ch_list[MAX_CHUNKS];
|
||||
int no_chunks = 0;
|
||||
int tmp_size = pm->model_data_size + SHIFT_SPACE;
|
||||
ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data
|
||||
|
||||
Assert(tmp != NULL);
|
||||
//start with first chunk (is always aligned!)
|
||||
cur_old = pm->model_data;
|
||||
cur_new = tmp;
|
||||
chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
|
||||
memcpy(cur_new, cur_old, chunk_len);
|
||||
while (no_chunks > 0) {
|
||||
int first_index = get_first_chunks_index(ch_list, no_chunks);
|
||||
cur_ch = ch_list[first_index];
|
||||
// remove first chunk from array:
|
||||
no_chunks--;
|
||||
for (i = first_index; i < no_chunks; i++)
|
||||
ch_list[i] = ch_list[i + 1];
|
||||
// if (new) address unaligned:
|
||||
if ((u_int32_t)new_dest(cur_ch) % 4L != 0) {
|
||||
// calculate how much to move to be aligned
|
||||
short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L;
|
||||
// correct chunks' addresses
|
||||
cur_ch.correction += to_shift;
|
||||
for (i = 0; i < no_chunks; i++)
|
||||
ch_list[i].correction += to_shift;
|
||||
total_correction += to_shift;
|
||||
Assert((u_int32_t)new_dest(cur_ch) % 4L == 0);
|
||||
Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE
|
||||
}
|
||||
//write (corrected) chunk for current chunk:
|
||||
*((short *)(cur_ch.new_base + cur_ch.offset))
|
||||
= INTEL_SHORT(cur_ch.correction
|
||||
+ INTEL_SHORT(*((short *)(cur_ch.old_base + cur_ch.offset))));
|
||||
//write (correctly aligned) chunk:
|
||||
cur_old = old_dest(cur_ch);
|
||||
cur_new = new_dest(cur_ch);
|
||||
chunk_len = get_chunks(cur_old, cur_new, ch_list, &no_chunks);
|
||||
memcpy(cur_new, cur_old, chunk_len);
|
||||
//correct submodel_ptr's for pm, too
|
||||
for (i = 0; i < MAX_SUBMODELS; i++)
|
||||
if (pm->model_data + pm->submodel_ptrs[i] >= cur_old
|
||||
&& pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len)
|
||||
pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data);
|
||||
}
|
||||
d_free(pm->model_data);
|
||||
pm->model_data_size += total_correction;
|
||||
pm->model_data = d_malloc(pm->model_data_size);
|
||||
Assert(pm->model_data != NULL);
|
||||
memcpy(pm->model_data, tmp, pm->model_data_size);
|
||||
d_free(tmp);
|
||||
}
|
||||
#endif //def WORDS_NEED_ALIGNMENT
|
||||
|
||||
//reads a binary file containing a 3d model
|
||||
polymodel *read_model_file(polymodel *pm,char *filename,robot_info *r)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue