Пример #1
0
// compute the vector VEC between a 3D point P0 and a line (
// passing through two 3D points P and S)
double vec_pt_to_line3D(double *P,double *S,double *P0,double *VEC)
{
	double diff10[3];
	double diff21[3];
	double dot_prod_diff10_diff21;
	double t,norm_diff21;
	double VT[3];
	double diffVT0[3];
	double norm_diffVT0;
	
	VEC_DIFF(diff10,P,P0);
	VEC_DIFF(diff21,S,P);
	VEC_LENGTH(norm_diff21,diff21);
	VEC_DOT_PRODUCT(dot_prod_diff10_diff21,diff10,diff21);
	t=-dot_prod_diff10_diff21 / ( norm_diff21*norm_diff21 );
	VEC_COPY(VT,P)
	VEC_ACCUM(VT,t,diff21);
	VEC_DIFF(diffVT0,VT,P0);
	
	for(int t=0;t<3;t++)
	{
		VEC[t] = P0[t];
		VEC[t+3] = VT[t];
	}
	
	VEC_LENGTH(norm_diffVT0,diffVT0);
	return norm_diffVT0;
}
Пример #2
0
/*
 * The uviewpoint subroutine computes and returns a 4x4 matrix that 
 * translates the origen to the point v1, puts the negative z axis
 * along the direction v21==v2-v1, and puts the y axis along the up
 * vector.
 */
