diff options
author | Benoit Bolsee <benoit.bolsee@online.be> | 2008-05-24 22:06:58 +0400 |
---|---|---|
committer | Benoit Bolsee <benoit.bolsee@online.be> | 2008-05-24 22:06:58 +0400 |
commit | cc6dac8c425bf0914df1cf3422577c28c617fbc4 (patch) | |
tree | 95b1d840c1e5821e0c3701c60772a88aca130cc6 | |
parent | 459b4ea5be5471eac9d20c13d8dc35f6b81b90ee (diff) |
BGE patch: add rayCastToEx(), an extended version of rayCastTo() for use in game script
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.cpp | 86 | ||||
-rw-r--r-- | source/gameengine/Ketsji/KX_GameObject.h | 1 | ||||
-rw-r--r-- | source/gameengine/PyDoc/KX_GameObject.py | 31 |
3 files changed, 116 insertions, 2 deletions
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index fb636b23082..6b4fd565495 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -743,6 +743,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS}, KX_PYMETHODTABLE(KX_GameObject, getDistanceTo), KX_PYMETHODTABLE(KX_GameObject, rayCastTo), + KX_PYMETHODTABLE(KX_GameObject, rayCastToEx), {NULL,NULL} //Sentinel }; @@ -1325,7 +1326,7 @@ bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT } KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, -"rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that match prop\n" +"rayCastTo(other,dist,prop): look towards another point/KX_GameObject and return first object hit within dist that matches prop\n" " prop = property name that object must have; can be omitted => detect any object\n" " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n" " other = 3-tuple or object reference") @@ -1380,6 +1381,89 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, Py_Return; } +KX_PYMETHODDEF_DOC(KX_GameObject, rayCastToEx, +"rayCastToEx(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or None if no hit\n" +" prop = property name that object must have; can be omitted => detect any object\n" +" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" +" from = 3-tuple or object reference for origin of ray (if object, use center of object)\n" +" Can None or omitted => start from self object center\n" +" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" +"Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n") +{ + MT_Point3 toPoint; + MT_Point3 fromPoint; + PyObject* pyto; + PyObject* pyfrom = NULL; + float dist = 0.0f; + char *propName = NULL; + KX_GameObject *other; + + if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) + return NULL; + + if (!PyVecTo(pyto, toPoint)) + { + PyErr_Clear(); + if (!PyType_IsSubtype(pyto->ob_type, &KX_GameObject::Type)) + return NULL; + other = static_cast<KX_GameObject*>(pyto); + toPoint = other->NodeGetWorldPosition(); + } + if (!pyfrom || pyfrom == Py_None) + { + fromPoint = NodeGetWorldPosition(); + } + else if (!PyVecTo(pyfrom, fromPoint)) + { + PyErr_Clear(); + if (!PyType_IsSubtype(pyfrom->ob_type, &KX_GameObject::Type)) + return NULL; + other = static_cast<KX_GameObject*>(pyfrom); + fromPoint = other->NodeGetWorldPosition(); + } + + if (dist != 0.0f) + { + MT_Vector3 toDir = toPoint-fromPoint; + toDir.normalize(); + toPoint = fromPoint + (dist) * toDir; + } + + MT_Point3 resultPoint; + MT_Vector3 resultNormal; + PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); + KX_IPhysicsController *spc = GetPhysicsController(); + KX_GameObject *parent = GetParent(); + if (!spc && parent) + spc = parent->GetPhysicsController(); + if (parent) + parent->Release(); + + m_pHitObject = NULL; + if (propName) + m_testPropName = propName; + else + m_testPropName.SetLength(0); + KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback<KX_GameObject>(this)); + + if (m_pHitObject) + { + PyObject* returnValue = PyTuple_New(3); + if (!returnValue) + return NULL; + PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); + return returnValue; + //return Py_BuildValue("(O,(fff),(fff))", + // m_pHitObject->AddRef(), // trick: KX_GameObject are not true Python object, they use a difference reference count system + // resultPoint[0], resultPoint[1], resultPoint[2], + // resultNormal[0], resultNormal[1], resultNormal[2]); + } + return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + //Py_Return; +} + /* --------------------------------------------------------------------- * Some stuff taken from the header * --------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 5dae59d1d63..9e35e45270c 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -665,6 +665,7 @@ public: KX_PYMETHOD(KX_GameObject,RemoveParent); KX_PYMETHOD(KX_GameObject,GetPhysicsId); KX_PYMETHOD_DOC(KX_GameObject,rayCastTo); + KX_PYMETHOD_DOC(KX_GameObject,rayCastToEx); KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo); private : diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index 8ef82b4943b..b0f55b4ad7a 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -174,9 +174,10 @@ class KX_GameObject: The ray is always casted from the center of the object, ignoring the object itself. The ray is casted towards the center of another object or an explicit [x,y,z] point. + Use rayCastToEx() if you need to retrieve the hit point @param other: [x,y,z] or object towards which the ray is casted - @type other: L{KX_GameObject} or string + @type other: L{KX_GameObject} or 3-tuple @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other @type dist: float @param prop: property name that object must have; can be omitted => detect any object @@ -184,4 +185,32 @@ class KX_GameObject: @rtype: L{KX_GameObject} @return: the first object hit or None if no object or object does not match prop """ + def rayCastToEx(to,from,dist,prop): + """ + Look from a point/object to another point/object and find first object hit within dist that matches prop. + Returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no object hit. + Ex: + # shoot along the axis gun-gunAim (gunAim should be collision-free) + ob,point,normal = gun.rayCastToEx(gunAim,None,50) + if ob: + # hit something + + Notes: + The ray ignores the object on which the method is called. + If is casted from/to object center or explicit [x,y,z] points. + The ray does not have X-Ray capability: the first object hit (other than self object) stops the ray + If a property was specified and the first object hit does not have that property, there is no hit + The ray ignores collision-free objects + + @param to: [x,y,z] or object to which the ray is casted + @type to: L{KX_GameObject} or 3-tuple + @param from: [x,y,z] or object from which the ray is casted; None or omitted => use self object center + @type from: L{KX_GameObject} or 3-tuple or None + @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to + @type dist: float + @param prop: property name that object must have; can be omitted => detect any object + @type prop: string + @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) + @return: (object,hitpoint,hitnormal) or (None,None,None) + """
\ No newline at end of file |