void dGeomTriMeshGetPoint(dGeomID g, int Index, dReal u, dReal v, dVector3 Out){
    dUASSERT(g && g->type == dTriMeshClass, "argument not a trimesh");

    dxTriMesh* Geom = (dxTriMesh*)g;
    dVector3 dv[3];
    gim_trimesh_locks_work_data(&Geom->m_collision_trimesh);	
    gim_trimesh_get_triangle_vertices(&Geom->m_collision_trimesh, Index, dv[0],dv[1],dv[2]);
    GetPointFromBarycentric(dv, u, v, Out);
    gim_trimesh_unlocks_work_data(&Geom->m_collision_trimesh);
}
int dCollideCylinderTrimesh(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
{
    dIASSERT( skip >= (int)sizeof( dContactGeom ) );
    dIASSERT( o1->type == dCylinderClass );
    dIASSERT( o2->type == dTriMeshClass );
    dIASSERT ((flags & NUMC_MASK) >= 1);

    // Main data holder
    sData cData;

    // Assign ODE stuff
    cData.gCylinder	 = o1;
    cData.gTrimesh	 = (dxTriMesh*)o2;
    cData.iFlags	 = flags;
    cData.iSkip		 = skip;
    cData.gContact	 = contact;
    cData.nContacts  = 0;

    _InitCylinderTrimeshData(cData);

//*****at first , collide box aabb******//

    aabb3f test_aabb;

    test_aabb.minX = o1->aabb[0];
    test_aabb.maxX = o1->aabb[1];
    test_aabb.minY = o1->aabb[2];
    test_aabb.maxY = o1->aabb[3];
    test_aabb.minZ = o1->aabb[4];
    test_aabb.maxZ = o1->aabb[5];


    GDYNAMIC_ARRAY collision_result;
    GIM_CREATE_BOXQUERY_LIST(collision_result);

    gim_aabbset_box_collision(&test_aabb, &cData.gTrimesh->m_collision_trimesh.m_aabbset , &collision_result);

    if(collision_result.m_size==0)
    {
        GIM_DYNARRAY_DESTROY(collision_result);
        return 0;
    }
//*****Set globals for box collision******//

    int ctContacts0 = 0;
    cData.gLocalContacts = (sLocalContactData*)dALLOCA16(sizeof(sLocalContactData)*(cData.iFlags & NUMC_MASK));

    GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
    GIM_TRIMESH * ptrimesh = &cData.gTrimesh->m_collision_trimesh;

    gim_trimesh_locks_work_data(ptrimesh);


    for(unsigned int i=0; i<collision_result.m_size; i++)
    {
        const int Triint = boxesresult[i];

        dVector3 dv[3];
        gim_trimesh_get_triangle_vertices(ptrimesh, Triint,dv[0],dv[1],dv[2]);
        // test this triangle
        TestOneTriangleVsCylinder(cData , dv[0],dv[1],dv[2], false);

        // fill-in triangle index for generated contacts
        for (; ctContacts0<cData.nContacts; ctContacts0++)
            cData.gLocalContacts[ctContacts0].triIndex =  Triint;

        // Putting "break" at the end of loop prevents unnecessary checks on first pass and "continue"
        if(cData.nContacts	>= (cData.iFlags & NUMC_MASK))
        {
            break;
        }
    }

    gim_trimesh_unlocks_work_data(ptrimesh);
    GIM_DYNARRAY_DESTROY(collision_result);

    return _ProcessLocalContacts(cData);
}