2 * $Source: x:/prj/tech/libsrc/md/RCS/scale.c $
5 * $Date: 1997/07/03 04:26:20 $
7 * Model Library scaling routine
19 #define max(x,y) (((x)>(y))?(x):(y))
22 #define TEST_VERSION(fname,model) \
24 if (model->ver!=MD_CUR_VER) { \
26 strncpy(safename,model->name,8); \
28 CriticalMsg3("%s: model %s is old version %d",fname,safename,model->ver); \
33 #define TEST_VERSION(fname,model)
37 float radius_from_bbox(mxs_vector
*bmin
,mxs_vector
*bmax
)
42 mn2
= bmin
->x
*bmin
->x
;
43 mx2
= bmax
->x
*bmax
->x
;
47 mn2
= bmin
->y
*bmin
->y
;
48 mx2
= bmax
->y
*bmax
->y
;
52 mn2
= bmin
->z
*bmin
->z
;
53 mx2
= bmax
->z
*bmax
->z
;
56 // radius is dist from center to max point
61 // Scale a model according to the scaling vector s. The scaling is
62 // done in source space. If the model *dst is NULL, it allocates memory
64 // light is whether or not to retransform the lighting vectors. Depending,
65 // you may actually want it to be the same, plus it's the slowest thing to
67 mds_model
*md_scale_model(mds_model
*dst
,mds_model
*src
,mxs_vector
*s
,bool light
)
71 mxs_vector sn
; // normal scale factor
72 float sd
; // plane scale factor
76 TEST_VERSION("md_scale_model",src
);
78 // This is what normals get scaled by
86 dst
= Malloc(src
->mod_size
);
90 memcpy(dst
,src
,src
->mod_size
);
92 // Scale the bbox and pcen
93 mx_elmuleq_vec(&dst
->bmin
,s
);
94 mx_elmuleq_vec(&dst
->bmax
,s
);
95 mx_elmuleq_vec(&dst
->pcen
,s
);
97 // Recompute bounding sphere
98 dst
->radius
= radius_from_bbox(&dst
->bmin
,&dst
->bmax
);
100 // Recompute max pgon radius, by putting bounding
101 // box around it and shrinking it
102 dst
->max_pgon_radius
*= mx_mag_vec(s
);
104 // Scale the vhot lists
105 v
= md_vhot_list(dst
);
106 for (i
=dst
->vhots
;i
>0;--i
) {
107 mx_elmuleq_vec(&v
->v
,s
);
112 pt
= md_point_list(dst
);
113 for (i
=dst
->verts
;i
>0;--i
) {
114 mx_elmuleq_vec(pt
,s
);
118 // lights, norms and pgons and nodes
119 // are done per subobj
121 for (i
=0;i
<dst
->subobjs
;++i
) {
124 mds_subobj
*sb
= &(md_subobj_list(dst
)[i
]);
128 // trans.. gotta think about that...
129 // I think we just scale the offset
130 mx_elmuleq_vec(&(sb
->trans
.vec
),s
);
132 // These don't have to be normalized, but the d values
133 // need to be recomputed both in pgons and nodes
134 norm
= md_norm_list(dst
)+sb
->norm_start
;
135 for (j
=sb
->norm_num
;j
>0;--j
) {
136 mx_elmuleq_vec(norm
,&sn
);
145 lt
= md_light_list(dst
)+sb
->light_start
;
147 for (j
=sb
->light_num
;j
>0;--j
) {
149 l
.x
= X_NORM(lt
->norm
)*sn
.x
;
150 l
.y
= Y_NORM(lt
->norm
)*sn
.y
;
151 l
.z
= Z_NORM(lt
->norm
)*sn
.z
;
155 md_norm2light(&(lt
->norm
),&l
);
160 // Go through the nodes
162 n
= (uchar
*)dst
+ dst
->node_off
+ sb
->node_start
;
163 for (j
=sb
->node_num
;j
>0;--j
) {
167 mds_node_subobj
*node
= (mds_node_subobj
*)n
;
168 n
= (char *)(node
+1);
169 ++j
; // doesn't count
174 mds_node_vcall
*node
= (mds_node_vcall
*)n
;
176 n
= (char *)(node
+1);
181 mds_node_call
*node
= (mds_node_call
*)n
;
183 n
= (char *)(node
+1);
184 n
+= (node
->pgons_before
+node
->pgons_after
)*sizeof(short);
189 mds_node_split
*node
= (mds_node_split
*)n
;
191 n
= (char *)(node
+1);
192 n
+= (node
->pgons_before
+node
->pgons_after
)*sizeof(short);
197 mds_node_raw
*node
= (mds_node_raw
*)n
;
198 n
= (char *)(node
+1);
199 n
+= node
->num
*sizeof(short);
206 // Go through the polygon list
207 // and touch up the d values
208 pgon
= (mds_pgon
*)(dst
->pgon_off
+(uchar
*)dst
);
209 for (i
=dst
->pgons
;i
>0;--i
) {
212 next
= (uchar
*)pgon
;
213 next
+= sizeof(mds_pgon
);
214 next
+= 2*pgon
->num
*sizeof(ushort
);
215 if ( ((pgon
->type
)&MD_PGON_PRIM_MASK
)==MD_PGON_PRIM_TMAP
) {
216 next
+= pgon
->num
* sizeof(ushort
);
218 pgon
= (mds_pgon
*)next
;