home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / flyby.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  9KB  |  325 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/main/rcs/flyby.c $
  15.  * $Revision: 2.0 $
  16.  * $Author: john $
  17.  * $Date: 1995/02/27 11:33:03 $
  18.  * 
  19.  * Routines to fly though a mine (to show it off)
  20.  * 
  21.  * $Log: flyby.c $
  22.  * Revision 2.0  1995/02/27  11:33:03  john
  23.  * New version 2.0, which has no anonymous unions, builds with
  24.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  25.  * 
  26.  * Revision 1.20  1994/11/19  15:17:49  mike
  27.  * rip out unused code and data
  28.  * 
  29.  * Revision 1.19  1994/11/17  14:58:40  mike
  30.  * move segment validation functions from editor to main.
  31.  * 
  32.  * Revision 1.18  1994/08/19  20:09:39  matt
  33.  * Added end-of-level cut scene with external scene
  34.  * 
  35.  * Revision 1.17  1994/05/20  11:56:44  matt
  36.  * Cleaned up find_vector_intersection() interface
  37.  * Killed check_point_in_seg(), check_player_seg(), check_object_seg()
  38.  * 
  39.  * Revision 1.16  1994/05/19  09:51:06  matt
  40.  * Use new function vm_vec_normalized_dir()
  41.  * 
  42.  * Revision 1.15  1994/05/18  22:29:25  matt
  43.  * Use new function vm_extract_angles_vector()
  44.  * 
  45.  * Revision 1.14  1994/05/12  10:26:33  matt
  46.  * Took out references to unused structure fields.
  47.  * 
  48.  * Revision 1.13  1994/03/30  16:44:13  matt
  49.  * Use great new vm_vec_scale_add2() function
  50.  * 
  51.  * Revision 1.12  1994/02/17  11:32:37  matt
  52.  * Changes in object system
  53.  * 
  54.  * Revision 1.11  1994/01/27  18:18:10  john
  55.  * Added new module, objfly, and made robots
  56.  * fly using this code.
  57.  * 
  58.  * Revision 1.10  1994/01/05  14:26:01  john
  59.  * Made Slew_object be able to slew, fly, and auto-fly.
  60.  * 
  61.  * Revision 1.9  1994/01/05  10:53:52  john
  62.  * New object code by John.  
  63.  * 
  64.  * Revision 1.8  1993/12/21  14:30:32  matt
  65.  * Explicitely set some variables in init, so flyby is the same each time.
  66.  * 
  67.  * Revision 1.7  1993/12/01  11:44:15  matt
  68.  * Chagned Frfract to FrameTime
  69.  * 
  70.  * Revision 1.6  1993/11/04  15:47:29  matt
  71.  * Added check to hopefully prevent divide overflow
  72.  * 
  73.  * Revision 1.5  1993/10/29  22:54:38  matt
  74.  * Made changes for new matrix ordering
  75.  * 
  76.  * Revision 1.4  1993/10/26  11:23:25  matt
  77.  * Doesn't get stuck now in some cases with very small segments
  78.  * 
  79.  * Revision 1.3  1993/10/25  14:34:42  matt
  80.  * Added direction choice keys to flythrough
  81.  * 
  82.  * Revision 1.2  1993/10/14  18:04:51  mike
  83.  * Change CONNECTIVITY to MAX_SIDES_PER_SEGMENT
  84.  * 
  85.  * Revision 1.1  1993/10/14  11:03:47  matt
  86.  * Initial revision
  87.  * 
  88.  * 
  89.  */
  90.  
  91. #pragma off (unreferenced)
  92. static char rcsid[] = "$Id: flyby.c 2.0 1995/02/27 11:33:03 john Exp $";
  93. #pragma on (unreferenced)
  94.  
  95.  
  96. #include <stdlib.h>
  97.  
  98. #include "inferno.h"
  99. #include "game.h"
  100. #include "editor\editor.h"
  101. #include "error.h"
  102.  
  103.  
  104. //variables for fly-through system
  105.  
  106. static vms_angvec player_angles;    //player's orientation in angles
  107.  
  108. vms_vector player_step;        //how far in a second
  109. vms_angvec player_angstep;    //rotation per second
  110.  
  111. fix player_speed=0x100000;    //how fast the player is moving (per second)
  112.  
  113. //which way the user wants to turn
  114. int ft_preference = FP_FORWARD;
  115.  
  116. vms_vector headvec;            //where we want to be pointing
  117.  
  118. vms_angvec *angvec_add2_scale(vms_angvec *dest,vms_angvec *src,fix s)
  119. {
  120.     dest->pitch += fixmul(src->pitch,s);
  121.     dest->bank  += fixmul(src->bank,s);
  122.     dest->head  += fixmul(src->head,s);
  123.  
  124.     return dest;
  125. }
  126.  
  127. //return though which side of seg0 is seg1
  128. int matt_find_connect_side(int seg0,int seg1)
  129. {
  130.     segment *Seg=&Segments[seg0];
  131.     int i;
  132.  
  133.     for (i=MAX_SIDES_PER_SEGMENT;i--;) if (Seg->children[i]==seg1) return i;
  134.  
  135.     return -1;
  136. }
  137.  
  138. //#include <math.h>
  139. //
  140. //#define PI 3.14159
  141. //
  142. ////extract 3 angles from forward vector, assuming bank==0
  143. //angles_from_vector(vms_angvec *dest,vms_vector *vec)
  144. //{
  145. //    vms_vector tempv;
  146. //    double x,y,z;
  147. //    double p,b,h;
  148. //
  149. //    tempv = *vec;
  150. //    vm_vec_normalize(&tempv);
  151. //
  152. //    x = f2fl(tempv.x); y = f2fl(tempv.y); z = f2fl(tempv.z);
  153. //
  154. //    b = 0;
  155. //    p = asin(-y);
  156. //
  157. //    if (x==0 && z==0) h=0;
  158. //    else
  159. //        h = atan2(x,z);
  160. //
  161. //    dest->p = fl2f(p/(PI*2));
  162. //    dest->b = fl2f(b/(PI*2));
  163. //    dest->h = fl2f(h/(PI*2));
  164. //}
  165.  
  166. void compute_segment_center(vms_vector *vp,segment *sp);
  167. void compute_center_point_on_side(vms_vector *vp,segment *sp,int side);
  168.  
  169. //find delta between two angles
  170. fixang delta_ang(fixang a,fixang b)
  171. {
  172.     fixang delta0,delta1;
  173.  
  174.     return (abs(delta0 = a - b) < abs(delta1 = b - a)) ? delta0 : delta1;
  175.  
  176. }
  177.  
  178. //--unused-- fixang interp_angle(fixang dest,fixang src,fixang step)
  179. //--unused-- {
  180. //--unused--     fixang delta;
  181. //--unused-- 
  182. //--unused--     delta = delta_ang(dest,src);
  183. //--unused-- 
  184. //--unused--     if (delta > step) delta = step;
  185. //--unused--     else if (delta < -step) delta = -step;
  186. //--unused-- 
  187. //--unused--     return dest + delta;
  188. //--unused-- 
  189. //--unused-- }
  190.  
  191. #define MIN_D 0x100
  192.  
  193. do_flythrough(object *obj,int first_time)        //set true if init
  194. {
  195.     segment *pseg;
  196.     int old_player_seg = obj->segnum;
  197.  
  198.     if (first_time) {
  199.         //vms_vector zero_vector = {0,0,0};
  200.  
  201.         obj->control_type = CT_FLYTHROUGH;
  202.  
  203.         //obj->fly_info.angle_step.p = 0;
  204.         //obj->fly_info.angle_step.b = 0;
  205.         //obj->fly_info.angle_step.h = 0;
  206.         //obj->fly_info.heading = zero_vector;
  207.  
  208.     }
  209.     
  210.     //move the player for this frame
  211.  
  212.     if (!first_time) {
  213.         //vms_vector tempv;
  214.         //fix rot_step;
  215.  
  216.         vm_vec_scale_add2(&obj->pos,&player_step,FrameTime);
  217.         angvec_add2_scale(&player_angles,&player_angstep,FrameTime);
  218.  
  219.         vm_angles_2_matrix(&obj->orient,&player_angles);
  220.     }
  221.  
  222.     //check new player seg
  223.  
  224.     update_object_seg(obj);
  225.     pseg = &Segments[obj->segnum];
  226.  
  227.     if (first_time || obj->segnum != old_player_seg) {        //moved into new seg
  228.         vms_vector curcenter,nextcenter;
  229.         fix step_size,seg_time;
  230.         short entry_side,exit_side;    //what sides we entry and leave through
  231.         vms_vector dest_point;        //where we are heading (center of exit_side)
  232.         vms_angvec dest_angles;        //where we want to be pointing
  233.  
  234.         //find new exit side
  235.  
  236.         if (!first_time) {
  237.  
  238.             entry_side = matt_find_connect_side(obj->segnum,old_player_seg);
  239.             exit_side = Side_opposite[entry_side];
  240.         }
  241.  
  242.         if (first_time) ft_preference = FP_FORWARD;
  243.  
  244.         if (first_time || entry_side==-1 || pseg->children[exit_side]==-1 || ft_preference!=FP_FORWARD) {
  245.             int i;
  246.             vms_vector prefvec,segcenter,sidevec;
  247.             fix best_val=-f2_0;
  248.             int best_side;
  249.  
  250.             //find exit side
  251.  
  252.             if (ft_preference == FP_FORWARD) {
  253.                 if (first_time) prefvec = obj->orient.fvec;
  254.                 else prefvec = headvec;
  255.                 vm_vec_normalize(&prefvec);
  256.             }
  257.             else
  258.                 prefvec = obj->orient.vecs[ft_preference%3];
  259.  
  260.             if (ft_preference >= 3) {prefvec.x = -prefvec.x; prefvec.y = -prefvec.y; prefvec.z = -prefvec.z;}
  261.  
  262.             compute_segment_center(&segcenter,pseg);
  263.  
  264.             best_side=-1;
  265.             for (i=MAX_SIDES_PER_SEGMENT;--i >= 0;) {
  266.                 fix d;
  267.  
  268.                 if (pseg->children[i]!=-1) {
  269.  
  270.                     compute_center_point_on_side(&sidevec,pseg,i);
  271.                     //vm_vec_sub2(&sidevec,&segcenter);
  272.                     //vm_vec_normalize(&sidevec);
  273.                     vm_vec_normalized_dir(&sidevec,&sidevec,&segcenter);
  274.                     d = vm_vec_dotprod(&sidevec,&prefvec);
  275.  
  276.                     if (labs(d) < MIN_D) d=0;
  277.  
  278.                     if (d > best_val || (d==best_val && i==exit_side)) {best_val=d; best_side=i;}
  279.  
  280.                 }
  281.             }
  282.  
  283.             if (best_val > 0) ft_preference = FP_FORWARD;
  284.  
  285.             Assert(best_side!=-1);
  286.  
  287.             exit_side = best_side;
  288.         }
  289.  
  290.         //update target point & angles
  291.  
  292.         compute_center_point_on_side(&dest_point,pseg,exit_side);
  293.  
  294.         //update target point and movement points
  295.  
  296.         vm_vec_sub(&player_step,&dest_point,&obj->pos);
  297.         step_size = vm_vec_normalize(&player_step);
  298.         vm_vec_scale(&player_step,player_speed);
  299.  
  300.         compute_segment_center(&curcenter,pseg);
  301.         compute_segment_center(&nextcenter,&Segments[pseg->children[exit_side]]);
  302.         vm_vec_sub(&headvec,&nextcenter,&curcenter);
  303.  
  304.         //angles_from_vector(&dest_angles,&headvec);    //extract angles
  305.         vm_extract_angles_vector(&dest_angles,&headvec);    //extract angles
  306.  
  307.         if (first_time)
  308.             //angles_from_vector(&player_angles,&obj->orient.fvec);
  309.             vm_extract_angles_vector(&player_angles,&obj->orient.fvec);
  310.  
  311.         seg_time = fixdiv(step_size,player_speed);    //how long through seg
  312.  
  313.         if (seg_time) {
  314.             player_angstep.p = fixdiv(delta_ang(player_angles.p,dest_angles.p),seg_time);
  315.             player_angstep.b = fixdiv(delta_ang(player_angles.b,dest_angles.b),seg_time);
  316.             player_angstep.h = fixdiv(delta_ang(player_angles.h,dest_angles.h),seg_time);
  317.         }
  318.         else {
  319.             player_angles = dest_angles;
  320.             player_angstep.p = player_angstep.b = player_angstep.h = 0;
  321.         }
  322.     }
  323. }
  324.  
  325.