/*!
\pre gim_trimesh_locks_work_data must be called before
*/
void gim_trimesh_update_aabbset(GIM_TRIMESH * trimesh)
{
    vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);
    assert(transformed_vertices);

    GUINT32 * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT32,trimesh->m_tri_index_buffer,0);
    assert(triangle_indices);
    // box set
    aabb3f * paabb = trimesh->m_aabbset.m_boxes;
    GUINT32 triangle_count = gim_trimesh_get_triangle_count(trimesh);
    float * v1,*v2,*v3;
    GUINT32 i;
    for (i=0; i<triangle_count;i++)
    {
        v1 = &transformed_vertices[triangle_indices[0]][0];
        v2 = &transformed_vertices[triangle_indices[1]][0];
        v3 = &transformed_vertices[triangle_indices[2]][0];
        COMPUTEAABB_FOR_TRIANGLE((*paabb),v1,v2,v3);
        triangle_indices+=3;
        paabb++;
    }
    //Clear planes cache
    GIM_BITSET_CLEAR_ALL(trimesh->m_planes_cache_bitset);
    //Sorts set
    gim_aabbset_update(&trimesh->m_aabbset);
}
void gim_trimesh_get_triangle_vertices(GIM_TRIMESH * trimesh, GUINT32 triangle_index, vec3f v1,vec3f v2,vec3f v3)
{
    vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);

    GUINT32 * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT32,trimesh->m_tri_index_buffer,triangle_index*3);

    //Copy the vertices
    VEC_COPY(v1,transformed_vertices[triangle_indices[0]]);
    VEC_COPY(v2,transformed_vertices[triangle_indices[1]]);
    VEC_COPY(v3,transformed_vertices[triangle_indices[2]]);
}
/*!

\param trimesh
\param plane vec4f plane
\param contacts A vec4f array. Must be initialized (~100). Each element have the coordinate point in the first 3 elements, and vec4f[3] has the penetration depth.
*/
void gim_trimesh_plane_collision(GIM_TRIMESH * trimesh,vec4f plane, GDYNAMIC_ARRAY * contacts)
{
    contacts->m_size = 0;
    char classify;
    PLANE_CLASSIFY_BOX(plane,trimesh->m_aabbset.m_global_bound,classify);
    if(classify>1) return; // in front of plane

    //Locks mesh
    gim_trimesh_locks_work_data(trimesh);
    //Get vertices
    GUINT32 i, vertcount = trimesh->m_transformed_vertex_buffer.m_element_count;
    vec3f * vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);

    GREAL dist;
    vec4f * result_contact;

    for (i=0; i<vertcount; i++)
    {
        dist = DISTANCE_PLANE_POINT(plane,vertices[i]);
        if(dist<=0.0f)
        {
            GIM_DYNARRAY_PUSH_EMPTY(vec4f,(*contacts));
            result_contact = GIM_DYNARRAY_POINTER_LAST(vec4f,(*contacts));
            VEC_COPY((*result_contact),vertices[i]);
            (*result_contact)[3] = -dist;
        }
    }
    gim_trimesh_unlocks_work_data(trimesh);
}
void gim_trimesh_get_triangle_data(GIM_TRIMESH * trimesh, GUINT32 triangle_index, GIM_TRIANGLE_DATA * tri_data)
{
    vec3f * transformed_vertices = GIM_BUFFER_ARRAY_POINTER(vec3f,trimesh->m_transformed_vertex_buffer,0);

    GUINT32 * triangle_indices = GIM_BUFFER_ARRAY_POINTER(GUINT32,trimesh->m_tri_index_buffer,triangle_index*3);


    //Copy the vertices
    VEC_COPY(tri_data->m_vertices[0],transformed_vertices[triangle_indices[0]]);
    VEC_COPY(tri_data->m_vertices[1],transformed_vertices[triangle_indices[1]]);
    VEC_COPY(tri_data->m_vertices[2],transformed_vertices[triangle_indices[2]]);

    //Get the planes
    GIM_TRIPLANES_CACHE * planes = GIM_DYNARRAY_POINTER(GIM_TRIPLANES_CACHE,trimesh->m_planes_cache_buffer);
    planes += triangle_index;

    //verify planes cache
    GUINT32 bit_eval;
    GIM_BITSET_GET(trimesh->m_planes_cache_bitset,triangle_index,bit_eval);
    if(bit_eval == 0)// Needs to calc the planes
    {
        //Calc the face plane
        TRIANGLE_PLANE(tri_data->m_vertices[0],tri_data->m_vertices[1],tri_data->m_vertices[2],planes->m_planes[0]);
        //Calc the edge 1
        EDGE_PLANE(tri_data->m_vertices[0],tri_data->m_vertices[1],(planes->m_planes[0]),(planes->m_planes[1]));

        //Calc the edge 2
        EDGE_PLANE(tri_data->m_vertices[1],tri_data->m_vertices[2],(planes->m_planes[0]),(planes->m_planes[2]));

        //Calc the edge 3
        EDGE_PLANE(tri_data->m_vertices[2],tri_data->m_vertices[0],(planes->m_planes[0]), (planes->m_planes[3]));

        //mark
        GIM_BITSET_SET(trimesh->m_planes_cache_bitset,triangle_index);
    }


    VEC_COPY_4((tri_data->m_planes.m_planes[0]),(planes->m_planes[0]));//face plane
    VEC_COPY_4((tri_data->m_planes.m_planes[1]),(planes->m_planes[1]));//edge1
    VEC_COPY_4((tri_data->m_planes.m_planes[2]),(planes->m_planes[2]));//edge2
    VEC_COPY_4((tri_data->m_planes.m_planes[3]),(planes->m_planes[3]));//edge3
}