Ejemplo n.º 1
0
bool plane_intersection_line(const struct plane *p, const struct vec3 *v1,
		const struct vec3 *v2, float *t)
{
	float p1_dist, p2_dist, p1_abs_dist, dist2;
	bool  p1_over, p2_over;

	p1_dist = vec3_plane_dist(v1, p);
	p2_dist = vec3_plane_dist(v2, p);

	if (close_float(p1_dist, 0.0f, EPSILON)) {
		if (close_float(p2_dist, 0.0f, EPSILON))
			return false;

		*t = 0.0f;
		return true;
	} else if (close_float(p2_dist, 0.0f, EPSILON)) {
		*t = 1.0f;
		return true;
	}

	p1_over = (p1_dist > 0.0f);
	p2_over = (p2_dist > 0.0f);

	if (p1_over == p2_over)
		return false;

	p1_abs_dist = fabsf(p1_dist);
	dist2 = p1_abs_dist + fabsf(p2_dist);
	if (dist2 < EPSILON)
		return false;

	*t = p1_abs_dist / dist2;
	return true;
}
Ejemplo n.º 2
0
bool plane_tri_inside(const struct plane *p,
                     const struct vec3 *v1,
                     const struct vec3 *v2,
                     const struct vec3 *v3,
                     float precision)
{
	/* bit 1: part or all is behind the plane      */
	/* bit 2: part or all is in front of the plane */
	int sides = 0;
	float d1 = vec3_plane_dist(v1, p);
	float d2 = vec3_plane_dist(v2, p);
	float d3 = vec3_plane_dist(v3, p);

	if (d1 >= precision)
		sides = 2;
	else if (d1 <= -precision)
		sides = 1;

	if (d2 >= precision)
		sides |= 2;
	else if (d2 <= -precision)
		sides |= 1;

	if (d3 >= precision)
		sides |= 2;
	else if (d3 <= -precision)
		sides |= 1;

	return sides;
}
Ejemplo n.º 3
0
float bounds_min_dist(const struct bounds *b, const struct plane *p)
{
	struct vec3 center;
	float vec_len = vec3or_offset_len(b, &p->dir) * 0.5f;
	float center_dist;

	bounds_get_center(&center, b);
	center_dist = vec3_plane_dist(&center, p);

	return p->dist + center_dist - vec_len;
}
Ejemplo n.º 4
0
bool bounds_plane_test(const struct bounds *b, const struct plane *p)
{
	struct vec3 vmin, vmax;
	int i;

	for (i = 0; i < 3; i++) {
		if (p->dir.ptr[i] >= 0.0f) {
			vmin.ptr[i] = b->min.ptr[i];
			vmax.ptr[i] = b->max.ptr[i];
		} else {
			vmin.ptr[i] = b->max.ptr[i];
			vmax.ptr[i] = b->min.ptr[i];
		}
	}

	if (vec3_plane_dist(&vmin, p) > 0.0f)
		return BOUNDS_OUTSIDE;

	if (vec3_plane_dist(&vmax, p) >= 0.0f)
		return BOUNDS_PARTIAL;

	return BOUNDS_INSIDE;
}
Ejemplo n.º 5
0
int Polygon_RayIntersect(polygon_p p, float dir[3], float dot[3], float *t)
{
    float tt, u, v, E1[3], E2[3], P[3], Q[3], T[3];
    vertex_p vp;

    u = vec3_dot(p->plane, dir);
    if(fabs(u) < 0.001 /*|| vec3_plane_dist(p->plane, dot) < -0.001*/)          // FIXME: magick
    {
        return 0;                                                               // plane is parallel to the ray - no intersection
    }
    *t = - vec3_plane_dist(p->plane, dot);
    *t /= u;

    vp = p->vertices;                                                           // current polygon pointer
    vec3_sub(T, dot, vp[0].position);

    vec3_sub(E2, vp[1].position, vp[0].position)
    for(uint16_t i = 0; i < p->vertex_count - 2; i++, vp++)
    {
        vec3_copy(E1, E2)                                                       // PREV
        vec3_sub(E2, vp[2].position, p->vertices[0].position)                   // NEXT

        vec3_cross(P, dir, E2)
        vec3_cross(Q, T, E1)

        tt = vec3_dot(P, E1);
        u = vec3_dot(P, T);
        u /= tt;
        v = vec3_dot(Q, dir);
        v /= tt;
        tt = 1.0 - u - v;
        if((u <= 1.0) && (u >= 0.0) && (v <= 1.0) && (v >= 0.0) && (tt <= 1.0) && (tt >= 0.0))
        {
            return 1;
        }
    }
    return 0;
}
Ejemplo n.º 6
0
int Polygon_SplitClassify(polygon_p p, float n[4])
{
    int i;
    int positive = 0;
    int negative = 0;
    float dist;
    vertex_p v;

    v = p->vertices;
    for (i=0;i<p->vertex_count;i++,v++)
    {
        dist = vec3_plane_dist(n, v->position);
        if (dist > SPLIT_EPSILON)
        {
            positive++;
        }
        else if (dist < -SPLIT_EPSILON)
        {
            negative++;
        }
    }

    if(positive > 0 && negative == 0)
    {
        return SPLIT_FRONT;
    }
    else if(positive == 0 && negative > 0)
    {
        return SPLIT_BACK;
    }
    else if (positive < 1 && negative < 1)
    {
        return SPLIT_IN_PLANE;
    }

    return SPLIT_IN_BOTH;
}
Ejemplo n.º 7
0
/*
 * animated textures coordinates splits too!
 */
