Blender V2.61 - r43446

KX_RayCast.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  * KX_MouseFocusSensor determines mouse in/out/over events.
00027  */
00028 
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 
00037 #include "KX_RayCast.h"
00038 
00039 #include "MT_Point3.h"
00040 #include "MT_Vector3.h"
00041 
00042 #include "KX_IPhysicsController.h"
00043 #include "PHY_IPhysicsEnvironment.h"
00044 #include "PHY_IPhysicsController.h"
00045 
00046 KX_RayCast::KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal, bool faceUV)
00047     :PHY_IRayCastFilterCallback(dynamic_cast<PHY_IPhysicsController*>(ignoreController), faceNormal, faceUV) 
00048 {
00049 }
00050 
00051 void KX_RayCast::reportHit(PHY_RayCastResult* result)
00052 {
00053     m_hitFound = true;
00054     m_hitPoint.setValue((const float*)result->m_hitPoint);
00055     m_hitNormal.setValue((const float*)result->m_hitNormal);
00056     m_hitUVOK = result->m_hitUVOK;
00057     m_hitUV.setValue((const float*)result->m_hitUV);
00058     m_hitMesh = result->m_meshObject;
00059     m_hitPolygon = result->m_polygon;
00060 }
00061 
00062 bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback)
00063 {
00064     if(physics_environment==NULL) return false; /* prevents crashing in some cases */
00065     
00066     // Loops over all physics objects between frompoint and topoint,
00067     // calling callback.RayHit for each one.
00068     //
00069     // callback.RayHit should return true to stop looking, or false to continue.
00070     //
00071     // returns true if an object was found, false if not.
00072     
00073     MT_Point3 frompoint(_frompoint);
00074     const MT_Vector3 todir( (topoint - frompoint).safe_normalized() );
00075     MT_Point3 prevpoint(_frompoint+todir*(-1.f));
00076     
00077     PHY_IPhysicsController* hit_controller;
00078 
00079     while((hit_controller = physics_environment->rayTest(callback,
00080             frompoint.x(),frompoint.y(),frompoint.z(),
00081             topoint.x(),topoint.y(),topoint.z())) != NULL) 
00082     {
00083         KX_ClientObjectInfo* info = static_cast<KX_ClientObjectInfo*>(hit_controller->getNewClientInfo());
00084         
00085         if (!info)
00086         {
00087             printf("no info!\n");
00088             MT_assert(info && "Physics controller with no client object info");
00089             break;
00090         }
00091         
00092         // The biggest danger to endless loop, prevent this by checking that the
00093         // hit point always progresses along the ray direction..
00094         prevpoint -= callback.m_hitPoint;
00095         if (prevpoint.length2() < MT_EPSILON)
00096             break;
00097 
00098         if (callback.RayHit(info))
00099             // caller may decide to stop the loop and still cancel the hit
00100             return callback.m_hitFound;
00101 
00102         // Skip past the object and keep tracing.
00103         // Note that retrieving in a single shot multiple hit points would be possible 
00104         // but it would require some change in Bullet.
00105         prevpoint = callback.m_hitPoint;
00106         /* We add 0.001 of fudge, so that if the margin && radius == 0., we don't endless loop. */
00107         MT_Scalar marg = 0.001 + hit_controller->GetMargin();
00108         marg *= 2.f;
00109         /* Calculate the other side of this object */
00110         MT_Scalar h = MT_abs(todir.dot(callback.m_hitNormal));
00111         if (h <= 0.01)
00112             // the normal is almost orthogonal to the ray direction, cannot compute the other side
00113             break;
00114         marg /= h; 
00115         frompoint = callback.m_hitPoint + marg * todir;
00116         // verify that we are not passed the to point
00117         if ((topoint - frompoint).dot(todir) < 0.f)
00118             break;
00119     }
00120     return false;
00121 }
00122