diff options
28 files changed, 573 insertions, 291 deletions
diff --git a/intern/moto/include/MT_Quaternion.h b/intern/moto/include/MT_Quaternion.h index aa2045fc56f..03b52efe600 100644 --- a/intern/moto/include/MT_Quaternion.h +++ b/intern/moto/include/MT_Quaternion.h @@ -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(); }; diff --git a/intern/moto/include/MT_Quaternion.inl b/intern/moto/include/MT_Quaternion.inl index 225b95b78ce..8b4fbc93c41 100644 --- a/intern/moto/include/MT_Quaternion.inl +++ b/intern/moto/include/MT_Quaternion.inl @@ -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; + } +} + 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(); |