Fix for bugs: 1788 (forces) and 1799 (python delattr on game objects)

Use Polytope collision for faster mesh intersection tests, so SOLID can actually use that qhull lib now.
This commit is contained in:
2004-11-22 10:19:19 +00:00
parent cf91617d78
commit 46fbe6b01e
28 changed files with 579 additions and 297 deletions

View File

@@ -95,6 +95,9 @@ public:
void invert();
MT_Quaternion inverse() const;
MT_Scalar angle(const MT_Quaternion& q) const;
MT_Quaternion slerp(const MT_Quaternion& q, const MT_Scalar& t) const;
static MT_Quaternion random();
};

View File

@@ -60,3 +60,27 @@ GEN_INLINE MT_Quaternion operator*(const MT_Vector3& w, const MT_Quaternion& q)
-w[0] * q[0] - w[1] * q[1] - w[2] * q[2]);
}
GEN_INLINE MT_Scalar MT_Quaternion::angle(const MT_Quaternion& q) const
{
MT_Scalar s = sqrt(length2() * q.length2());
assert(s != MT_Scalar(0.0));
return acos(dot(q) / s);
}
GEN_INLINE MT_Quaternion MT_Quaternion::slerp(const MT_Quaternion& q, const MT_Scalar& t) const
{
MT_Scalar theta = angle(q);
if (theta != MT_Scalar(0.0))
{
MT_Scalar d = MT_Scalar(1.0) / sin(theta);
MT_Scalar s0 = sin((MT_Scalar(1.0) - t) * theta);
MT_Scalar s1 = sin(t * theta);
return d*(*this * s0 + q * s1);
}
else
{
return *this;
}
}

View File

@@ -318,6 +318,7 @@ extern Object workob;
#define OB_BOUND_CYLINDER 2
#define OB_BOUND_CONE 3
#define OB_BOUND_POLYH 4
#define OB_BOUND_POLYT 5
/* also needed for base!!!!! or rather, thy interfere....*/
/* base->flag and ob->flag */

View File

@@ -2389,7 +2389,7 @@ void buttons_ketsji(uiBlock *block, Object *ob)
&ob->gameflag, 0, 0,0, 0,
"Specify a bounds object for physics");
if (ob->gameflag & OB_BOUNDS) {
uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Polyheder%x4",
uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Polyheder%x4|Polytope%x5",
85, 125, 100, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the boundary display type");
}
}

View File

