home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacWT 0.9 / wt Source / world.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-10  |  3.7 KB  |  155 lines  |  [TEXT/CWIE]

  1. /*
  2. **  MacWT -- a 3d game engine for the Macintosh
  3. **  © 1995, Bill Hayden and Nikol Software
  4. **  Free for non-commercial use - address questions to the e-mail address below
  5. **
  6. **  Mail:           afn28988@freenet.ufl.edu (Bill Hayden)
  7. **    MacWT FTP site: ftp.circa.ufl.edu/pub/software/ufmug/mirrors/LocalSW/Hayden/
  8. **  WWW Page:       http://grove.ufl.edu:80/~nikolsw
  9. **
  10. **    All of the above addresses are due to changes sometime in 1996, so stay tuned
  11. **
  12. **  based on wt, by Chris Laurel
  13. **
  14. **  This program is distributed in the hope that it will be useful,
  15. **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. */
  18.  
  19.  
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include "wt.h"
  24. #include "error.h"
  25. #include "fixed.h"
  26. #include "wtmem.h"
  27. #include "framebuf.h"
  28. #include "texture.h"
  29. #include "table.h"
  30. #include "list.h"
  31. #include "view.h"
  32. #include "world.h"
  33. #include "object.h"
  34.  
  35.  
  36. World *new_world(void)
  37. {
  38.     World *w;
  39.  
  40.     w = (World *)wtmalloc(sizeof(World));
  41.     w->vertices = new_table(sizeof(Vertex), MAX_VERTICES);
  42.     w->walls = new_table(sizeof(Wall), MAX_WALLS);
  43.     w->regions = new_table(sizeof(Region), MAX_REGIONS);
  44.     w->textures = new_table(sizeof(Texture *), MAX_TEXTURES);
  45.     w->objects = new_list();
  46.      
  47.     return w;
  48. }
  49.  
  50.  
  51. int add_texture(World *w, Texture *tex)
  52. {
  53.     return add_table_entry(w->textures, &tex);
  54. }
  55.  
  56.  
  57. int add_wall(World *w, Wall *wall)
  58. {
  59.     return add_table_entry(w->walls, wall);
  60. }
  61.  
  62.  
  63. int add_vertex(World *w, Vertex *v)
  64. {
  65.     return add_table_entry(w->vertices, v);
  66. }
  67.  
  68.  
  69. int add_region(World *w, Region *r)
  70. {
  71.     return add_table_entry(w->regions, r);
  72. }
  73.  
  74.  
  75.  
  76. void update_wall_scale(World *w, int wall_num, fixed xscale, fixed yscale)
  77. {
  78.     Wall *wall;
  79.     Texture *texture;
  80.     fixed wall_length;
  81.  
  82.     if (wall_num < 0 || wall_num > TABLE_SIZE(w->walls))
  83.         fatal_error("invalid wall number");
  84.  
  85.     wall = (Wall *) w->walls->table + wall_num;
  86.     texture = wall->surface_texture;
  87.  
  88.     wall_length = FLOAT_TO_FIXED(sqrt(FIXED_TO_FLOAT(wall->vertex2->x - wall->vertex1->x) *
  89.                                           FIXED_TO_FLOAT(wall->vertex2->x - wall->vertex1->x) +
  90.                                           FIXED_TO_FLOAT(wall->vertex2->y - wall->vertex1->y) *
  91.                                          FIXED_TO_FLOAT(wall->vertex2->y - wall->vertex1->y)));
  92.     wall->yscale = fixmul(yscale, INT_TO_FIXED(texture->height));
  93.     wall->xscale = fixmul( fixmul(xscale, INT_TO_FIXED(texture->width)), wall_length );
  94. }
  95.  
  96.  
  97.  
  98. void update_wall_phase(World *w, int wall_num, fixed xphase, fixed yphase)
  99. {
  100.     Wall *wall;
  101.  
  102.     if (wall_num < 0 || wall_num > TABLE_SIZE(w->walls))
  103.         fatal_error("invalid wall number");
  104.  
  105.     wall = (Wall *) w->walls->table + wall_num;
  106.  
  107.     wall->xphase = xphase;
  108.     wall->yphase = yphase;
  109. }
  110.  
  111.  
  112. /* Return the region in which a point falls.  The method for determining
  113. **   this is simple--probably too much so.  We shoot a ray horizontally
  114. **   from the point.  The region containing the point is either the front
  115. **   or back region of the wall which intersects the ray closest to the
  116. **   point.
  117. */
  118. Region *in_region(World *w, fixed x, fixed y)
  119. {
  120.     Wall *wall = (Wall *) w->walls->table;
  121.     Region *closest_region = NULL;
  122.     fixed closest = FIXED_MAX;
  123.     short i;
  124.      
  125.     for (i = 0; i < TABLE_SIZE(w->walls); i++, wall++)
  126.         {
  127.         fixed y1 = wall->vertex1->y;
  128.         fixed y2 = wall->vertex2->y;
  129.  
  130.         if ((y >= y1 && y < y2) || (y >= y2 && y < y1))
  131.             {
  132.             fixed dist;
  133.             Vertex *v1 = wall->vertex1, *v2 = wall->vertex2;
  134.  
  135.             // Kludge to avoid division overflows for near-horizontal walls.
  136.  
  137.             if (FIXED_ABS(y1 - y2) < FIXED_EPSILON)
  138.                 dist = MIN(v1->x - x, v2->x - x);
  139.             else
  140.                 dist = fixmul(fixdiv(v1->x - v2->x, v1->y - v2->y), y - v1->y) + v1->x - x;
  141.                 
  142.             if (dist > FIXED_ZERO && dist < closest)
  143.                 {
  144.                 closest = dist;
  145.                 if (y1 < y2)
  146.                     closest_region = wall->front;
  147.                 else
  148.                     closest_region = wall->back;
  149.                 }
  150.             }
  151.         }
  152.  
  153.      return closest_region;
  154. }
  155.