void uviewpoint (gleDouble m[4][4],		/* returned */
                 gleDouble v1[3],		/* input */
                 gleDouble v2[3],		/* input */
                 gleDouble up[3])		/* input */
{
   gleDouble v_hat_21 [3];
   gleDouble trans_mat[4][4];
   gleDouble rot_mat[4][4];

   /* find the vector that points in the v21 direction */
   VEC_DIFF (v_hat_21, v2, v1);

   /* compute rotation matrix that takes -z axis to the v21 axis,
    * and y to the up dierction */
   uview_direction (rot_mat, v_hat_21, up);

   /* build matrix that translates the origin to v1 */
   IDENTIFY_MATRIX_4X4 (trans_mat);
   trans_mat[3][0] = v1[0];
   trans_mat[3][1] = v1[1];
   trans_mat[3][2] = v1[2];

   /* concatenate the matrices together */
   MATRIX_PRODUCT_4X4 (m, rot_mat, trans_mat);

}
Пример #3
0
void kalman_update_3x3(kalman_state_n* state, float* measurement,float** A, float** H)
{
    float** auxMat;
    auxMat=(float**)malloc(3*sizeof(float*));
    for (int i=0; i<3; i++) auxMat[i]=malloc(3*sizeof(float));
    float* auxVet;
    auxVet=(float*)malloc(3*sizeof(float));
   
    float pTrsp[3][3],Atrsp[3][3];
    
    /*predicted p*/
    TRANSPOSE_MATRIX_3X3(Atrsp, A);
    MATRIX_PRODUCT_3X3(auxMat, state->p, Atrsp);
    MATRIX_PRODUCT_3X3(state->p, A, auxMat);
    ACCUM_SCALE_MATRIX_3X3(state->p, 1, state->q)
    /*predicted x*/
    MAT_DOT_VEC_3X3(state->x, A, state->x);
//    state->x=xaux;

    /*kalman gain*/
    float Htrsp[3][3], S[3][3], Sinv[3][3], B[3][3], det;
    TRANSPOSE_MATRIX_3X3(Htrsp, H);
    TRANSPOSE_MATRIX_3X3(pTrsp, state->p);
    MATRIX_PRODUCT_3X3(auxMat, pTrsp, Htrsp);
    MATRIX_PRODUCT_3X3(S, H, auxMat);
    ACCUM_SCALE_MATRIX_3X3(S, 1.0, state->r);
 
    MATRIX_PRODUCT_3X3(B, H, pTrsp);
 
    INVERT_3X3(Sinv, det, S);
    MATRIX_PRODUCT_3X3(auxMat, Sinv, B);
    TRANSPOSE_MATRIX_3X3(state->k, auxMat);
//    MAT_PRINT_3X3(state->k);

    /*estimated x*/    
    MAT_DOT_VEC_3X3(auxVet, H, state->x);
    VEC_DIFF(auxVet, measurement, auxVet);
    MAT_DOT_VEC_3X3(auxVet, state->k, auxVet);
    VEC_SUM(state->x, state->x, auxVet);
    
    /*estimated P*/
    MATRIX_PRODUCT_3X3(auxMat, H, state->p);
    MATRIX_PRODUCT_3X3(auxMat, state->k, auxMat);
    ACCUM_SCALE_MATRIX_3X3(state->p, -1.0, auxMat);
   
    /*out*/
    MAT_DOT_VEC_3X3(measurement, H, state->x);
    
    for (int i=0; i<3; i++) free(auxMat[i]);
    free(auxMat);
    free(auxVet);
}
/*!

\param triangle
\param s1
\param s2
\param contacts Contains the closest points on the segment (1,2), and the normal points to segment, and m_depth contains the distance

\post The contacts array is not set to 0. It adds aditional contacts
*/
void gim_closest_point_triangle_segment(GIM_TRIANGLE_DATA * triangle, vec3f s1,vec3f s2, GDYNAMIC_ARRAY * contacts)
{
    vec3f segment_points[4];
    vec3f closest_points[2];
    GUINT intersection_type, out_edge= 10;
    GREAL dis, dis_temp,perpend;
    vec4f sdiff;

    dis = DISTANCE_PLANE_POINT(triangle->m_planes.m_planes[0],s1);
    dis_temp = DISTANCE_PLANE_POINT(triangle->m_planes.m_planes[0],s2);

    if(dis<=0.0f && dis_temp<=0.0f) return;

    VEC_DIFF(sdiff,s2,s1);
    perpend = VEC_DOT(sdiff,triangle->m_planes.m_planes[0]);

    if(!IS_ZERO(perpend)) // Not perpendicular
    {
        if(dis<dis_temp)
        {
            VEC_COPY(closest_points[0],s1);
        }
        else
        {
            dis = dis_temp;
            VEC_COPY(closest_points[0],s2);
        }

        //Testing segment vertices over triangle
        if(dis>=0.0f && dis_temp>=0.0f)
        {
            POINT_IN_HULL(closest_points[0],(&triangle->m_planes.m_planes[1]),3,out_edge);

            if(out_edge==0)//Point over face
            {
                GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
                return;
            }
        }
        else
        {

            PLANE_CLIP_SEGMENT(s1,s2,triangle->m_planes.m_planes[0],closest_points[1]);

            POINT_IN_HULL(closest_points[1],(&triangle->m_planes.m_planes[1]),3,out_edge);

            if(out_edge==0)//Point over face
            {
                GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
                return;
            }
        }

    }
    else // Perpendicular Face
    {
        //out_edge=10
        //Clip segment by triangle
    //    Edge1
        PLANE_CLIP_SEGMENT_CLOSEST(s1,s2,triangle->m_planes.m_planes[1],segment_points[0],segment_points[1],intersection_type);
        if(intersection_type==0||intersection_type==1)
        {
            out_edge = 0;
            VEC_COPY(closest_points[0],segment_points[0]);
        }
        else
        {
            //Edge2
            PLANE_CLIP_SEGMENT_CLOSEST(segment_points[0],segment_points[1],triangle->m_planes.m_planes[2],segment_points[2],segment_points[3],intersection_type);
            if(intersection_type==0||intersection_type==1)
            {
                out_edge = 1;
                VEC_COPY(closest_points[0],segment_points[3]);
            }
            else
            {
                //Edge3
                PLANE_CLIP_SEGMENT_CLOSEST(segment_points[2],segment_points[3],triangle->m_planes.m_planes[3],closest_points[0],closest_points[1],intersection_type);
                if(intersection_type==0||intersection_type==1)
                {
                    out_edge = 2;
                }
            }
        }
        //POST closest_points[0] and closest_points[1] are inside the triangle, if out_edge>2
        if(out_edge>2) // Over triangle
        {
            dis = VEC_DOT(closest_points[0],triangle->m_planes.m_planes[0]);
            GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
            GIM_PUSH_CONTACT((*contacts),closest_points[1] ,triangle->m_planes.m_planes[0] ,dis,0, 0, 0,0);
            return;
        }
    }

    //Find closest edges
    out_edge = 10;
    dis = G_REAL_INFINITY;
    GUINT i;
    for(i=0;i<3;i++)
    {
        SEGMENT_COLLISION(s1,s2,triangle->m_vertices[i],triangle->m_vertices[(i+1)%3],segment_points[0],segment_points[1]);
        VEC_DIFF(sdiff,segment_points[0],segment_points[1]);
        dis_temp = VEC_DOT(sdiff,sdiff);
        if(dis_temp< dis)
        {
            dis = dis_temp;
            out_edge = i;
            VEC_COPY(closest_points[0],segment_points[0]);
            VEC_COPY(closest_points[1],sdiff);//normal
        }
    }
    if(out_edge>2) return ;// ???? ASSERT this please

    if(IS_ZERO(dis))
    {
        //Set face plane
        GIM_PUSH_CONTACT((*contacts),closest_points[0] ,triangle->m_planes.m_planes[0] ,0.0f,0, 0, 0,0);

    }
    else
    {
        GIM_SQRT(dis,dis);
        VEC_SCALE(closest_points[1],(1.0f/dis),closest_points[1]);//normal
        GIM_PUSH_CONTACT((*contacts),closest_points[0] ,closest_points[1],dis,0, 0, 0,0);
    }
}
int gim_triangle_sphere_collision(
							GIM_TRIANGLE_DATA *tri,
							vec3f center, GREAL radius,
							GIM_TRIANGLE_CONTACT_DATA * contact_data)
{
    contact_data->m_point_count = 0;

    //Find Face plane distance
    GREAL  dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[0],center);
    if(dis>radius) return 0; //out
    if(dis<-radius) return 0;//Out of triangle
    contact_data->m_penetration_depth = dis;

    //Find the most edge
    GUINT32 most_edge = 4;//no edge
    GREAL max_dis = 0.0f;
    dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[1],center);
    if(dis>radius) return 0;//Out of triangle
    if(dis>0.0f)
    {
        max_dis = dis;
        most_edge = 0;
    }

    dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[2],center);
    if(dis>radius) return 0;//Out of triangle
    if(dis>max_dis)// && dis>0.0f)
    {
        max_dis = dis;
        most_edge = 1;
    }

    dis = DISTANCE_PLANE_POINT(tri->m_planes.m_planes[3],center);
    if(dis>radius) return 0;//Out of triangle
    if(dis>max_dis)// && dis>0.0f)
    {
        max_dis = dis;
        most_edge = 2;
    }

    if(most_edge == 4) //Box is into triangle
    {
        //contact_data->m_penetration_depth = dis is set above
        //Find Face plane point
        VEC_COPY(contact_data->m_separating_normal,tri->m_planes.m_planes[0]);
        //Find point projection on plane
        if(contact_data->m_penetration_depth>=0.0f)
        {
            VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
        }
        else
        {
            VEC_SCALE(contact_data->m_points[0],radius,contact_data->m_separating_normal);
        }
        contact_data->m_penetration_depth = radius - contact_data->m_penetration_depth;

        VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
        //Scale normal for pointing to triangle
        VEC_SCALE(contact_data->m_separating_normal,-1.0f,contact_data->m_separating_normal);
        contact_data->m_point_count = 1;
        return 1;
    }
    //find the edge
    vec3f e1,e2;
    VEC_COPY(e1,tri->m_vertices[most_edge]);
    VEC_COPY(e2,tri->m_vertices[(most_edge+1)%3]);

    CLOSEST_POINT_ON_SEGMENT(contact_data->m_points[0],center,e1,e2);
    //find distance
    VEC_DIFF(e1,center,contact_data->m_points[0]);
    VEC_LENGTH(e1,dis);
    if(dis>radius) return 0;

    contact_data->m_penetration_depth = radius - dis;

    if(IS_ZERO(dis))
    {
        VEC_COPY(contact_data->m_separating_normal,tri->m_planes.m_planes[most_edge+1]);
        VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
        VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
    }
    else
    {
        VEC_SCALE(contact_data->m_separating_normal,1.0f/dis,e1);
        VEC_SCALE(contact_data->m_points[0],-radius,contact_data->m_separating_normal);
        VEC_SUM(contact_data->m_points[0],contact_data->m_points[0],center);
    }

    //Scale normal for pointing to triangle
    VEC_SCALE(contact_data->m_separating_normal,-1.0f,contact_data->m_separating_normal);

    contact_data->m_point_count = 1;
    return 1;

}