@@ -715,6 +715,14 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
objprop.m_boundobject.box.m_extends[1]=2.f*bb.m_extends[1];
objprop.m_boundobject.box.m_extends[2]=2.f*bb.m_extends[2];
break;
case OB_BOUND_POLYT:
if (blenderobject->type == OB_MESH)
{
objprop.m_boundclass = KX_BOUNDPOLYTOPE;
break;
}
// Object is not a mesh... fall through OB_BOUND_POLYH to
// OB_BOUND_SPHERE
case OB_BOUND_POLYH:
if (blenderobject->type == OB_MESH)
{

View File

@@ -111,6 +111,11 @@ PyObject *PyObjectPlus::_getattr(const STR_String& attr)
return Py_FindMethod(Methods, this, const_cast<char *>(attr.ReadPtr()));
}
int PyObjectPlus::_delattr(const STR_String& attr)
{
return 1;
}
int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value)
{
//return PyObject::_setattr(attr,value);

View File

@@ -119,47 +119,57 @@ PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*)
------------------------------*/
typedef PyTypeObject * PyParentObject; // Define the PyParent Object
class PyObjectPlus : public PyObject { // The PyObjectPlus abstract class
Py_Header; // Always start with Py_Header
public:
PyObjectPlus(PyTypeObject *T);
virtual ~PyObjectPlus() {}; // destructor
static void PyDestructor(PyObject *P) // python wrapper
{
delete ((PyObjectPlus *) P);
};
//void INCREF(void) {
// Py_INCREF(this);
// }; // incref method
//void DECREF(void) {
// Py_DECREF(this);
// }; // decref method
virtual PyObject *_getattr(const STR_String& attr); // _getattr method
static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type.
{ return ((PyObjectPlus*) PyObj)->_getattr(STR_String(attr)); };
virtual int _setattr(const STR_String& attr, PyObject *value); // _setattr method
static int __setattr(PyObject *PyObj, // This should be the entry in Type.
char *attr,
PyObject *value)
{ return ((PyObjectPlus*) PyObj)->_setattr(STR_String(attr), value); };
virtual PyObject *_repr(void); // _repr method
static PyObject *__repr(PyObject *PyObj) // This should be the entry in Type.
{ return ((PyObjectPlus*) PyObj)->_repr(); };
// isA methods
bool isA(PyTypeObject *T);
bool isA(const char *mytypename);
PyObject *Py_isA(PyObject *args);
static PyObject *sPy_isA(PyObject *self, PyObject *args, PyObject *kwd)
{return ((PyObjectPlus*)self)->Py_isA(args);};
class PyObjectPlus : public PyObject
{ // The PyObjectPlus abstract class
Py_Header; // Always start with Py_Header
public:
PyObjectPlus(PyTypeObject *T);
virtual ~PyObjectPlus() {}; // destructor
static void PyDestructor(PyObject *P) // python wrapper
{
delete ((PyObjectPlus *) P);
};
//void INCREF(void) {
// Py_INCREF(this);
// }; // incref method
//void DECREF(void) {
// Py_DECREF(this);
// }; // decref method
virtual PyObject *_getattr(const STR_String& attr); // _getattr method
static PyObject *__getattr(PyObject * PyObj, char *attr) // This should be the entry in Type.
{
return ((PyObjectPlus*) PyObj)->_getattr(STR_String(attr));
}
virtual int _delattr(const STR_String& attr);
virtual int _setattr(const STR_String& attr, PyObject *value); // _setattr method
static int __setattr(PyObject *PyObj, // This should be the entry in Type.
char *attr,
PyObject *value)
{
if (!value)
return ((PyObjectPlus*) PyObj)->_delattr(attr);
return ((PyObjectPlus*) PyObj)->_setattr(STR_String(attr), value);
}
virtual PyObject *_repr(void); // _repr method
static PyObject *__repr(PyObject *PyObj) // This should be the entry in Type.
{
return ((PyObjectPlus*) PyObj)->_repr();
}
// isA methods
bool isA(PyTypeObject *T);
bool isA(const char *mytypename);
PyObject *Py_isA(PyObject *args);
static PyObject *sPy_isA(PyObject *self, PyObject *args, PyObject *kwd)
{
return ((PyObjectPlus*)self)->Py_isA(args);
}
};
#endif // _adr_py_lib_h_

View File

@@ -698,14 +698,15 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj)
return vallie;
}
int CValue::_delattr(const STR_String& attr)
{
RemoveProperty(attr);
return 0;
}
int CValue::_setattr(const STR_String& attr,PyObject* pyobj)
{
if (!pyobj) { // member deletion
RemoveProperty(attr);
return 0;
}
CValue* vallie = ConvertPythonToValue(pyobj);
if (vallie)
{

View File

@@ -249,6 +249,7 @@ public:
virtual CValue* ConvertPythonToValue(PyObject* pyobj);
virtual int _delattr(const STR_String& attr);
virtual int _setattr(const STR_String& attr,PyObject* value);
KX_PYMETHOD(CValue,GetName);

View File

@@ -194,7 +194,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
RemoveAllEvents();
if (bNegativeEvent) return false;
/* The rules: */
/* CONSTRAINT 1: not implemented */
/* CONSTRAINT 2: can camera see actor? */

View File

@@ -44,7 +44,8 @@ typedef enum {
KX_BOUNDSPHERE,
KX_BOUNDCYLINDER,
KX_BOUNDCONE,
KX_BOUNDMESH
KX_BOUNDMESH,
KX_BOUNDPOLYTOPE
} KX_BoundBoxClass;
struct KX_BoxBounds

View File

@@ -78,10 +78,11 @@
#include "KX_SumoPhysicsController.h"
static GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
static GEN_Map<GEN_HashedPtr, DT_VertexBaseHandle> map_gamemesh_to_vertex_base_handle;
// forward declarations
void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,class SM_Object* sumoObj,const STR_String& matname,bool isDynamic,bool isActor);
DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj);
static void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,class SM_Object* sumoObj,const STR_String& matname,bool isDynamic,bool isActor);
static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope);
void KX_ConvertSumoObject( KX_GameObject* gameobj,
@@ -127,6 +128,7 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj,
if (objprop->m_dyna && objprop->m_isactor)
{
DT_ShapeHandle shape = NULL;
bool polytope = false;
switch (objprop->m_boundclass)
{
case KX_BOUNDBOX:
@@ -151,10 +153,13 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj,
smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
break;
/* Dynamic mesh objects. WARNING! slow. */
case KX_BOUNDPOLYTOPE:
polytope = true;
// fall through
case KX_BOUNDMESH:
if (meshobj && meshobj->NumPolygons() > 0)
{
if ((shape = CreateShapeFromMesh(meshobj)))
if ((shape = CreateShapeFromMesh(meshobj, polytope)))
{
// TODO: calculate proper inertia
smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
@@ -185,6 +190,7 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj,
{
DT_ShapeHandle complexshape=0;
bool polytope = false;
switch (objprop->m_boundclass)
{
@@ -200,11 +206,14 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj,
case KX_BOUNDCONE:
complexshape = DT_NewCone(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
break;
case KX_BOUNDPOLYTOPE:
polytope = true;
// fall through
default:
case KX_BOUNDMESH:
if (numpolys>0)
{
complexshape = CreateShapeFromMesh(meshobj);
complexshape = CreateShapeFromMesh(meshobj, polytope);
//std::cout << "Convert Physics Mesh: " << meshobj->GetName() << std::endl;
/* if (!complexshape)
{
@@ -267,7 +276,7 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj,
void BL_RegisterSumoObject(
static void BL_RegisterSumoObject(
KX_GameObject* gameobj,
class SM_Scene* sumoScene,
class SM_Object* sumoObj,
@@ -296,21 +305,114 @@ void BL_RegisterSumoObject(
physicscontroller->SetObject(gameobj->GetSGNode());
}
DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
{
// instance a mesh from a single vertex array & material
const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
//const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray];
DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert));
DT_ShapeHandle shape = DT_NewComplexShape(vertex_base);
std::vector<DT_Index> indices;
for (int p = 0; p < meshobj->NumPolygons(); p++)
{
RAS_Polygon* poly = meshobj->GetPolygon(p);
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{
DT_VertexIndices(3, poly->GetVertexIndexBase().m_indexarray);
// tesselate
if (poly->VertexCount() == 4)
{
DT_Begin();
DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[0]);
DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[2]);
DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[3]);
DT_End();
}
}
}
//DT_VertexIndices(indices.size(), &indices[0]);
DT_EndComplexShape();
map_gamemesh_to_vertex_base_handle.insert(GEN_HashedPtr(meshobj), vertex_base);
return shape;
}
static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
{
// instance a mesh from a single vertex array & material
const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
//const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray];
DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert));
std::vector<DT_Index> indices;
for (int p = 0; p < meshobj->NumPolygons(); p++)
{
RAS_Polygon* poly = meshobj->GetPolygon(p);
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{
indices.push_back(poly->GetVertexIndexBase().m_indexarray[0]);
indices.push_back(poly->GetVertexIndexBase().m_indexarray[1]);
indices.push_back(poly->GetVertexIndexBase().m_indexarray[2]);
if (poly->VertexCount() == 4)
indices.push_back(poly->GetVertexIndexBase().m_indexarray[3]);
}
}
DT_ShapeHandle shape = DT_NewPolytope(vertex_base);
DT_VertexIndices(indices.size(), &indices[0]);
DT_EndPolytope();
map_gamemesh_to_vertex_base_handle.insert(GEN_HashedPtr(meshobj), vertex_base);
return shape;
}
// This will have to be a method in a class somewhere...
// Update SOLID with a changed physics mesh.
// not used... yet.
bool ReInstanceShapeFromMesh(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
{
DT_VertexBaseHandle *vertex_base = map_gamemesh_to_vertex_base_handle[GEN_HashedPtr(meshobj)];
if (vertex_base)
{
const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
DT_ChangeVertexBase(*vertex_base, vertex_array[0].getLocalXYZ());
return true;
}
return false;
}
static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
{
DT_ShapeHandle *shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)];
// Mesh has already been converted: reuse
if (shapeptr)
{
return *shapeptr;
}
// Mesh has no polygons!
int numpolys = meshobj->NumPolygons();
if (!numpolys)
{
return NULL;
}
// Count the number of collision polygons and check they all come from the same
// vertex array
int numvalidpolys = 0;
int vtxarray = -1;
RAS_IPolyMaterial *poly_material = NULL;
bool reinstance = true;
for (int p=0; p<numpolys; p++)
{
@@ -319,74 +421,116 @@ DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{
// check polygon is from the same vertex array
if (poly->GetVertexIndexBase().m_vtxarray != vtxarray)
{
if (vtxarray < 0)
vtxarray = poly->GetVertexIndexBase().m_vtxarray;
else
{
reinstance = false;
vtxarray = -1;
}
}
// check poly is from the same material
if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
{
if (poly_material)
{
reinstance = false;
poly_material = NULL;
}
else
poly_material = poly->GetMaterial()->GetPolyMaterial();
}
// count the number of collision polys
numvalidpolys++;
break;
// We have one collision poly, and we can't reinstance, so we
// might as well break here.
if (!reinstance)
break;
}
}
// No collision polygons
if (numvalidpolys < 1)
return NULL;
DT_ShapeHandle shape = DT_NewComplexShape(NULL);
numvalidpolys = 0;
for (int p2=0; p2<numpolys; p2++)
DT_ShapeHandle shape;
if (reinstance)
{
RAS_Polygon* poly = meshobj->GetPolygon(p2);
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{ /* We have to tesselate here because SOLID can only raycast triangles */
DT_Begin();
DT_Vector3 pt;
/* V1 */
meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[2],
poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
DT_Vertex(pt);
/* V2 */
meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[1],
poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
DT_Vertex(pt);
/* V3 */
meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[0],
poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
DT_Vertex(pt);
numvalidpolys++;
DT_End();
if (poly->VertexCount() == 4)
{
DT_Begin();
/* V1 */
meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[3],
poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
DT_Vertex(pt);
/* V3 */
meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[2],
poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
DT_Vertex(pt);
/* V4 */
meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[0],
poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
DT_Vertex(pt);
numvalidpolys++;
DT_End();
}
}
if (polytope)
shape = InstancePhysicsPolytope(meshobj, vtxarray, poly_material);
else
shape = InstancePhysicsComplex(meshobj, vtxarray, poly_material);
}
else
{
if (polytope)
{
std::cout << "CreateShapeFromMesh: " << meshobj->GetName() << " is not suitable for polytope." << std::endl;
if (!poly_material)
std::cout << " Check mesh materials." << std::endl;
if (vtxarray < 0)
std::cout << " Check number of vertices." << std::endl;
}
shape = DT_NewComplexShape(NULL);
numvalidpolys = 0;
DT_EndComplexShape();
for (int p2=0; p2<numpolys; p2++)
{
RAS_Polygon* poly = meshobj->GetPolygon(p2);
// only add polygons that have the collisionflag set
if (poly->IsCollider())
{ /* We have to tesselate here because SOLID can only raycast triangles */
DT_Begin();
/* V1 */
DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[2],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
/* V2 */
DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[1],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
/* V3 */
DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[0],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
numvalidpolys++;
DT_End();
if (poly->VertexCount() == 4)
{
DT_Begin();
/* V1 */
DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[3],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
/* V3 */
DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[2],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
/* V4 */
DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
poly->GetVertexIndexBase().m_indexarray[0],
poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
numvalidpolys++;
DT_End();
}
}
}
DT_EndComplexShape();
}
if (numvalidpolys > 0)
{
@@ -398,17 +542,22 @@ DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
return NULL;
}
void KX_ClearSumoSharedShapes()
{
int numshapes = map_gamemesh_to_sumoshape.size();
for (int i=0;i<numshapes ;i++)
int i;
for (i=0;i<numshapes ;i++)
{
DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
DT_DeleteShape(shape);
}
map_gamemesh_to_sumoshape.clear();
for (i=0; i < map_gamemesh_to_vertex_base_handle.size(); i++)
DT_DeleteVertexBase(*map_gamemesh_to_vertex_base_handle.at(i));
map_gamemesh_to_vertex_base_handle.clear();
}

View File

@@ -276,7 +276,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
m_direction = 1;
SetStartTime(curtime);
}
SetLocalTime(curtime);
if (ClampLocalTime() && m_localtime == m_startframe)

View File

@@ -315,13 +315,13 @@ void KX_KetsjiEngine::NextFrame()
m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
double curtime;
double localtime = m_previoustime;
if (m_bFixedTime)
curtime = m_previoustime + 1.0/m_ticrate;
else
curtime = m_kxsystem->GetTimeInSeconds();
m_deltatime += curtime - m_previoustime;
m_previoustime = curtime;
double localtime = curtime - m_deltatime;
// Compute the number of logic frames to do each update (fixed tic bricks)
int frames = (int) (m_deltatime*m_ticrate);
@@ -329,44 +329,7 @@ void KX_KetsjiEngine::NextFrame()
KX_SceneList::iterator sceneit;
if (!frames)
{
for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
// for each scene, call the proceed functions
{
KX_Scene* scene = *sceneit;
if (!scene->IsSuspended())
{
// set Python hooks for each scene
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
PHY_SetActiveScene(scene);
// Perform physics calculations on the scene. This can involve
// many iterations of the physics solver.
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
scene->GetPhysicsEnvironment()->proceed(curtime);
// Update scenegraph after physics step. This maps physics calculations
// into node positions.
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->UpdateParents(curtime);
// Do some cleanup work for this logic frame
m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
scene->LogicUpdateFrame(curtime, false);
// Actuators can affect the scenegraph
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->UpdateParents(curtime);
} // suspended
DoSound(scene);
m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
}
}
while (frames--)
while (frames)
{
localtime += 1.0/m_ticrate;
for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
@@ -384,44 +347,46 @@ void KX_KetsjiEngine::NextFrame()
if (!scene->IsSuspended())
{
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
scene->GetPhysicsEnvironment()->endFrame();
scene->GetPhysicsEnvironment()->beginFrame();
m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
scene->GetNetworkScene()->proceed(curtime);
scene->GetNetworkScene()->proceed(localtime);
// set Python hooks for each scene
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
PHY_SetActiveScene(scene);
// Perform physics calculations on the scene. This can involve
// many iterations of the physics solver.
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
scene->GetPhysicsEnvironment()->proceed(curtime);
scene->GetPhysicsEnvironment()->endFrame();
// Update scenegraph after physics step. This maps physics calculations
// into node positions.
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->UpdateParents(curtime);
scene->UpdateParents(localtime);
// Process sensors, and controllers
m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
scene->LogicBeginFrame(curtime);
scene->LogicBeginFrame(localtime);
// Scenegraph needs to be updated again, because Logic Controllers
// can affect the local matrices.
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->UpdateParents(curtime);
scene->UpdateParents(localtime);
// Process actuators
// Do some cleanup work for this logic frame
m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
scene->LogicUpdateFrame(curtime, true);
scene->LogicUpdateFrame(localtime, true);
scene->LogicEndFrame();
// Actuators can affect the scenegraph
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->UpdateParents(curtime);
scene->UpdateParents(localtime);
scene->GetPhysicsEnvironment()->beginFrame();
// Perform physics calculations on the scene. This can involve
// many iterations of the physics solver.
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
scene->GetPhysicsEnvironment()->proceed(localtime);
} // suspended
DoSound(scene);
@@ -445,8 +410,46 @@ void KX_KetsjiEngine::NextFrame()
// scene management
ProcessScheduledScenes();
frames--;
}
// Logic update sub frame: this will let some logic bricks run at the
// full frame rate.
for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
// for each scene, call the proceed functions
{
KX_Scene* scene = *sceneit;
if (!scene->IsSuspended())
{
// set Python hooks for each scene
PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
PHY_SetActiveScene(scene);
// Perform physics calculations on the scene. This can involve
// many iterations of the physics solver.
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
scene->GetPhysicsEnvironment()->proceed(curtime);
// Update scenegraph after physics step. This maps physics calculations
// into node positions.
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->UpdateParents(curtime);
// Do some cleanup work for this logic frame
m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
scene->LogicUpdateFrame(curtime, false);
// Actuators can affect the scenegraph
m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->UpdateParents(curtime);
} // suspended
DoSound(scene);
m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
}
// Start logging time spend outside main loop
m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
}

View File

@@ -860,7 +860,7 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi
for (int m=0;m<nummeshes;m++)
{
// this adds the vertices to the display list
(gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode(),rasty);
(gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode());
}
}
gameobj->MarkVisible(visible);
@@ -916,7 +916,7 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj)
for (int m=0;m<nummeshes;m++)
{
// this adds the vertices to the display list
(gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode(),rasty);
(gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode());
}
// Visibility/ non-visibility are marked
// elsewhere now.
@@ -1186,6 +1186,12 @@ PyObject* KX_Scene::_getattr(const STR_String& attr)
_getattr_up(PyObjectPlus);
}
int KX_Scene::_delattr(const STR_String &attr)
{
PyDict_DelItemString(m_attrlist, const_cast<char *>(attr.ReadPtr()));
return 0;
}
int KX_Scene::_setattr(const STR_String &attr, PyObject *pyvalue)
{

View File

@@ -514,6 +514,7 @@ public:
virtual PyObject* _getattr(const STR_String& attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */
virtual int _setattr(const STR_String &attr, PyObject *pyvalue);
virtual int _delattr(const STR_String &attr);
};
typedef std::vector<KX_Scene*> KX_SceneList;

View File

@@ -40,31 +40,6 @@
#include "SM_Object.h"
KX_TouchEventManager::Collision::Collision(SCA_ISensor *sensor, SM_Object *obj1, SM_Object *obj2)
: m_id(next_id++),
m_sensor(sensor),
m_object1(obj1),
m_object2(obj2)
{
}
bool KX_TouchEventManager::Collision::operator<(const Collision &other) const
{
if (*this == other)
return true;
return m_id < other.m_id;
}
bool KX_TouchEventManager::Collision::operator==(const Collision &other) const
{
return m_sensor == other.m_sensor &&
((m_object1 == other.m_object1 && m_object2 == other.m_object2) ||
(m_object1 == other.m_object2 && m_object2 == other.m_object1));
}
int KX_TouchEventManager::Collision::next_id = 0;
KX_TouchEventManager::KX_TouchEventManager(class SCA_LogicManager* logicmgr,
SM_Scene *scene)
: SCA_EventManager(TOUCH_EVENTMGR),
@@ -80,15 +55,8 @@ DT_Bool KX_TouchEventManager::HandleCollision(void* object1, void* object2, cons
{
SM_Object * obj1 = static_cast<SM_Object*>(object1);
SM_Object * obj2 = static_cast<SM_Object*>(object2);
KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo *>(obj1->getClientObject());
list<SCA_ISensor*>::iterator it;
for ( it = client_info->m_sensors.begin(); it != client_info->m_sensors.end(); ++it)
m_collisions.insert(Collision(*it, obj1, obj2));
client_info = static_cast<KX_ClientObjectInfo *>(obj2->getClientObject());
for ( it = client_info->m_sensors.begin(); it != client_info->m_sensors.end(); ++it)
m_collisions.insert(Collision(*it, obj2, obj1));
m_collisions.insert(std::pair<SM_Object*, SM_Object*>(obj1, obj2));
return DT_CONTINUE;
}
@@ -164,7 +132,17 @@ void KX_TouchEventManager::NextFrame()
static_cast<KX_TouchSensor*>(*it)->SynchronizeTransform();
for (std::set<Collision>::iterator cit = m_collisions.begin(); cit != m_collisions.end(); ++cit)
static_cast<KX_TouchSensor*>((*cit).m_sensor)->HandleCollision((*cit).m_object1, (*cit).m_object2, NULL);
{
KX_ClientObjectInfo *client_info = static_cast<KX_ClientObjectInfo *>((*cit).first->getClientObject());
list<SCA_ISensor*>::iterator sit;
for ( sit = client_info->m_sensors.begin(); sit != client_info->m_sensors.end(); ++sit)
static_cast<KX_TouchSensor*>(*sit)->HandleCollision((*cit).first, (*cit).second, NULL);
client_info = static_cast<KX_ClientObjectInfo *>((*cit).second->getClientObject());
for ( sit = client_info->m_sensors.begin(); sit != client_info->m_sensors.end(); ++sit)
static_cast<KX_TouchSensor*>(*sit)->HandleCollision((*cit).second, (*cit).first, NULL);
}
m_collisions.clear();
@@ -184,6 +162,7 @@ void KX_TouchEventManager::RemoveSensor(class SCA_ISensor* sensor)
std::swap(*i, m_sensors.back());
m_sensors.pop_back();
}
// remove the sensor forever :)
SCA_EventManager::RemoveSensor(sensor);
}

View File

@@ -44,20 +44,7 @@ class SM_Object;
class KX_TouchEventManager : public SCA_EventManager
{
struct Collision
{
static int next_id;
int m_id;
SCA_ISensor *m_sensor;
SM_Object *m_object1;
SM_Object *m_object2;
Collision(SCA_ISensor *sensor, SM_Object *obj1, SM_Object *obj2);
bool operator<(const Collision &other) const;
bool operator==(const Collision &other) const;
};
typedef std::pair<SM_Object*, SM_Object*> Collision;
class SCA_LogicManager* m_logicmgr;
SM_Scene *m_scene;

View File

@@ -40,7 +40,7 @@ public:
SM_FhObject(DT_ShapeHandle rayshape, MT_Vector3 ray, SM_Object *parent_object);
const MT_Vector3& getRay() const { return m_ray; }
MT_Point3 getSpot() const { return m_pos + m_ray; }
MT_Point3 getSpot() const { return getPosition() + m_ray; }
const MT_Vector3& getRayDirection() const { return m_ray_direction; }
SM_Object *getParentObject() const { return m_parent_object; }

View File

@@ -1,3 +1,34 @@
/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#ifndef SM_MOTIONSTATE_H
#define SM_MOTIONSTATE_H
@@ -6,6 +37,7 @@
class SM_MotionState {
public:
SM_MotionState() :
m_time(0.0),
m_pos(0.0, 0.0, 0.0),
m_orn(0.0, 0.0, 0.0, 1.0),
m_lin_vel(0.0, 0.0, 0.0),
@@ -16,17 +48,27 @@ public:
void setOrientation(const MT_Quaternion& orn) { m_orn = orn; }
void setLinearVelocity(const MT_Vector3& lin_vel) { m_lin_vel = lin_vel; }
void setAngularVelocity(const MT_Vector3& ang_vel) { m_ang_vel = ang_vel; }
void setTime(MT_Scalar time) { m_time = time; }
const MT_Point3& getPosition() const { return m_pos; }
const MT_Quaternion& getOrientation() const { return m_orn; }
const MT_Vector3& getLinearVelocity() const { return m_lin_vel; }
const MT_Vector3& getAngularVelocity() const { return m_ang_vel; }
MT_Scalar getTime() const { return m_time; }
void integrateMidpoint(MT_Scalar timeStep, const SM_MotionState &prev_state, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel);
void integrateBackward(MT_Scalar timeStep, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel);
void integrateForward(MT_Scalar timeStep, const SM_MotionState &prev_state);
void lerp(MT_Scalar t, const SM_MotionState &other);
virtual MT_Transform getTransform() const {
return MT_Transform(m_pos, m_orn);
}
protected:
MT_Scalar m_time;
MT_Point3 m_pos;
MT_Quaternion m_orn;
MT_Vector3 m_lin_vel;

View File

@@ -144,7 +144,6 @@ public:
void setOrientation(const MT_Quaternion& orn);
void setScaling(const MT_Vector3& scaling);
/**
* set an external velocity. This velocity complements
* the physics velocity. So setting it does not override the
@@ -267,13 +266,7 @@ public:
void relax();
void backup() {
m_pos = m_prev_state.getPosition();
m_orn = m_prev_state.getOrientation();
m_xform = m_prev_xform;
}
private:
// Tweak parameters
static MT_Scalar ImpulseThreshold;

View File

@@ -88,13 +88,7 @@ public:
void add(SM_Object& object);
void remove(SM_Object& object);
void addPair(SM_Object *obj1, SM_Object *obj2) {
m_pairList.insert(std::make_pair(obj1, obj2));
}
void clearPairs() {
m_pairList.clear();
}
void notifyCollision(SM_Object *obj1, SM_Object *obj2);
void setSecondaryRespTable(DT_RespTableHandle secondaryRespTable);
DT_RespTableHandle getSecondaryRespTable() { return m_secondaryRespTable; }
@@ -146,8 +140,6 @@ private:
/** internal type */
typedef std::vector<SM_Object *> T_ObjectList;
/** internal type */
typedef std::set<std::pair<SM_Object *, SM_Object *> > T_PairList;
/** Handle to the scene in SOLID */
DT_SceneHandle m_scene;
@@ -174,12 +166,6 @@ private:
* The list of objects that receive motion updates and do
* collision tests. */
T_ObjectList m_objectList;
/**
* A list with pairs of objects that collided the previous
* timestep. The list is built during the proceed(). During that
* time, it is not valid. */
T_PairList m_pairList;
MT_Scalar m_lastTime;
};

View File

@@ -0,0 +1,71 @@
/**
* $Id$
*
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. The Blender
* Foundation also sells licenses for use in proprietary software under
* the Blender License. See http://www.blender.org/BL/ for information
* about this.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include <MT_Vector3.h>
#include <MT_Quaternion.h>
#include "SM_MotionState.h"
void SM_MotionState::integrateMidpoint(MT_Scalar timeStep, const SM_MotionState &prev_state, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel)
{
m_pos += (prev_state.getLinearVelocity() + velocity) * (timeStep * 0.5);
m_orn += (prev_state.getAngularVelocity() * prev_state.getOrientation() + ang_vel * m_orn) * (timeStep * 0.25);
m_orn.normalize();
}
void SM_MotionState::integrateBackward(MT_Scalar timeStep, const MT_Vector3 &velocity, const MT_Quaternion& ang_vel)
{
m_pos += velocity * timeStep;
m_orn += ang_vel * m_orn * (timeStep * 0.5);
m_orn.normalize();
}
void SM_MotionState::integrateForward(MT_Scalar timeStep, const SM_MotionState &prev_state)
{
m_pos += prev_state.getLinearVelocity() * timeStep;
m_orn += prev_state.getAngularVelocity() * m_orn * (timeStep * 0.5);
m_orn.normalize();
}
void SM_MotionState::lerp(MT_Scalar t, const SM_MotionState &other)
{
MT_Scalar x = (t - getTime())/(other.getTime() - getTime());
m_pos = x*m_pos + (1-x)*other.getPosition();
m_orn = m_orn.slerp(other.getOrientation(), x);
m_lin_vel = x*m_lin_vel + (1-x)*other.getLinearVelocity();
m_ang_vel = x*m_ang_vel + (1-x)*other.getAngularVelocity();
m_time = t;
}

View File

@@ -65,7 +65,6 @@ SM_Object::SM_Object(
m_materialPropsBackup(0),
m_shapeProps(shapeProps),
m_shapePropsBackup(0),
m_object(DT_CreateObject(this, shape)),
m_margin(0.0),
m_scaling(1.0, 1.0, 1.0),
m_reaction_impulse(0.0, 0.0, 0.0),
@@ -84,6 +83,7 @@ SM_Object::SM_Object(
m_inv_mass(0.0),
m_inv_inertia(0., 0., 0.)
{
m_object = DT_CreateObject(this, shape);
m_xform.setIdentity();
m_xform.getValue(m_ogl_matrix);
if (shapeProps)
@@ -146,19 +146,14 @@ integrateMomentum(
//#define BACKWARD
#ifdef MIDPOINT
// Midpoint rule
m_pos += (m_prev_state.getLinearVelocity() + actualLinVelocity()) * (timeStep * 0.5);
m_orn += (m_prev_state.getAngularVelocity() * m_prev_state.getOrientation() + actualAngVelocity() * m_orn) * (timeStep * 0.25);
integrateMidpoint(timeStep, m_prev_state, actualLinVelocity(), actualAngVelocity());
#elif defined BACKWARD
// Backward Euler
m_pos += actualLinVelocity() * timeStep;
m_orn += actualAngVelocity() * m_orn * (timeStep * 0.5);
integrateBackward(timeStep, actualLinVelocity(), actualAngVelocity());
#else
// Forward Euler
m_pos += m_prev_state.getLinearVelocity() * timeStep;
m_orn += m_prev_state.getAngularVelocity() * m_orn * (timeStep * 0.5);
integrateForward(timeStep, m_prev_state);
#endif
m_orn.normalize(); // I might not be necessary to do this every call
calcXform();
notifyClient();
@@ -212,7 +207,7 @@ void SM_Object::dynamicCollision(const MT_Point3 &local2,
* Apply impulse at the collision point.
* Take rotational inertia into account.
*/
applyImpulse(local2 + m_pos, impulse * normal);
applyImpulse(local2 + getPosition(), impulse * normal);
} else {
/**
* Apply impulse through object centre. (no rotation.)
@@ -323,7 +318,7 @@ void SM_Object::dynamicCollision(const MT_Point3 &local2,
(invMass + lateral.dot(temp.cross(local2)));
MT_Scalar friction = MT_min(impulse_lateral, max_friction);
applyImpulse(local2 + m_pos, -lateral * friction);
applyImpulse(local2 + getPosition(), -lateral * friction);
}
else {
MT_Scalar impulse_lateral = rel_vel_lateral / invMass;
@@ -349,7 +344,7 @@ static void AddCallback(SM_Scene *scene, SM_Object *obj1, SM_Object *obj2)
if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) ||
(obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback()) &&
DT_GetIntersect(obj1->getObjectHandle(), obj2->getObjectHandle(), v))
scene->addPair(obj1, obj2);
scene->notifyCollision(obj1, obj2);
}
DT_Bool SM_Object::boing(
@@ -402,10 +397,10 @@ DT_Bool SM_Object::boing(
// Set callbacks for game engine.
if ((obj1->getClientObject() && obj1->getClientObject()->hasCollisionCallback()) ||
(obj2->getClientObject() && obj2->getClientObject()->hasCollisionCallback()))
scene->addPair(obj1, obj2);
scene->notifyCollision(obj1, obj2);
local1 -= obj1->m_pos;
local2 -= obj2->m_pos;
local1 -= obj1->getPosition();
local2 -= obj2->getPosition();
// Calculate collision parameters
MT_Vector3 rel_vel = obj1->getVelocity(local1) - obj2->getVelocity(local2);
@@ -492,7 +487,7 @@ void SM_Object::relax(void)
return;
//std::cout << "SM_Object::relax: { " << m_error << " }" << std::endl;
m_pos += m_error;
setPosition(getPosition() + m_error);
m_error.setValue(0., 0., 0.);
calcXform();
notifyClient();
@@ -641,15 +636,15 @@ calcXform() {
printf(" m_scaling = { %-0.5f, %-0.5f, %-0.5f }\n",
m_scaling[0], m_scaling[1], m_scaling[2]);
#endif
m_xform.setOrigin(m_pos);
m_xform.setBasis(MT_Matrix3x3(m_orn, m_scaling));
m_xform.setOrigin(getPosition());
m_xform.setBasis(MT_Matrix3x3(getOrientation(), m_scaling));
m_xform.getValue(m_ogl_matrix);
/* Blender has been known to crash here.
This usually means SM_Object *this has been deleted more than once. */
DT_SetMatrixd(m_object, m_ogl_matrix);
if (m_fh_object) {
m_fh_object->setPosition(m_pos);
m_fh_object->setPosition(getPosition());
m_fh_object->calcXform();
}
updateInvInertiaTensor();
@@ -765,9 +760,9 @@ setPosition(
const MT_Point3& pos
){
m_kinematic = true;
m_pos = pos;
SM_MotionState::setPosition(pos);
}
void
SM_Object::
setOrientation(
@@ -775,7 +770,7 @@ setOrientation(
){
assert(!orn.fuzzyZero());
m_kinematic = true;
m_orn = orn;
SM_MotionState::setOrientation(orn);
}
void

View File

@@ -65,21 +65,21 @@ SM_Scene::SM_Scene() :
/* Sensor */
DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[SENSOR_RESPONSE], m_ResponseClass[FH_RESPONSE], 0, DT_NO_RESPONSE, this);
/* Static */
DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[STATIC_RESPONSE], 0, DT_NO_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[STATIC_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
/* Object */
DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], SM_Scene::boing, DT_SIMPLE_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[STATIC_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[OBJECT_RESPONSE], SM_Object::boing, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_BROAD_RESPONSE, this);
DT_AddPairResponse(m_respTable, m_ResponseClass[OBJECT_RESPONSE], m_ResponseClass[FH_RESPONSE], SM_FhObject::ray_hit, DT_SIMPLE_RESPONSE, this);
/* Fh Object */
DT_AddPairResponse(m_respTable, m_ResponseClass[FH_RESPONSE], m_ResponseClass[SENSOR_RESPONSE], 0, DT_NO_RESPONSE, this);
@@ -187,8 +187,30 @@ bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
// Divide the timeStep into a number of subsamples of size roughly
// equal to subS (might be a little smaller).
MT_Scalar timeStep = curtime - m_lastTime;
MT_Scalar subStep = 1.0/ticrate;
int num_samples = int(timeStep * ticrate);
MT_Scalar subStep;
int num_samples;
if (ticrate > 0.0)
{
subStep = 1.0/ticrate;
num_samples = int(timeStep * ticrate);
if (num_samples > 4)
{
std::cout << "Dropping physics frames! step: " << timeStep << " frames:" << num_samples << std::endl;
num_samples /= 4;
subStep *= 4.0;
}
}
else
{
// Variable time step. (old update)
// Integrate at least 100 Hz
subStep = timeStep > 0.01 ? 0.01 : timeStep;
num_samples = int(timeStep * 0.01);
if (num_samples < 1)
num_samples = 1;
}
T_ObjectList::iterator i;
@@ -209,7 +231,7 @@ bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
#endif
return false;
}
m_lastTime += MT_Scalar(num_samples)*subStep;
// Do the integration steps per object.
@@ -253,24 +275,17 @@ bool SM_Scene::proceed(MT_Scalar curtime, MT_Scalar ticrate) {
//(*i)->clearForce();
}
}
// For each pair of object that collided, call the corresponding callback.
// Additional collisions of a pair within the same time step are ignored.
if (m_secondaryRespTable) {
T_PairList::iterator p;
for (p = m_pairList.begin(); p != m_pairList.end(); ++p) {
DT_CallResponse(m_secondaryRespTable,
(*p).first->getObjectHandle(),
(*p).second->getObjectHandle(),
0);
}
}
clearPairs();
return true;
}
void SM_Scene::notifyCollision(SM_Object *obj1, SM_Object *obj2)
{
// For each pair of object that collided, call the corresponding callback.
if (m_secondaryRespTable)
DT_CallResponse(m_secondaryRespTable, obj1->getObjectHandle(), obj2->getObjectHandle(), 0);
}
SM_Object *SM_Scene::rayTest(void *ignore_client,
const MT_Point3& from, const MT_Point3& to,
MT_Point3& result, MT_Vector3& normal) const {
@@ -320,13 +335,13 @@ DT_Bool SM_Scene::boing(
void *client_data,
void *object1,
void *object2,
const DT_CollData *coll_data
const DT_CollData *
){
SM_Scene *scene = (SM_Scene *)client_data;
SM_Object *obj1 = (SM_Object *)object1;
SM_Object *obj2 = (SM_Object *)object2;
scene->addPair(obj1, obj2); // Record this collision for client callbacks
scene->notifyCollision(obj1, obj2); // Record this collision for client callbacks
#ifdef SM_DEBUG_BOING
printf("SM_Scene::boing\n");

View File

@@ -9,7 +9,9 @@ source_files = ['SumoPhysicsController.cpp',
'SumoPhysicsEnvironment.cpp',
'Fuzzics/src/SM_FhObject.cpp',
'Fuzzics/src/SM_Object.cpp',
'Fuzzics/src/SM_Scene.cpp']
'Fuzzics/src/SM_Scene.cpp',
'Fuzzics/src/SM_MotionState.cpp'
]
phy_sumo_env.Append (CPPPATH = ['.',
'../common',

View File

@@ -636,7 +636,7 @@ void RAS_MeshObject::SortPolygons(const MT_Transform &transform)
}
void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawingmode,RAS_IRasterizer* rasty)
void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawingmode)
{
// int nummaterials = m_materials.size();
int i;
@@ -654,8 +654,8 @@ void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawing
int numpolys = m_Polygons.size();
if ((rasty->GetDrawingMode() > RAS_IRasterizer::KX_BOUNDINGBOX) &&
(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID))
if ((drawingmode > RAS_IRasterizer::KX_BOUNDINGBOX) &&
(drawingmode < RAS_IRasterizer::KX_SOLID))
{
for (i=0;i<numpolys;i++)
{
@@ -684,7 +684,7 @@ void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawing
m_bModified = false;
}
if (m_zsort && rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
if (m_zsort && drawingmode >= RAS_IRasterizer::KX_SOLID)
{
SortPolygons(transform);
}

View File

@@ -197,8 +197,7 @@ public:
void SchedulePolygons(
const MT_Transform &transform,
int drawingmode,
class RAS_IRasterizer* rasty
int drawingmode
);
void ClearArrayData();