/*!
In each contact
<ul>
<li> m_handle1 points to trimesh.
<li> m_handle2 points to NULL.
<li> m_feature1 Is a triangle index of trimesh.
</ul>

\param trimesh
\param center
\param radius
\param contacts A GIM_CONTACT array. Must be initialized
*/
void gim_trimesh_sphere_collision(GIM_TRIMESH * trimesh,vec3f center,GREAL radius, GDYNAMIC_ARRAY * contacts)
{
    contacts->m_size = 0;

    aabb3f test_aabb;
	test_aabb.minX = center[0]-radius;
	test_aabb.maxX = center[0]+radius;
	test_aabb.minY = center[1]-radius;
	test_aabb.maxY = center[1]+radius;
	test_aabb.minZ = center[2]-radius;
	test_aabb.maxZ = center[2]+radius;

	GDYNAMIC_ARRAY collision_result;
	GIM_CREATE_BOXQUERY_LIST(collision_result);

	gim_aabbset_box_collision(&test_aabb, &trimesh->m_aabbset , &collision_result);

	if(collision_result.m_size==0)
	{
	    GIM_DYNARRAY_DESTROY(collision_result);
	}

	//collide triangles
	//Locks trimesh
	gim_trimesh_locks_work_data(trimesh);
	 //dummy contacts
    GDYNAMIC_ARRAY dummycontacts;
    GIM_CREATE_CONTACT_LIST(dummycontacts);

	int cresult;
	unsigned int i;
	GUINT32 * boxesresult = GIM_DYNARRAY_POINTER(GUINT32,collision_result);
	GIM_TRIANGLE_CONTACT_DATA tri_contact_data;
	GIM_TRIANGLE_DATA tri_data;

	for(i=0;i<collision_result.m_size;i++)
	{
		gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data);
		cresult = gim_triangle_sphere_collision(&tri_data,center,radius,&tri_contact_data);
		if(cresult!=0)
		{
		    GIM_PUSH_CONTACT(dummycontacts, tri_contact_data.m_points[0],tri_contact_data.m_separating_normal ,tri_contact_data.m_penetration_depth,trimesh, 0, boxesresult[i],0);
		}
	}
	///unlocks
	gim_trimesh_unlocks_work_data(trimesh);
	///Destroy box result
	GIM_DYNARRAY_DESTROY(collision_result);

	 //merge contacts
    gim_merge_contacts(&dummycontacts,contacts);

    //Destroy dummy
    GIM_DYNARRAY_DESTROY(dummycontacts);
}
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);
}
/*!
Find the closest primitive collided by the ray
\param trimesh
\param capsule
\param contact
\param contacts A GIM_CONTACT array. Must be initialized
*/
void gim_trimesh_capsule_collision(GIM_TRIMESH * trimesh, GIM_CAPSULE_DATA * capsule, GDYNAMIC_ARRAY * contacts)
{
    contacts->m_size = 0;

    aabb3f test_aabb;
    CALC_CAPSULE_AABB((*capsule),test_aabb);

	GDYNAMIC_ARRAY collision_result;
	GIM_CREATE_BOXQUERY_LIST(collision_result);

	gim_aabbset_box_collision(&test_aabb, &trimesh->m_aabbset , &collision_result);

	if(collision_result.m_size==0)
	{
	    GIM_DYNARRAY_DESTROY(collision_result);
	}

	//collide triangles
	//Locks trimesh
	gim_trimesh_locks_work_data(trimesh);
	 //dummy contacts
    GDYNAMIC_ARRAY dummycontacts;
    GIM_CREATE_CONTACT_LIST(dummycontacts);

	int cresult;
	unsigned int i;
	GUINT * boxesresult = GIM_DYNARRAY_POINTER(GUINT,collision_result);
	GIM_TRIANGLE_DATA tri_data;
	GUINT old_contact_size;
	GIM_CONTACT * pcontact;

	for(i=0;i<collision_result.m_size;i++)
	{
	    old_contact_size = dummycontacts.m_size;
		gim_trimesh_get_triangle_data(trimesh,boxesresult[i],&tri_data);
		cresult = gim_triangle_capsule_collision(&tri_data, capsule, &dummycontacts);
		if(cresult!=0)
		{
		    pcontact = GIM_DYNARRAY_POINTER(GIM_CONTACT ,dummycontacts);
            pcontact+= old_contact_size;
		    while(old_contact_size<dummycontacts.m_size)
            {
                pcontact->m_handle1 = trimesh;
                pcontact->m_handle2 = capsule;
                pcontact->m_feature1 = boxesresult[i];
                pcontact->m_feature2 = 0;
                pcontact++;
                old_contact_size++;
            }
		}
	}
	///unlocks
	gim_trimesh_unlocks_work_data(trimesh);
	///Destroy box result
	GIM_DYNARRAY_DESTROY(collision_result);

	 //merge contacts
    gim_merge_contacts(&dummycontacts,contacts);

    //Destroy dummy
    GIM_DYNARRAY_DESTROY(dummycontacts);
}