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