home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwwin / pick.c_ / pick.bin
Text File  |  1995-11-14  |  6KB  |  197 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 <windows.h>
  48. #include <rwlib.h>
  49. #include <rwwin.h>
  50.  
  51. #include "common.h"
  52. #include "pick.h"
  53.  
  54. /**********************************************************************
  55.  *
  56.  * Functions.
  57.  *
  58.  **********************************************************************/
  59.  
  60. /**********************************************************************/
  61.  
  62. /*
  63.  * Return t at the point of interestion of the given ray and plane.
  64.  * The plane is defined by a point on the plane (p) and a nornal to the
  65.  * plane (n). Returns TRUE if the ray and plane intersect and FALSE if
  66.  * the ray and plane are parallel.
  67.  */
  68. RwBool
  69. IntersectRayAndPlane(RwRay *ray, RwV3d *n, RwV3d *p, RwReal *t)
  70. {
  71.     RwReal div;
  72.  
  73.     div = RwDotProduct(&ray->v, n);
  74.     if (div == CREAL(0.0))
  75.     {
  76.         /*
  77.          * The the ray is parallel to the plane so there is no
  78.          * intersection.
  79.          */
  80.         return FALSE;
  81.     }
  82.     else
  83.     {
  84.         /*
  85.          * Math. voodoo to compute the parameter along the ray of the point
  86.          * of intersection.
  87.          */
  88.         *t = -RDiv(RAdd(-RwDotProduct(n, p), RwDotProduct(&ray->p, n)), div);
  89.         return TRUE;
  90.     }
  91. }
  92.  
  93. /**********************************************************************/
  94.  
  95. /*
  96.  * Given a camera and a viewport position spawn a ray into world space.
  97.  * NOTE: This function does not take into account camera offsets.
  98.  */
  99. RwRay *
  100. SpawnRay(RwCamera *camera, RwInt32 x, RwInt32 y, RwRay *ray)
  101. {
  102.     RwInt32 vpw;
  103.     RwInt32 vph;
  104.     RwReal  vww;
  105.     RwReal  vwh;
  106.     RwReal  vwx;
  107.     RwReal  vwy;
  108.  
  109.     /*
  110.      * Convert the viewport position to a viewwindow position.
  111.      */
  112.     RwGetCameraViewport(camera, NULL, NULL, &vpw, &vph);
  113.     RwGetCameraViewwindow(camera, &vww, &vwh);
  114.     vwx = RSub(RDiv(RMul(INT2REAL(x), vww), INT2REAL(vpw)), RDiv(vww, CREAL(2.0)));
  115.     vwy = RSub(RDiv(RMul(INT2REAL((vph - 1) - y), vwh), INT2REAL(vph)), RDiv(vwh, CREAL(2.0)));
  116.  
  117.     /*
  118.      * Initalize the ray in camera space.
  119.      */
  120.     ray->p.x = CREAL(0.0);
  121.     ray->p.y = CREAL(0.0);
  122.     ray->p.z = CREAL(0.0);
  123.     ray->v.x = vwx;
  124.     ray->v.y = vwy;
  125.     ray->v.z = CREAL(0.5);
  126.  
  127.     /*
  128.      * Transform the ray into world space.
  129.      */
  130.     RwPushScratchMatrix();
  131.         RwGetCameraLTM(camera, RwScratchMatrix());
  132.         /*
  133.          * The camera's positive z points into the screen. For the
  134.          * world, positive z points out of the screen. We need to handle
  135.          * this difference in "handedness" by flipping the x axis. A quick
  136.          * way of doing this is to scale the x axis by -1.
  137.          */
  138.         RwScaleMatrix(RwScratchMatrix(), CREAL(-1.0), CREAL(1.0), CREAL(1.0), rwPRECONCAT);
  139.         RwTransformVector(&ray->v, RwScratchMatrix());
  140.         RwTransformPoint(&ray->p, RwScratchMatrix());
  141.     RwPopScratchMatrix();
  142.  
  143.     return ray;
  144. }
  145.  
  146. /**********************************************************************/
  147.  
  148. /*
  149.  * Compute the position (in world coordinates) of the given clump under
  150.  * the given (x, y) position in the viewport of the given camera. The
  151.  * clump will keep a constant orientation and distance with respect to
  152.  * the camera, i.e., this function can be used to drag the clump around
  153.  * on the plane parallel to the camera on which the clump lies.
  154.  */
  155. RwV3d *
  156. GetClumpPositionUnderPointer(RwClump *clump, RwCamera *camera,
  157.                              RwInt32 x, RwInt32 y, RwV3d *pos)
  158. {
  159.     RwV3d  n;
  160.     RwV3d  p;
  161.     RwRay  ray;
  162.     RwReal t;
  163.     
  164.     /*
  165.      * Compute the parameters of the plane on which the clump lies. The
  166.      * plane normal is the negative camera look at vector and the point
  167.      * on the plane is given by the clump's origin.
  168.      */
  169.     RwGetCameraLookAt(camera, &n);
  170.     n.x = -n.x;
  171.     n.y = -n.y;
  172.     n.z = -n.z;
  173.     RwGetClumpOrigin(clump, &p);
  174.  
  175.     /*
  176.      * Spawn a ray from the picked position.
  177.      */
  178.     SpawnRay(camera, x, y, &ray);
  179.  
  180.     /*
  181.      * Compute the parameter along the ray of the point of intersection.
  182.      * NOTE: This is a special case in that we know the plane is
  183.      * perpindicular to the ray so we know there must be an intersection.
  184.      */
  185.     IntersectRayAndPlane(&ray, &n, &p, &t);
  186.  
  187.     /*
  188.      * Convert the parameter to an actual world position.
  189.      */
  190.     RwScaleVector(&ray.v, t, pos);
  191.     RwAddVector(&ray.p, pos, pos);
  192.     
  193.     return pos;
  194. }
  195.  
  196. /**********************************************************************/
  197.