void Polygon_Split(polygon_p src, float n[4], polygon_p front, polygon_p back)
{
    float t, tmp, dir[3];
    vertex_t *curr_v, *prev_v, tv;
    float dist[2];

    vec4_copy(front->plane, src->plane);
    front->anim_id = src->anim_id;
    front->frame_offset = src->frame_offset;
    front->double_side = src->double_side;
    front->texture_index = src->texture_index;
    front->transparency = src->transparency;

    vec4_copy(back->plane, src->plane);
    back->anim_id = src->anim_id;
    back->frame_offset = src->frame_offset;
    back->double_side = src->double_side;
    back->texture_index = src->texture_index;
    back->transparency = src->transparency;

    curr_v = src->vertices;
    prev_v = src->vertices + src->vertex_count - 1;
    
    dist[0] = vec3_plane_dist(n, prev_v->position);
    for(uint16_t i = 0; i < src->vertex_count; i++)
    {
        dist[1] = vec3_plane_dist(n, curr_v->position);

        if(dist[1] > SPLIT_EPSILON)
        {
            if(dist[0] < -SPLIT_EPSILON)
            {
                vec3_sub(dir, curr_v->position, prev_v->position);
                vec3_ray_plane_intersect(prev_v->position, dir, n, tv.position, t);

                tv.normal[0] = prev_v->normal[0] + t * (curr_v->normal[0] - prev_v->normal[0]);
                tv.normal[1] = prev_v->normal[1] + t * (curr_v->normal[1] - prev_v->normal[1]);
                tv.normal[2] = prev_v->normal[2] + t * (curr_v->normal[2] - prev_v->normal[2]);
                vec3_norm(tv.normal, tmp);

                tv.color[0] = prev_v->color[0] + t * (curr_v->color[0] - prev_v->color[0]);
                tv.color[1] = prev_v->color[1] + t * (curr_v->color[1] - prev_v->color[1]);
                tv.color[2] = prev_v->color[2] + t * (curr_v->color[2] - prev_v->color[2]);
                tv.color[3] = prev_v->color[3] + t * (curr_v->color[3] - prev_v->color[3]);

                tv.tex_coord[0] = prev_v->tex_coord[0] + t * (curr_v->tex_coord[0] - prev_v->tex_coord[0]);
                tv.tex_coord[1] = prev_v->tex_coord[1] + t * (curr_v->tex_coord[1] - prev_v->tex_coord[1]);

                front->vertices[front->vertex_count++] = tv;
                back->vertices[back->vertex_count++] = tv;
            }
            front->vertices[front->vertex_count++] = *curr_v;
        }
        else if(dist[1] < -SPLIT_EPSILON)
        {
            if(dist[0] > SPLIT_EPSILON)
            {
                vec3_sub(dir, curr_v->position, prev_v->position);
                vec3_ray_plane_intersect(prev_v->position, dir, n, tv.position, t);

                tv.normal[0] = prev_v->normal[0] + t * (curr_v->normal[0] - prev_v->normal[0]);
                tv.normal[1] = prev_v->normal[1] + t * (curr_v->normal[1] - prev_v->normal[1]);
                tv.normal[2] = prev_v->normal[2] + t * (curr_v->normal[2] - prev_v->normal[2]);
                vec3_norm(tv.normal, tmp);

                tv.color[0] = prev_v->color[0] + t * (curr_v->color[0] - prev_v->color[0]);
                tv.color[1] = prev_v->color[1] + t * (curr_v->color[1] - prev_v->color[1]);
                tv.color[2] = prev_v->color[2] + t * (curr_v->color[2] - prev_v->color[2]);
                tv.color[3] = prev_v->color[3] + t * (curr_v->color[3] - prev_v->color[3]);

                tv.tex_coord[0] = prev_v->tex_coord[0] + t * (curr_v->tex_coord[0] - prev_v->tex_coord[0]);
                tv.tex_coord[1] = prev_v->tex_coord[1] + t * (curr_v->tex_coord[1] - prev_v->tex_coord[1]);

                front->vertices[front->vertex_count++] = tv;
                back->vertices[back->vertex_count++] = tv;
            }
            back->vertices[back->vertex_count++] = *curr_v;
        }
        else
        {
            front->vertices[front->vertex_count++] = *curr_v;
            back->vertices[back->vertex_count++] = *curr_v;
        }

        prev_v = curr_v;
        curr_v ++;
        dist[0] = dist[1];
    }
}
Ejemplo n.º 8
0
int Polygon_IntersectPolygon(polygon_p p1, polygon_p p2)
{
    float dist[3], dir[3], t, *result_buf, *result_v;
    vertex_p prev_v, curr_v;
    size_t buf_size;
    char cnt = 0;

    if(SPLIT_IN_BOTH != Polygon_SplitClassify(p1, p2->plane) || (SPLIT_IN_BOTH != Polygon_SplitClassify(p2, p1->plane)))
    {
        return 0;                                                               // quick check
    }

    buf_size = (p1->vertex_count + p2->vertex_count) * 3 * sizeof(float);
    result_buf = (float*)Sys_GetTempMem(buf_size);
    result_v = result_buf;

    /*
     * intersection of polygon p1 and plane p2
     */
    prev_v = p1->vertices + p1->vertex_count - 1;
    curr_v = p1->vertices;
    dist[0] = vec3_plane_dist(p2->plane, prev_v->position);
    for(uint16_t i = 0; i < p1->vertex_count; i++)
    {
        dist[1] = vec3_plane_dist(p2->plane, curr_v->position);
        if(dist[1] > SPLIT_EPSILON)
        {
            if(dist[0] < -SPLIT_EPSILON)
            {
                vec3_sub(dir, curr_v->position, prev_v->position);
                vec3_ray_plane_intersect(prev_v->position, dir, p2->plane, result_v, t);
                result_v += 3;
                cnt++;
            }
        }
        else if(dist[1] < -SPLIT_EPSILON)
        {
            if(dist[0] > SPLIT_EPSILON)
            {
                vec3_sub(dir, curr_v->position, prev_v->position);
                vec3_ray_plane_intersect(prev_v->position, dir, p2->plane, result_v, t);
                result_v += 3;
                cnt++;
            }
        }
        else
        {
            vec3_copy(result_v, curr_v->position);
            result_v += 3;
            cnt++;
        }

        if(cnt >= 2)
        {
            break;
        }
        dist[0] = dist[1];
        prev_v = curr_v;
        curr_v ++;
    }

    /*
     * splitting p2 by p1 split plane
     */
    prev_v = p2->vertices + p2->vertex_count - 1;
    curr_v = p2->vertices;
    dist[0] = vec3_plane_dist(p1->plane, prev_v->position);
    for(uint16_t i = 0; i < p2->vertex_count; i++)
    {
        dist[1] = vec3_plane_dist(p1->plane, curr_v->position);
        if(dist[1] > SPLIT_EPSILON)
        {
            if(dist[0] < -SPLIT_EPSILON)
            {
                vec3_sub(dir, curr_v->position, prev_v->position);
                vec3_ray_plane_intersect(prev_v->position, dir, p1->plane, result_v, t);
                result_v += 3;
                cnt++;
            }
        }
        else if(dist[1] < -SPLIT_EPSILON)
        {
            if(dist[0] > SPLIT_EPSILON)
            {
                vec3_sub(dir, curr_v->position, prev_v->position);
                vec3_ray_plane_intersect(prev_v->position, dir, p1->plane, result_v, t);
                result_v += 3;
                cnt++;
            }
        }
        else
        {
            vec3_copy(result_v, curr_v->position);
            result_v += 3;
            cnt++;
        }

        if(cnt >= 4)
        {
            break;
        }
        dist[0] = dist[1];
        prev_v = curr_v;
        curr_v ++;
    }

    vec3_cross(dir, p1->plane, p2->plane);                                      // vector of two planes intersection line
    t = ABS(dir[0]);
    dist[0] = ABS(dir[1]);
    dist[1] = ABS(dir[2]);
    int pn = PLANE_X;
    if(t < dist[0])
    {
        t = dist[0];
        pn = PLANE_Y;
    }
    if(t < dist[1])
    {
        pn = PLANE_Z;
    }

    switch(pn)
    {
        case PLANE_X:
            dist[0] = (result_buf[3+0] -  result_buf[0]) / dir[0];
            dist[1] = (result_buf[6+0] -  result_buf[0]) / dir[0];
            dist[2] = (result_buf[9+0] -  result_buf[0]) / dir[0];
            break;

        case PLANE_Y:
            dist[0] = (result_buf[3+1] -  result_buf[1]) / dir[1];
            dist[1] = (result_buf[6+1] -  result_buf[1]) / dir[1];
            dist[2] = (result_buf[9+1] -  result_buf[1]) / dir[1];
            break;

        case PLANE_Z:
            dist[0] = (result_buf[3+2] -  result_buf[2]) / dir[2];
            dist[1] = (result_buf[6+2] -  result_buf[2]) / dir[2];
            dist[2] = (result_buf[9+2] -  result_buf[2]) / dir[2];
            break;
    };

    Sys_ReturnTempMem(buf_size);

    if(dist[0] > 0)
    {
        return !((dist[1] < 0.0 && dist[2] < 0.0) || (dist[1] > dist[0] && dist[2] > dist[0]));
    }
    return !((dist[1] < dist[0] && dist[2] < dist[0]) || (dist[1] > 0.0 && dist[2] > 0.0));
}
Ejemplo n.º 9
0
void CDynamicBSP::AddPolygon(struct bsp_node_s *root, struct polygon_s *p)
{
    if(m_realloc_state)
    {
        return;
    }

    if(m_tree_allocated + 1024 > m_tree_buffer_size)
    {
        m_realloc_state = NEED_REALLOC_TREE_BUFF;
        return;
    }

    if(m_temp_allocated + 1024 > m_temp_buffer_size)
    {
        m_realloc_state = NEED_REALLOC_TEMP_BUFF;
        return;
    }

    if(root->polygons_front == NULL)
    {
        // we though root->front == NULL and root->back == NULL
        vec4_copy(root->plane, p->plane);
        p->next = NULL;
        this->AddBSPPolygon(root, p);
        return;
    }

    uint16_t positive = 0;
    uint16_t negative = 0;
    uint16_t in_plane = 0;
    float dist;
    vertex_p v = p->vertices;
    for(uint16_t i = 0; i < p->vertex_count; i++, v++)
    {
        dist = vec3_plane_dist(root->plane, v->position);
        if (dist > SPLIT_EPSILON)
        {
            positive++;
        }
        else if (dist < -SPLIT_EPSILON)
        {
            negative++;
        }
        else
        {
            in_plane++;
        }
    }

    if ((positive > 0) && (negative == 0))                  // SPLIT_FRONT
    {
        if (root->front == NULL)
        {
            root->front = this->CreateBSPNode();
        }
        this->AddPolygon(root->front, p);
    }
    else if ((positive == 0) && (negative > 0))             // SPLIT_BACK
    {
        if (root->back == NULL)
        {
            root->back = this->CreateBSPNode();
        }
        this->AddPolygon(root->back, p);
    }
    else if ((positive == 0) && (negative == 0))            // SPLIT_IN_PLANE
    {
        this->AddBSPPolygon(root, p);
    }
    else                                                    // SPLIT_IN_BOTH
    {
        polygon_p front, back;
        front = this->CreatePolygon(p->vertex_count + 2);
        front->vertex_count = 0;
        back = this->CreatePolygon(p->vertex_count + 2);
        back->vertex_count = 0;
        Polygon_Split(p, root->plane, front, back);

        if(root->front == NULL)
        {
            root->front = this->CreateBSPNode();
        }
        this->AddPolygon(root->front, front);
        if(root->back == NULL)
        {
            root->back = this->CreateBSPNode();
        }
        this->AddPolygon(root->back, back);
    }
}