Blender V2.61 - r43446
|
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