FS2_Open
Open source remastering of the Freespace 2 engine
modeloctant.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include <math.h>
14 
15 #define MODEL_LIB
16 
17 #include "cmdline/cmdline.h"
18 #include "math/vecmat.h"
19 #include "model/model.h"
20 #include "model/modelsinc.h"
21 
22 extern void model_allocate_interp_data(int n_verts, int n_norms, int n_list_verts = 0);
23 
24 
25 // returns 1 if a point is in an octant.
27 {
28  if ( vert->xyz.x < oct->min.xyz.x ) return 0;
29  if ( vert->xyz.x > oct->max.xyz.x ) return 0;
30 
31  if ( vert->xyz.y < oct->min.xyz.y ) return 0;
32  if ( vert->xyz.y > oct->max.xyz.y ) return 0;
33 
34  if ( vert->xyz.z < oct->min.xyz.z) return 0;
35  if ( vert->xyz.z > oct->max.xyz.z) return 0;
36 
37  return 1;
38 }
39 
40 
42 {
43  int i, j, n;
44  shield_tri *tri;
45 
46  n = 0;
47 
48  // Scan all the triangles in the mesh to find how many tris there are.
49  for (i=0; i<pm->shield.ntris; i++ ) {
50 
51  tri = &pm->shield.tris[i];
52 
53  for (j=0; j<3; j++ ) {
54  if ( point_in_octant( pm, oct, &pm->shield.verts[tri->verts[j]].pos )) {
55  n++;
56  break;
57  }
58  }
59  }
60 
61  //mprintf(( "Octant has %d shield polys in it\n", n ));
62 
63  oct->nshield_tris = n;
64 
65  // if we don't have any shield polys then don't bother continuing - taylor
66  if (oct->nshield_tris <= 0) {
67  oct->shield_tris = NULL;
68  return;
69  }
70 
71  oct->shield_tris = (shield_tri **)vm_malloc( sizeof(shield_tri *) * oct->nshield_tris );
72  Assert(oct->shield_tris!=NULL);
73 
74  n = 0;
75 
76  // Rescan all the triangles in the mesh.
77  for (i=0; i<pm->shield.ntris; i++ ) {
78 
79  tri = &pm->shield.tris[i];
80 
81  for (j=0; j<3; j++ ) {
82  if ( point_in_octant( pm, oct, &pm->shield.verts[tri->verts[j]].pos )) {
83  oct->shield_tris[n++] = tri;
84  break;
85  }
86  }
87  }
88 
89  Assert( oct->nshield_tris == n );
90 }
91 
92 
93 void moff_defpoints(ubyte * p, int just_count)
94 {
95  int n;
96  int nverts = w(p+8);
97  int offset = w(p+16);
98  int nnorms = 0;
99 
100  // if we are just counting then we don't need to be here
101  if (just_count)
102  return;
103 
104  ubyte * normcount = p+20;
105  vec3d *src = vp(p+offset);
106 
107  // make sure we have enough space allocated for the new data
108  for (n = 0; n < nverts; n++) {
109  nnorms += normcount[n];
110  }
111 
112  model_allocate_interp_data( nverts, nnorms );
113 
114  Assert( Interp_verts != NULL );
115 
116  for (n=0; n<nverts; n++ ) {
117  Interp_verts[n] = src;
118 
119  src += normcount[n]+1;
120  }
121 }
122 
123 
124 
125 // Textured Poly
126 // +0 int id
127 // +4 int size
128 // +8 vec3d normal
129 // +20 vec3d center
130 // +32 float radius
131 // +36 int nverts
132 // +40 int tmap_num
133 // +44 nverts*(model_tmap_vert) vertlist (n,u,v)
134 void moff_tmappoly(ubyte * p, polymodel * pm, model_octant * oct, int just_count )
135 {
136  int i, nv;
137  model_tmap_vert *verts;
138 
139  nv = w(p+36);
140  if ( nv < 0 ) return;
141 
142  verts = (model_tmap_vert *)(p+44);
143 
144  if ( (pm->version < 2003) && !just_count ) {
145  // Set the "normal_point" part of field to be the center of the polygon
146  vec3d center_point;
147  vm_vec_zero( &center_point );
148 
149  Assert( Interp_verts != NULL );
150 
151  for (i=0;i<nv;i++) {
152  vm_vec_add2( &center_point, Interp_verts[verts[i].vertnum] );
153  }
154 
155  center_point.xyz.x /= nv;
156  center_point.xyz.y /= nv;
157  center_point.xyz.z /= nv;
158 
159  *vp(p+20) = center_point;
160 
161  float rad = 0.0f;
162 
163  for (i=0;i<nv;i++) {
164  float dist = vm_vec_dist( &center_point, Interp_verts[verts[i].vertnum] );
165  if ( dist > rad ) {
166  rad = dist;
167  }
168  }
169  fl(p+32) = rad;
170  }
171 
172  // Put each face into a particular octant
173  if ( point_in_octant( pm, oct, vp(p+20) ) ) {
174  if (just_count)
175  oct->nverts++;
176  else
177  oct->verts[oct->nverts++] = vp(p+20);
178  return;
179  }
180 }
181 
182 
183 // Flat Poly
184 // +0 int id
185 // +4 int size
186 // +8 vec3d normal
187 // +20 vec3d center
188 // +32 float radius
189 // +36 int nverts
190 // +40 byte red
191 // +41 byte green
192 // +42 byte blue
193 // +43 byte pad
194 // +44 nverts*int vertlist
195 void moff_flatpoly(ubyte * p, polymodel * pm, model_octant * oct, int just_count )
196 {
197  int i, nv;
198  short *verts;
199 
200  nv = w(p+36);
201  if ( nv < 0 ) return;
202 
203  verts = (short *)(p+44);
204 
205  if ( (pm->version < 2003) && !just_count ) {
206  // Set the "normal_point" part of field to be the center of the polygon
207  vec3d center_point;
208  vm_vec_zero( &center_point );
209 
210  Assert( Interp_verts != NULL );
211 
212  for (i=0;i<nv;i++) {
213  vm_vec_add2( &center_point, Interp_verts[verts[i*2]] );
214  }
215 
216  center_point.xyz.x /= nv;
217  center_point.xyz.y /= nv;
218  center_point.xyz.z /= nv;
219 
220  *vp(p+20) = center_point;
221 
222  float rad = 0.0f;
223 
224  for (i=0;i<nv;i++) {
225  float dist = vm_vec_dist( &center_point, Interp_verts[verts[i*2]] );
226  if ( dist > rad ) {
227  rad = dist;
228  }
229  }
230  fl(p+32) = rad;
231  }
232 
233  // Put each face's center point into a particular octant
234  if ( point_in_octant( pm, oct, vp(p+20) ) ) {
235  if (just_count)
236  oct->nverts++;
237  else
238  oct->verts[oct->nverts++] = vp(p+20);
239  }
240 }
241 
242 
243 
244 int model_octant_find_faces_sub(polymodel * pm, model_octant * oct, void *model_ptr, int just_count )
245 {
246  ubyte *p = (ubyte *)model_ptr;
247  int chunk_type, chunk_size;
248 
249  chunk_type = w(p);
250  chunk_size = w(p+4);
251 
252  while (chunk_type != OP_EOF) {
253 
254  switch (chunk_type) {
255  case OP_DEFPOINTS:
256  moff_defpoints(p, just_count);
257  break;
258  case OP_FLATPOLY: moff_flatpoly(p, pm, oct, just_count ); break;
259  case OP_TMAPPOLY: moff_tmappoly(p, pm, oct, just_count ); break;
260  case OP_SORTNORM: {
261  int frontlist = w(p+36);
262  int backlist = w(p+40);
263  int prelist = w(p+44);
264  int postlist = w(p+48);
265  int onlist = w(p+52);
266 
267  if (prelist) model_octant_find_faces_sub(pm,oct,p+prelist,just_count);
268  if (backlist) model_octant_find_faces_sub(pm,oct,p+backlist,just_count);
269  if (onlist) model_octant_find_faces_sub(pm,oct,p+onlist,just_count);
270  if (frontlist) model_octant_find_faces_sub(pm,oct,p+frontlist,just_count);
271  if (postlist) model_octant_find_faces_sub(pm,oct,p+postlist,just_count);
272  }
273  break;
274  case OP_BOUNDBOX: break;
275  default:
276  mprintf(( "Bad chunk type %d, len=%d in model_octant_find_faces_sub\n", chunk_type, chunk_size ));
277  Int3(); // Bad chunk type!
278  return 0;
279  }
280  p += chunk_size;
281  chunk_type = w(p);
282  chunk_size = w(p+4);
283  }
284  return 1;
285 }
286 
287 
289 {
290  ubyte *p;
291  int submodel_num = pm->detail[0];
292 
293  p = pm->submodel[submodel_num].bsp_data;
294 
295  oct->nverts = 0;
296  model_octant_find_faces_sub(pm, oct, p, 1 );
297 
298  if ( oct->nverts < 1 ) {
299  oct->nverts = 0;
300  oct->verts = NULL;
301  return;
302  }
303 
304  oct->verts = (vec3d **)vm_malloc( sizeof(vec3d *) * oct->nverts );
305  Assert(oct->verts!=NULL);
306 
307  oct->nverts = 0;
308  model_octant_find_faces_sub(pm, oct, p, 0 );
309 
310 // mprintf(( "Octant has %d faces\n", oct->nfaces ));
311 }
312 
313 
314 // Creates the octants for a given polygon model
316 {
317  vec3d min, max, center;
318  int i, x, y, z;
319 
320  min = pm->mins;
321  max = pm->maxs;
322 
323  vm_vec_avg( &center, &min, &max );
324 
325  for (i=0; i<8; i++ ) {
326  x = i & 4;
327  y = i & 2;
328  z = i & 1;
329 
330  if ( x ) {
331  pm->octants[i].max.xyz.x = max.xyz.x;
332  pm->octants[i].min.xyz.x = center.xyz.x;
333  } else {
334  pm->octants[i].max.xyz.x = center.xyz.x;
335  pm->octants[i].min.xyz.x = min.xyz.x;
336  }
337 
338  if ( y ) {
339  pm->octants[i].max.xyz.y = max.xyz.y;
340  pm->octants[i].min.xyz.y = center.xyz.y;
341  } else {
342  pm->octants[i].max.xyz.y = center.xyz.y;
343  pm->octants[i].min.xyz.y = min.xyz.y;
344  }
345 
346  if ( z ) {
347  pm->octants[i].max.xyz.z = max.xyz.z;
348  pm->octants[i].min.xyz.z = center.xyz.z;
349  } else {
350  pm->octants[i].max.xyz.z = center.xyz.z;
351  pm->octants[i].min.xyz.z = min.xyz.z;
352  }
353 
354  model_octant_find_shields( pm, &pm->octants[i] );
355  model_octant_find_faces( pm, &pm->octants[i] );
356 
357  }
358 
359 }
360 
361 
362 // frees the memory the octants use for a given polygon model
364 {
365  int i;
366 
367  for (i=0; i<8; i++ ) {
368  model_octant * oct = &pm->octants[i];
369 
370  if ( oct->verts ) {
371  vm_free(oct->verts);
372  oct->verts = NULL;
373  }
374 
375  if ( oct->shield_tris ) {
376  vm_free( oct->shield_tris );
377  oct->shield_tris = NULL;
378  }
379 
380  }
381 }
382 
383 
384 // Returns which octant point pnt is closet to. This will always return
385 // a valid octant (0-7) since the point doesn't have to be in an octant.
386 // If model_orient and/or model_pos are NULL, pnt is assumed to already
387 // be rotated into the model's local coordinates.
388 // If oct is not null, it will be filled in with a pointer to the octant
389 // data.
390 int model_which_octant_distant_many( vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, polymodel **pm, int *octs)
391 {
392  vec3d tempv, rotpnt;
393 
394  *pm = model_get(model_num);
395 
396  if ( model_orient && model_pos ) {
397  // First, rotate pnt into the model's frame of reference.
398  vm_vec_sub( &tempv, pnt, model_pos );
399  vm_vec_rotate( &rotpnt, &tempv, model_orient );
400  } else {
401  rotpnt = *pnt;
402  }
403 
404  vec3d center;
405  vm_vec_avg( &center, &((*pm)->mins), &((*pm)->maxs ));
406  int i, x, y, z;
407 
408  if ( rotpnt.xyz.x > center.xyz.x ) x = 1; else x = 0;
409  if ( rotpnt.xyz.y > center.xyz.y ) y = 1; else y = 0;
410  if ( rotpnt.xyz.z > center.xyz.z ) z = 1; else z = 0;
411 
412  i = ( (x<<2) | (y<<1) | z );
413 
414  octs[0] = i;
415  octs[1] = i ^ 4; // Adjacent octant in x dimension
416  octs[2] = i ^ 2; // Adjacent octant in y dimension
417  octs[3] = i ^ 1; // Adjacent octant in z dimension
418 
419  return i;
420 }
421 
422 
423 // Returns which octant point pnt is closet to. This will always return
424 // a valid octant (0-7) since the point doesn't have to be in an octant.
425 // If model_orient and/or model_pos are NULL, pnt is assumed to already
426 // be rotated into the model's local coordinates.
427 // If oct is not null, it will be filled in with a pointer to the octant
428 // data.
429 int model_which_octant_distant( vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, model_octant **oct )
430 {
431  polymodel * pm;
432  vec3d tempv, rotpnt;
433 
434  pm = model_get(model_num);
435 
436  if ( model_orient && model_pos ) {
437  // First, rotate pnt into the model's frame of reference.
438  vm_vec_sub( &tempv, pnt, model_pos );
439  vm_vec_rotate( &rotpnt, &tempv, model_orient );
440  } else {
441  rotpnt = *pnt;
442  }
443 
444  vec3d center;
445  vm_vec_avg( &center, &pm->mins, &pm->maxs );
446  int i, x, y, z;
447 
448  if ( rotpnt.xyz.x > center.xyz.x ) x = 1; else x = 0;
449  if ( rotpnt.xyz.y > center.xyz.y ) y = 1; else y = 0;
450  if ( rotpnt.xyz.z > center.xyz.z ) z = 1; else z = 0;
451 
452  i = ( (x<<2) | (y<<1) | z );
453 
454  if ( oct )
455  *oct = &pm->octants[i];
456 
457  return i;
458 }
459 
460 
461 
462 // Returns which octant point pnt is in. This might return
463 // -1 if the point isn't in any octant.
464 // If model_orient and/or model_pos are NULL, pnt is assumed to already
465 // be rotated into the model's local coordinates.
466 // If oct is not null, it will be filled in with a pointer to the octant
467 // data. Or NULL if the pnt isn't in the octant.
468 int model_which_octant( vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, model_octant **oct )
469 {
470  polymodel * pm;
471  vec3d tempv, rotpnt;
472 
473  pm = model_get(model_num);
474 
475  if ( model_orient && model_pos ) {
476  // First, rotate pnt into the model's frame of reference.
477  vm_vec_sub( &tempv, pnt, model_pos );
478  vm_vec_rotate( &rotpnt, &tempv, model_orient );
479  } else {
480  rotpnt = *pnt;
481  }
482 
483  vec3d center;
484  vm_vec_avg( &center, &pm->mins, &pm->maxs );
485  int i, x, y, z;
486 
487  if ( rotpnt.xyz.x > center.xyz.x ) x = 1; else x = 0;
488  if ( rotpnt.xyz.y > center.xyz.y ) y = 1; else y = 0;
489  if ( rotpnt.xyz.z > center.xyz.z ) z = 1; else z = 0;
490 
491  i = (x<<2) | (y<<1) | z;
492 
493  if ( point_in_octant( pm, &pm->octants[i], &rotpnt ) ) {
494  if ( oct )
495  *oct = &pm->octants[i];
496  return i;
497  }
498 
499  if ( oct )
500  *oct = NULL;
501 
502  return -1;
503 }
vec3d ** verts
Definition: model.h:587
bsp_info * submodel
Definition: model.h:764
vec3d ** Interp_verts
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
#define vp(p)
Definition: modelsinc.h:70
int point_in_octant(polymodel *pm, model_octant *oct, vec3d *vert)
Definition: modeloctant.cpp:26
vec3d mins
Definition: model.h:746
#define OP_BOUNDBOX
Definition: modelsinc.h:25
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
#define OP_EOF
Definition: modelsinc.h:20
void model_octant_find_shields(polymodel *pm, model_octant *oct)
Definition: modeloctant.cpp:41
Assert(pm!=NULL)
vec3d max
Definition: model.h:585
int detail[MAX_MODEL_DETAIL_LEVELS]
Definition: model.h:738
Definition: pstypes.h:88
#define mprintf(args)
Definition: pstypes.h:238
int verts[3]
Definition: model.h:552
struct vec3d::@225::@227 xyz
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
shield_tri ** shield_tris
Definition: model.h:589
vec3d maxs
Definition: model.h:746
int model_which_octant(vec3d *pnt, int model_num, matrix *model_orient, vec3d *model_pos, model_octant **oct)
shield_vertex * verts
Definition: model.h:569
#define Int3()
Definition: pstypes.h:292
hull_check submodel_num
Definition: lua.cpp:5048
#define OP_TMAPPOLY
Definition: modelsinc.h:23
GLintptr offset
Definition: Glext.h:5497
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
#define w(p)
Definition: modelsinc.h:68
GLdouble GLdouble z
Definition: Glext.h:5451
shield_info shield
Definition: model.h:778
#define OP_SORTNORM
Definition: modelsinc.h:24
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:355
void model_octant_find_faces(polymodel *pm, model_octant *oct)
int nshield_tris
Definition: model.h:588
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
GLclampd n
Definition: Glext.h:7286
unsigned char ubyte
Definition: pstypes.h:62
#define vm_vec_zero(v)
Definition: vecmat.h:37
int nverts
Definition: model.h:586
int version
Definition: model.h:733
vec3d pos
Definition: model.h:560
void model_octant_free(polymodel *pm)
#define vm_malloc(size)
Definition: pstypes.h:547
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
#define OP_DEFPOINTS
Definition: modelsinc.h:21
int model_which_octant_distant_many(vec3d *pnt, int model_num, matrix *model_orient, vec3d *model_pos, polymodel **pm, int *octs)
ubyte * bsp_data
Definition: model.h:334
void model_allocate_interp_data(int n_verts, int n_norms, int n_list_verts=0)
GLfloat GLfloat p
Definition: Glext.h:8373
GLenum src
Definition: Glext.h:5917
vec3d * vm_vec_avg(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:217
void moff_tmappoly(ubyte *p, polymodel *pm, model_octant *oct, int just_count)
#define OP_FLATPOLY
Definition: modelsinc.h:22
void moff_defpoints(ubyte *p, int just_count)
Definition: modeloctant.cpp:93
void moff_flatpoly(ubyte *p, polymodel *pm, model_octant *oct, int just_count)
polymodel * pm
Definition: lua.cpp:1598
void model_octant_create(polymodel *pm)
model_octant octants[8]
Definition: model.h:791
int model_which_octant_distant(vec3d *pnt, int model_num, matrix *model_orient, vec3d *model_pos, model_octant **oct)
int model_octant_find_faces_sub(polymodel *pm, model_octant *oct, void *model_ptr, int just_count)
int model_num
Definition: lua.cpp:4996
shield_tri * tris
Definition: model.h:570
int ntris
Definition: model.h:568
#define fl(p)
Definition: modelsinc.h:71
GLint y
Definition: Gl.h:1505
vec3d min
Definition: model.h:585