home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwdos / pick.c < prev    next >
C/C++ Source or Header  |  1995-02-15  |  6KB  |  192 lines

  1. /**********************************************************************
  2.  *
  3.  * File :     pick.c
  4.  *
  5.  * Abstract : The implementation of some enhanced picking functionality
  6.  *            which use ray casting to determine the exact position
  7.  *            of the projection of a viewport position onto an
  8.  *            arbitrary plane. These functions can be used to drag
  9.  *            objects directly under the mouse cursor.
  10.  *
  11.  *            This application had been written to be compatible with
  12.  *            both the fixed and floating-point versions of the
  13.  *            RenderWare library, i.e., it uses the macros CREAL,
  14.  *            INT2REAL, RAdd, RDiv, RSub etc. If your application is
  15.  *            intended for the floating-point version of the library
  16.  *            only these macros are not necessary.
  17.  *
  18.  *            Please note that this application is intended for
  19.  *            demonstration purposes only. No support will be
  20.  *            provided for this code and it comes with no warranty.
  21.  *
  22.  **********************************************************************
  23.  *
  24.  * This file is a product of Criterion Software Ltd.
  25.  *
  26.  * This file is provided as is with no warranties of any kind and is
  27.  * provided without any obligation on Criterion Software Ltd. or
  28.  * Canon Inc. to assist in its use or modification.
  29.  *
  30.  * Criterion Software Ltd. will not, under any
  31.  * circumstances, be liable for any lost revenue or other damages arising
  32.  * from the use of this file.
  33.  *
  34.  * Copyright (c) 1994, 1995 Criterion Software Ltd.
  35.  * All Rights Reserved.
  36.  *
  37.  * RenderWare is a trademark of Canon Inc.
  38.  *
  39.  **********************************************************************/
  40.  
  41. /**********************************************************************
  42.  *
  43.  * Header files.
  44.  *
  45.  **********************************************************************/
  46.  
  47. #include "pick.h"
  48.  
  49. /**********************************************************************
  50.  *
  51.  * Functions.
  52.  *
  53.  **********************************************************************/
  54.  
  55. /**********************************************************************/
  56.  
  57. /*
  58.  * Return t at the point of interestion of the given ray and plane.
  59.  * The plane is defined by a point on the plane (p) and a nornal to the
  60.  * plane (n). Returns TRUE if the ray and plane intersect and FALSE if
  61.  * the ray and plane are parallel.
  62.  */
  63. RwBool
  64. IntersectRayAndPlane(RwRay *ray, RwV3d *n, RwV3d *p, RwReal *t)
  65. {
  66.     RwReal div;
  67.  
  68.     div = RwDotProduct(&ray->v, n);
  69.     if (div == CREAL(0.0))
  70.     {
  71.         /*
  72.          * The the ray is parallel to the plane so there is no
  73.          * intersection.
  74.          */
  75.         return FALSE;
  76.     }
  77.     else
  78.     {
  79.         /*
  80.          * Math. voodoo to compute the parameter along the ray of the point
  81.          * of intersection.
  82.          */
  83.         *t = -RDiv(RAdd(-RwDotProduct(n, p), RwDotProduct(&ray->p, n)), div);
  84.         return TRUE;
  85.     }
  86. }
  87.  
  88. /**********************************************************************/
  89.  
  90. /*
  91.  * Given a camera and a viewport position spawn a ray into world space.
  92.  * NOTE: This function does not take into account camera offsets.
  93.  */
  94. RwRay *
  95. SpawnRay(RwCamera *camera, RwInt32 x, RwInt32 y, RwRay *ray)
  96. {
  97.     RwInt32 vpw;
  98.     RwInt32 vph;
  99.     RwReal  vww;
  100.     RwReal  vwh;
  101.     RwReal  vwx;
  102.     RwReal  vwy;
  103.  
  104.     /*
  105.      * Convert the viewport position to a viewwindow position.
  106.      */
  107.     RwGetCameraViewport(camera, NULL, NULL, &vpw, &vph);
  108.     RwGetCameraViewwindow(camera, &vww, &vwh);
  109.     vwx = RSub(RDiv(RMul(INT2REAL(x), vww), INT2REAL(vpw)), RDiv(vww, CREAL(2.0)));
  110.     vwy = RSub(RDiv(RMul(INT2REAL((vph - 1) - y), vwh), INT2REAL(vph)), RDiv(vwh, CREAL(2.0)));
  111.  
  112.     /*
  113.      * Initalize the ray in camera space.
  114.      */
  115.     ray->p.x = CREAL(0.0);
  116.     ray->p.y = CREAL(0.0);
  117.     ray->p.z = CREAL(0.0);
  118.     ray->v.x = vwx;
  119.     ray->v.y = vwy;
  120.     ray->v.z = CREAL(0.5);
  121.  
  122.     /*
  123.      * Transform the ray into world space.
  124.      */
  125.     RwPushScratchMatrix();
  126.         RwGetCameraLTM(camera, RwScratchMatrix());
  127.         /*
  128.          * The camera's positive z points into the screen. For the
  129.          * world, positive z points out of the screen. We need to handle
  130.          * this difference in "handedness" by flipping the x axis. A quick
  131.          * way of doing this is to scale the x axis by -1.
  132.          */
  133.         RwScaleMatrix(RwScratchMatrix(), CREAL(-1.0), CREAL(1.0), CREAL(1.0), rwPRECONCAT);
  134.         RwTransformVector(&ray->v, RwScratchMatrix());
  135.         RwTransformPoint(&ray->p, RwScratchMatrix());
  136.     RwPopScratchMatrix();
  137.  
  138.     return ray;
  139. }
  140.  
  141. /**********************************************************************/
  142.  
  143. /*
  144.  * Compute the position (in world coordinates) of the given clump under
  145.  * the given (x, y) position in the viewport of the given camera. The
  146.  * clump will keep a constant orientation and distance with respect to
  147.  * the camera, i.e., this function can be used to drag the clump around
  148.  * on the plane parallel to the camera on which the clump lies.
  149.  */
  150. RwV3d *
  151. GetClumpPositionUnderPointer(RwClump *clump, RwCamera *camera,
  152.                              RwInt32 x, RwInt32 y, RwV3d *pos)
  153. {
  154.     RwV3d  n;
  155.     RwV3d  p;
  156.     RwRay  ray;
  157.     RwReal t;
  158.     
  159.     /*
  160.      * Compute the parameters of the plane on which the clump lies. The
  161.      * plane normal is the negative camera look at vector and the point
  162.      * on the plane is given by the clump's origin.
  163.      */
  164.     RwGetCameraLookAt(camera, &n);
  165.     n.x = -n.x;
  166.     n.y = -n.y;
  167.     n.z = -n.z;
  168.     RwGetClumpOrigin(clump, &p);
  169.  
  170.     /*
  171.      * Spawn a ray from the picked position.
  172.      */
  173.     SpawnRay(camera, x, y, &ray);
  174.  
  175.     /*
  176.      * Compute the parameter along the ray of the point of intersection.
  177.      * NOTE: This is a special case in that we know the plane is
  178.      * perpindicular to the ray so we know there must be an intersection.
  179.      */
  180.     IntersectRayAndPlane(&ray, &n, &p, &t);
  181.  
  182.     /*
  183.      * Convert the parameter to an actual world position.
  184.      */
  185.     RwScaleVector(&ray.v, t, pos);
  186.     RwAddVector(&ray.p, pos, pos);
  187.     
  188.     return pos;
  189. }
  190.  
  191. /**********************************************************************/
  192.