Commits

Richard Jones committed ace0495

add some more material, contact and joint bits; add capsule

  • Participants
  • Parent commits 68c817c

Comments (0)

Files changed (2)

File cython/newton.pxd

 
 cdef extern from '../newton/Newton.h':
 
+    cdef cppclass dgContactMaterial:
+        VoidPtr GetUserData()
+
 #---------------------------------------------------------------------------------------------------
 # Base (hidden) structures.
 #---------------------------------------------------------------------------------------------------
         
     # struct NewtonJointRecord
     cdef struct NewtonJointRecord:
-        pass
+        float m_attachmenMatrix_0[4][4]
+        float m_attachmenMatrix_1[4][4]
+        float m_minLinearDof[3]
+        float m_maxLinearDof[3]
+        float m_minAngularDof[3]
+        float m_maxAngularDof[3]
+        NewtonBodyConstPtr m_attachBody_0
+        NewtonBodyConstPtr m_attachBody_1
+        float m_extraParameters[16]
+        int    m_bodiesCollisionOn
+        char m_descriptionType[32]
     ctypedef NewtonJointRecord * NewtonJointRecordPtr 'NewtonJointRecord *'
     ctypedef NewtonJointRecord * NewtonJointRecordConstPtr 'const NewtonJointRecord *'
     

File cython/newton.pyx

 #    void NewtonTreeCollisionSetFaceAtribute(NewtonCollisionConstPtr treeCollision, ConstIntPtr faceIndexArray, int attribute) 
 #    int NewtonTreeCollisionGetVertexListIndexListInAABB(NewtonCollisionConstPtr treeCollision, ConstFloatPtr p0, ConstFloatPtr p1, ConstFloatPtrPtr vertexArray, int* vertexCount, int* vertexStrideInBytes, ConstIntPtr indexList, int maxIndexCount, ConstIntPtr faceAttribute) 
 
-
 #---------------------------------------------------------------------------------------------------
 # Physics material related functions.
 #---------------------------------------------------------------------------------------------------
 cdef class Material:
     cdef newton.NewtonWorldPtr _world
     cdef public int _group_id
+    cdef public dict callbacks
+
+    def __cinit__(self):
+        self._world = NULL
+        self._group_id = 0
+        self.callbacks = {}
     
     def __repr__(self):
         return '<Material %d @0x%x>' % (self._group_id, id(self))
         newton.NewtonMaterialSetDefaultFriction(self._world, self._group_id,
             other._group_id, static, kinetic)
 
+    # NewtonMaterialSetCollisionCallback
+    def set_collision_callback(self, Material other, user_data,
+            aabb_overlap=None, contacts_process=None):
+        # TODO this is UNTESTED as the contacts_process user data stuff needs work
+        self.callbacks[other._group_id] = dict(
+            aabb_overlap=aabb_overlap,
+            contacts_process=contacts_process,
+        )
+        # TODO: user data, and how is it passed to the callbacks anyway???
+        NewtonMaterialSetCollisionCallback(self._world, self._group_id,
+            other._group_id, NULL, Material_aabb_overlap_callback,
+            Material_contacts_process_callback)
+
+#---------------------------------------------------------------------------------------------------
+# Joint and constraints related functions.
+#---------------------------------------------------------------------------------------------------
+
+cdef class Joint:
+    cdef newton.NewtonWorldPtr _world
+    cdef newton.NewtonJointConstPtr _joint
+    cdef newton.NewtonJointRecord _info
+    
+    cdef setup(self, newton.NewtonJointConstPtr joint,
+            newton.NewtonWorldPtr world):
+        self._joint = joint
+        NewtonJointGetInfo(self._joint, &self._info)
+        if world is NULL:
+            assert self._info.m_attachBody_0 is not NULL, 'm_attachBody_0 is NULL'
+            body0 = <Body>NewtonBodyGetUserData(self._info.m_attachBody_0)
+            self._world = body0._world
+        else:
+            self._world = world
+
+    cdef Material get_material(self):
+        id0 = NewtonBodyGetMaterialGroupID(self._info.m_attachBody_0)
+        id1 = NewtonBodyGetMaterialGroupID(self._info.m_attachBody_1)
+        return <Material>newton.NewtonMaterialGetUserData(self._world, id0, id1)
+    
+    # NewtonDestroyJoint
+    def __dealloc__(self):
+        if self._world is not NULL and self._joint is not NULL:
+            newton.NewtonDestroyJoint(self._world, self._joint)
+
+cdef class ContactJoint(Joint):
+    # NewtonContactJointGetContactCount
+    def __len__(self):
+        return newton.NewtonContactJointGetContactCount(self._joint)
+
+    def __iter__(self):
+        j = ContactJointIter()
+        j._world = self._world
+        j._joint = self._joint
+        return j
+
+cdef class ContactJointIter:
+    cdef newton.NewtonWorldPtr _world
+    cdef newton.NewtonJointConstPtr _joint
+
+    # actually a dgContactMaterial, but this is easier
+    cdef newton.VoidPtr _current
+
+    def next(self):
+        if self._current is NULL:
+            self._current = NewtonContactJointGetFirstContact(self._joint)
+        else:
+            self._current = NewtonContactJointGetNextContact(self._joint, self._current)
+        if self._current is NULL:
+            raise StopIteration
+        c = Contact()
+        c._world = self._world
+        c._contact = self._current
+        return c
+
+cdef class Contact:
+    cdef newton.NewtonWorldPtr _world
+    cdef newton.ConstVoidPtr _contact
+
+    '''
+    # NewtonContactGetMaterial
+    def get_material(self):
+        m = NewtonContactGetMaterial(self._contact).group_id
+        return <Material>newton.NewtonMaterialGetUserData(m)
+    '''
 
 #---------------------------------------------------------------------------------------------------
 # Body related functions.
 cdef class Body:
     cdef newton.NewtonWorldPtr _world
     cdef newton.NewtonBodyPtr _body
