diff options
author | Kester Maddock <Christopher.Maddock.1@uni.massey.ac.nz> | 2004-11-22 13:19:19 +0300 |
---|---|---|
committer | Kester Maddock <Christopher.Maddock.1@uni.massey.ac.nz> | 2004-11-22 13:19:19 +0300 |
commit | 46fbe6b01e095ddb66f3bf6e0516569cfdca8f74 (patch) | |
tree | e7a7754188ef9b290eca479df6ac59b00ea7478b /source | |
parent | cf91617d7829647629c8ce04b9f047dfbdf3d910 (diff) |
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.
Diffstat (limited to 'source')
26 files changed, 546 insertions, 291 deletions
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 7c4279a3b8a..da056ee35cd 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -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 */ diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 3719a5cf225..0bc5344074c 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -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"); } } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index e0d460d18d6..7fa2b68e0c2 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -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) { diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 88a38b35ad4..2b331d7f728 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -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); diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 05c806ec4ff..7e6b3f29bab 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -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_ diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 07505829737..9233a10b784 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -698,14 +698,15 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) return vallie; } -int CValue::_setattr(const STR_String& attr,PyObject* pyobj) + +int CValue::_delattr(const STR_String& attr) { - - if (!pyobj) { // member deletion - RemoveProperty(attr); - return 0; - } + RemoveProperty(attr); + return 0; +} +int CValue::_setattr(const STR_String& attr,PyObject* pyobj) +{ CValue* vallie = ConvertPythonToValue(pyobj); if (vallie) { diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index d30e8a26d97..d49c8debfdc 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -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); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index f96276c37f1..4952c1050a7 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -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? */ diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 0cf305dd14b..909229b04c2 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -44,7 +44,8 @@ typedef enum { KX_BOUNDSPHERE, KX_BOUNDCYLINDER, KX_BOUNDCONE, - KX_BOUNDMESH + KX_BOUNDMESH, + KX_BOUNDPOLYTOPE } KX_BoundBoxClass; struct KX_BoxBounds diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 3e0c7768f56..b72d17aa3b5 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -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 (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); - if (poly->VertexCount() == 4) - { - DT_Begin(); + numvalidpolys = 0; + + 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 */ - 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, + DT_Vertex(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->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())->xyz().getValue(pt); - DT_Vertex(pt); - + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + numvalidpolys++; - DT_End(); + 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(); } - - 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(); } diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index 52d9d3e4790..08464fc88de 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -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) diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index bd84e7e0104..3bd36aebc93 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -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); } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index f10ea902c96..26825fe5e1f 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -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) { diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 2f867c28c40..74161a4d5b8 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -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; diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp index 4f074ce9b12..a95e6a13548 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp +++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp @@ -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); } diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.h b/source/gameengine/Ketsji/KX_TouchEventManager.h index eb2c26a64f3..128758f0be6 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.h +++ b/source/gameengine/Ketsji/KX_TouchEventManager.h @@ -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; diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h index 116eed12cea..4db531d945d 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_FhObject.h @@ -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; } diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h index e7fbf3cdacc..b0e0717cf8c 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_MotionState.h @@ -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; diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h index 4a69f7e2990..b37e1a5466b 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Object.h @@ -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; diff --git a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h index 0b429a3c1a4..80e8c635cbb 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h +++ b/source/gameengine/Physics/Sumo/Fuzzics/include/SM_Scene.h @@ -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; }; diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp new file mode 100644 index 00000000000..a3285b19116 --- /dev/null +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_MotionState.cpp @@ -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; +} + diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp index 42adfcd4d9e..ed5171a87a2 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Object.cpp @@ -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 diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp index 1ea19c56336..c29be228d64 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp @@ -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"); diff --git a/source/gameengine/Physics/Sumo/SConscript b/source/gameengine/Physics/Sumo/SConscript index 63261f6f627..4e2ea9f566f 100755 --- a/source/gameengine/Physics/Sumo/SConscript +++ b/source/gameengine/Physics/Sumo/SConscript @@ -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', diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 4c24a58237c..bfc4c3012c3 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -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); } diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index f2be0355c6e..367aab750e0 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -197,8 +197,7 @@ public: void SchedulePolygons( const MT_Transform &transform, - int drawingmode, - class RAS_IRasterizer* rasty + int drawingmode ); void ClearArrayData(); |