home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Learn 3D Graphics Programming on the PC
/
Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso
/
rwwin
/
xick.c_
/
xick.bin
Wrap
Text File
|
1995-11-14
|
6KB
|
197 lines
/**********************************************************************
*
* File : pick.c
*
* Abstract : The implementation of some enhanced picking functionality
* which use ray casting to determine the exact position
* of the projection of a viewport position onto an
* arbitrary plane. These functions can be used to drag
* objects directly under the mouse cursor.
*
* This application had been written to be compatible with
* both the fixed and floating-point versions of the
* RenderWare library, i.e., it uses the macros CREAL,
* INT2REAL, RAdd, RDiv, RSub etc. If your application is
* intended for the floating-point version of the library
* only these macros are not necessary.
*
* Please note that this application is intended for
* demonstration purposes only. No support will be
* provided for this code and it comes with no warranty.
*
**********************************************************************
*
* This file is a product of Criterion Software Ltd.
*
* This file is provided as is with no warranties of any kind and is
* provided without any obligation on Criterion Software Ltd. or
* Canon Inc. to assist in its use or modification.
*
* Criterion Software Ltd. will not, under any
* circumstances, be liable for any lost revenue or other damages arising
* from the use of this file.
*
* Copyright (c) 1994, 1995 Criterion Software Ltd.
* All Rights Reserved.
*
* RenderWare is a trademark of Canon Inc.
*
**********************************************************************/
/**********************************************************************
*
* Header files.
*
**********************************************************************/
#include <windows.h>
#include <rwlib.h>
#include <rwwin.h>
#include "common.h"
#include "pick.h"
/**********************************************************************
*
* Functions.
*
**********************************************************************/
/**********************************************************************/
/*
* Return t at the point of interestion of the given ray and plane.
* The plane is defined by a point on the plane (p) and a nornal to the
* plane (n). Returns TRUE if the ray and plane intersect and FALSE if
* the ray and plane are parallel.
*/
RwBool
IntersectRayAndPlane(RwRay *ray, RwV3d *n, RwV3d *p, RwReal *t)
{
RwReal div;
div = RwDotProduct(&ray->v, n);
if (div == CREAL(0.0))
{
/*
* The the ray is parallel to the plane so there is no
* intersection.
*/
return FALSE;
}
else
{
/*
* Math. voodoo to compute the parameter along the ray of the point
* of intersection.
*/
*t = -RDiv(RAdd(-RwDotProduct(n, p), RwDotProduct(&ray->p, n)), div);
return TRUE;
}
}
/**********************************************************************/
/*
* Given a camera and a viewport position spawn a ray into world space.
* NOTE: This function does not take into account camera offsets.
*/
RwRay *
SpawnRay(RwCamera *camera, RwInt32 x, RwInt32 y, RwRay *ray)
{
RwInt32 vpw;
RwInt32 vph;
RwReal vww;
RwReal vwh;
RwReal vwx;
RwReal vwy;
/*
* Convert the viewport position to a viewwindow position.
*/
RwGetCameraViewport(camera, NULL, NULL, &vpw, &vph);
RwGetCameraViewwindow(camera, &vww, &vwh);
vwx = RSub(RDiv(RMul(INT2REAL(x), vww), INT2REAL(vpw)), RDiv(vww, CREAL(2.0)));
vwy = RSub(RDiv(RMul(INT2REAL((vph - 1) - y), vwh), INT2REAL(vph)), RDiv(vwh, CREAL(2.0)));
/*
* Initalize the ray in camera space.
*/
ray->p.x = CREAL(0.0);
ray->p.y = CREAL(0.0);
ray->p.z = CREAL(0.0);
ray->v.x = vwx;
ray->v.y = vwy;
ray->v.z = CREAL(0.5);
/*
* Transform the ray into world space.
*/
RwPushScratchMatrix();
RwGetCameraLTM(camera, RwScratchMatrix());
/*
* The camera's positive z points into the screen. For the
* world, positive z points out of the screen. We need to handle
* this difference in "handedness" by flipping the x axis. A quick
* way of doing this is to scale the x axis by -1.
*/
RwScaleMatrix(RwScratchMatrix(), CREAL(-1.0), CREAL(1.0), CREAL(1.0), rwPRECONCAT);
RwTransformVector(&ray->v, RwScratchMatrix());
RwTransformPoint(&ray->p, RwScratchMatrix());
RwPopScratchMatrix();
return ray;
}
/**********************************************************************/
/*
* Compute the position (in world coordinates) of the given clump under
* the given (x, y) position in the viewport of the given camera. The
* clump will keep a constant orientation and distance with respect to
* the camera, i.e., this function can be used to drag the clump around
* on the plane parallel to the camera on which the clump lies.
*/
RwV3d *
GetClumpPositionUnderPointer(RwClump *clump, RwCamera *camera,
RwInt32 x, RwInt32 y, RwV3d *pos)
{
RwV3d n;
RwV3d p;
RwRay ray;
RwReal t;
/*
* Compute the parameters of the plane on which the clump lies. The
* plane normal is the negative camera look at vector and the point
* on the plane is given by the clump's origin.
*/
RwGetCameraLookAt(camera, &n);
n.x = -n.x;
n.y = -n.y;
n.z = -n.z;
RwGetClumpOrigin(clump, &p);
/*
* Spawn a ray from the picked position.
*/
SpawnRay(camera, x, y, &ray);
/*
* Compute the parameter along the ray of the point of intersection.
* NOTE: This is a special case in that we know the plane is
* perpindicular to the ray so we know there must be an intersection.
*/
IntersectRayAndPlane(&ray, &n, &p, &t);
/*
* Convert the parameter to an actual world position.
*/
RwScaleVector(&ray.v, t, pos);
RwAddVector(&ray.p, pos, pos);
return pos;
}
/**********************************************************************/