-    callbacks = {}
-    
+    cdef public dict callbacks
+
     def __cinit__(self):
-        pass
+        self._world = NULL
+        self._body = NULL
+        self.callbacks = {}
     
     # NewtonDestroyBody
     def __dealloc__(self):
     # NewtonConstraintCreateUpVector
     def create_up_vector(self, x, y, z):
         cdef float *vector = [x, y, z]
+        cdef NewtonJointConstPtr _j = newton.NewtonConstraintCreateUpVector(self._world, vector, self._body)
         j = Joint()
-        j._world = self._world
-        j._joint = newton.NewtonConstraintCreateUpVector(self._world, vector, self._body)
+        j.setup(_j, self._world)
         return j
 
     # NewtonBodySetMaterialGroupID(NewtonBodyConstPtr body, int id)
 
 
 #---------------------------------------------------------------------------------------------------
-# Joint and constraints related functions.
+# Physics material related callback support.
 #---------------------------------------------------------------------------------------------------
 
-cdef class Joint:
-    cdef newton.NewtonWorldPtr _world
-    cdef newton.NewtonJointPtr _joint
-    callbacks = {}
-    
-    def __cinit__(self):
-        pass
-    
-    # NewtonDestroyJoint
-    def __dealloc__(self):
-        if self._world is not NULL and self._joint is not NULL:
-            newton.NewtonDestroyJoint(self._world, self._joint)
+# Glue for NewtonOnAABBOverlap callback
+cdef int Material_aabb_overlap_callback(newton.NewtonMaterialConstPtr m,
+        newton.NewtonBodyConstPtr body0, newton.NewtonBodyConstPtr body1, int threadIndex):
+    p_body0 = <Body>newton.NewtonBodyGetUserData(body0)
+    p_body1 = <Body>newton.NewtonBodyGetUserData(body1)
+
+    id0 = NewtonBodyGetMaterialGroupID(body0)
+    id1 = NewtonBodyGetMaterialGroupID(body1)
+    material = <Material>newton.NewtonMaterialGetUserData(p_body0._world, id0, id1)
+
+    return material.callbacks['force_torque'](p_body0, p_body1, threadIndex)
+
+# Glue for NewtonContactsProcess callback
+cdef void Material_contacts_process_callback(newton.NewtonJointConstPtr contact,
+        float timestep, int threadIndex):
+    # right, now we can return our Joint
+    j = Joint()
+    j.setup(contact, NULL)
+    j.get_material().callbacks['contacts_process'](j)
+
 
 #---------------------------------------------------------------------------------------------------
 # World related functions.
         collision._collision = newton.NewtonCreateBox(self._world, dx, dy, dz, 0, _matrix)
         return collision
 
+    # NewtonCreateCapsule
+    def create_capsule(self, float radius, float height, int shape_id, offset_matrix=None):
+        cdef float *_matrix
+        if offset_matrix is None:
+            _matrix = NULL
+        else:
+            raise NotImplementedError
+        collision = Collision()
+        collision._world = self._world
+        collision._collision = newton.NewtonCreateCapsule(self._world, radius, height,
+            shape_id, _matrix)
+        return collision
+
     # NewtonCreateTreeCollision
     def create_tree_collision(self, int shape_id):
         collision = TreeCollision()