[算法]三角形与立方体重叠测试

//AABBtriangle.h
#pragma once
/********************************************************/
/* AABB-triangle overlap test code */
/* Function: int triBoxOverlap(float boxcenter[3], float boxhalfsize[3], float triverts[3][3]); */
/********************************************************/
#include <math.h>
#include <stdio.h>
#define X 0
#define Y 1
#define Z 2
#define CROSS(dest,v1,v2) dest[0] = v1[1] * v2[2] - v1[2] * v2[1];dest[1] = v1[2] * v2[0] - v1[0] * v2[2];dest[2] = v1[0] * v2[1] - v1[1] * v2[0];
#define DOT(v1,v2) v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2]
#define SUB(dest,v1,v2)  dest[0] = v1[0] - v2[0];dest[1] = v1[1] - v2[1]; dest[2] = v1[2] - v2[2];
#define FINDMINMAX(x0,x1,x2,min,max) min = max = x0; if (x1 < min) min = x1; if (x1 > max) max = x1; if (x2 < min) min = x2; if (x2 > max) max = x2;

int planeBoxOverlap(float normal[3], float d, float maxbox[3]);

/*======================== X-tests ========================*/
#define AXISTEST_X01(a, b, fa, fb) p0 = a*v0[Y] - b*v0[Z];p2 = a*v2[Y] - b*v2[Z]; if (p0<p2) { min = p0; max = p2; } else { min = p2; max = p0; } rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; if (min>rad || max<-rad) return 0;
#define AXISTEST_X2(a, b, fa, fb)  p0 = a*v0[Y] - b*v0[Z]; p1 = a*v1[Y] - b*v1[Z]; if (p0<p1) { min = p0; max = p1; }else { min = p1; max = p0; } rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; if (min>rad || max<-rad) return 0;

/*======================== Y-tests ========================*/
#define AXISTEST_Y02(a, b, fa, fb) p0 = -a*v0[X] + b*v0[Z]; p2 = -a*v2[X] + b*v2[Z];if (p0<p2) { min = p0; max = p2; }else { min = p2; max = p0; } rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; if (min>rad || max<-rad) return 0;
#define AXISTEST_Y1(a, b, fa, fb)  p0 = -a*v0[X] + b*v0[Z]; p1 = -a*v1[X] + b*v1[Z];if (p0<p1) { min = p0; max = p1; }else { min = p1; max = p0; } rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; if (min>rad || max<-rad) return 0;

/*======================== Z-tests ========================*/
#define AXISTEST_Z12(a, b, fa, fb)  p1 = a*v1[X] - b*v1[Y];  p2 = a*v2[X] - b*v2[Y]; if (p2<p1) { min = p2; max = p1; }else { min = p1; max = p2; }rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; if (min>rad || max<-rad) return 0;
#define AXISTEST_Z0(a, b, fa, fb)   p0 = a*v0[X] - b*v0[Y];  p1 = a*v1[X] - b*v1[Y]; if (p0<p1) { min = p0; max = p1; }else { min = p1; max = p0; }rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; if (min>rad || max<-rad) return 0;

int triBoxOverlap(float boxcenter[3], float boxhalfsize[3], float triverts[3][3]);

  

//AABBtriangle.cpp
#include"AABBtriangle.h"

int planeBoxOverlap(float normal[3], float d, float maxbox[3])
{
	int q;
	float vmin[3], vmax[3];
	for (q = X; q <= Z; q++)
	{
		if (normal[q] > 0.0f)
		{
			vmin[q] = -maxbox[q];
			vmax[q] = maxbox[q];
		}
		else
		{
			vmin[q] = maxbox[q];
			vmax[q] = -maxbox[q];
		}
	}
	if (DOT(normal, vmin) + d > 0.0f) return 0;
	if (DOT(normal, vmax) + d >= 0.0f) return 1;
	return 0;
}

int triBoxOverlap(float boxcenter[3], float boxhalfsize[3], float triverts[3][3])
{
	/* use separating axis theorem to test overlap between triangle and box */
	/* need to test for overlap in these directions: */
	/* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
	/* we do not even need to test these) */
	/* 2) normal of the triangle */
	/* 3) crossproduct(edge from tri, {x,y,z}-directin) */
	/* this gives 3x3=9 more tests */

	float v0[3], v1[3], v2[3];
	float axis[3];
	float min, max, d, p0, p1, p2, rad, fex, fey, fez;
	float normal[3], e0[3], e1[3], e2[3];

	/* This is the fastest branch on Sun */
	/* move everything so that the boxcenter is in (0,0,0) */
	SUB(v0,triverts[0],boxcenter);
	SUB(v1, triverts[1], boxcenter);
	SUB(v2, triverts[2], boxcenter); 

	/* compute triangle edges */
	SUB(e0, v1, v0); /* tri edge 0 */
	SUB(e1, v2, v1); /* tri edge 1 */
	SUB(e2, v0, v2); /* tri edge 2 */

	/* Bullet 3: */
	/* test the 9 tests first (this was faster) */
	fex = fabs(e0[X]);
	fey = fabs(e0[Y]);
	fez = fabs(e0[Z]);
	AXISTEST_X01(e0[Z], e0[Y], fez, fey);
	AXISTEST_Y02(e0[Z], e0[X], fez, fex);
	AXISTEST_Z12(e0[Y], e0[X], fey, fex);

	fex = fabs(e1[X]);
	fey = fabs(e1[Y]);
	fez = fabs(e1[Z]);
	AXISTEST_X01(e1[Z], e1[Y], fez, fey);
	AXISTEST_Y02(e1[Z], e1[X], fez, fex);
	AXISTEST_Z0(e1[Y], e1[X], fey, fex);

	fex = fabs(e2[X]);
	fey = fabs(e2[Y]);
	fez = fabs(e2[Z]);
	AXISTEST_X2(e2[Z], e2[Y], fez, fey);
	AXISTEST_Y1(e2[Z], e2[X], fez, fex);
	AXISTEST_Z12(e2[Y], e2[X], fey, fex);

	/* Bullet 1: */
	/* first test overlap in the {x,y,z}-directions */
	/* find min, max of the triangle each direction, and test for overlap in */
	/* that direction -- this is equivalent to testing a minimal AABB around */
	/*  the triangle against the AABB */
	/* test in X-direction */
	FINDMINMAX(v0[X],v1[X],v2[X],min,max);
	if (min>boxhalfsize[X] || max<-boxhalfsize[X]) return 0;

	/* test in Y-direction */
	FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
	if (min>boxhalfsize[Y] || max<-boxhalfsize[Y]) return 0; 

	/* test in Z-direction */
	FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
	if (min>boxhalfsize[Z] || max<-boxhalfsize[Z]) return 0;

	/* Bullet 2: */
	/* test if the box intersects the plane of the triangle */
	/* compute plane equation of triangle: normal*x+d=0 */
	CROSS(normal, e0, e1);
	d = -DOT(normal, v0); /* plane eq: normal.x+d=0 */
	if (!planeBoxOverlap(normal, d, boxhalfsize)) return 0;
	return 1; /* box and triangle overlaps */

}

  

时间: 2024-12-21 14:24:38

[算法]三角形与立方体重叠测试的相关文章

Light Oj 1211 计算多个立方体重叠部分体积

Intersection of Cubes Time Limit:500MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice LightOJ 1211 Description You are given n cubes, each cube is described by two points in 3D space: (x1, y1, z1) being one corner of

物体检测算法 SSD 的训练和测试

GitHub:https://github.com/stoneyang/caffe_ssd Paper: https://arxiv.org/abs/1512.02325 1. 安装 caffe_SSD: git clone https://github.com/weiliu89/caffe.git cd caffe git checkout ssd 2. 编译该 caffe 文件,在主目录下: # Modify Makefile.config according to your Caffe i

泛型算法(三)之测试序列的性质的算法

1.all_of(InputIterator first, InputIterator last, UnaryPredicate pred) : C11算法.如果序列所有元素均满足谓词pred,则返回true 比如,判断一个序列中的元素是不是都小于0: std::vector<int> c; //添加元素{-10,-9,-8,-7,-6,-5,-4,-3,-2,-1} for (int i = 0; i < 10; i++) { c.push_back(i - 10); } //返回tr

判断三角形并使用Junit测试

  一.安装Junit,hamcrest和EclEmma的过程 1.下载Junit的jar包和hamcrest,目前它的版本是junit 4.12,可以从www.junit.org上下载. 2.打开eclipse,在要使用Junit的project名上,点击properties--java build path-libraries,点击Add External JARs,把Junit包点上就行了.如图1所示,点击Add External JARs,选择相应的Junit包. 图1 安装junit包

0330 复利算法5.0(包括测试)

更新说明: 本次程序和50黄柏堂同学一次完成 把C语言版本转换为JAVA: 更新了界面: 更新了测试: package fuli; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.IOException; import java.math.BigDecimal; import java.lang.Runtime; import javax.swing.JButton; imp

随机生成数,摘自算法竞赛入门经典P120-P123测试STL。

//#include<bits/stdc++.h> #include<cstring> #include<iostream> #include<cstdio> #include<time.h>///调用time的头文件. #include<algorithm> #include<vector> #include<cstdlib>///调用rand的头文件. #include<assert.h>///

3D图象算法(转)

 原文链接 3D简介 我们首先从坐标系统开始.你也许知道在2D里我们经常使用Ren?笛卡儿坐标系统在平面上来识别点.我们使用二维(X,Y):X表示水平轴坐标,Y表示纵轴坐标.在3维坐标系,我们增加了Z,一般用它来表示深度.所以为表示三维坐标系的一个点,我们用三个参数(X,Y,Z).这里有不同的笛卡儿三维系统可以使用.但是它们都是左手螺旋或右手螺旋的.右手螺旋是右手手指的卷曲方向指向Z轴正方向,而大拇指指向X轴正方向.左手螺旋是左手手指的卷曲方向指向Z轴负方向.实际上,我们可以在任何方向上旋转

跨越千年的RSA算法

跨越千年的RSA算法 数论,数学中的皇冠,最纯粹的数学.早在古希腊时代,人们就开始痴迷地研究数字,沉浸于这个几乎没有任何实用价值的思维游戏中.直到计算机诞生之后,几千年来的数论研究成果突然有了实际的应用,这个过程可以说是最为激动人心的数学话题之一.最近我在<程序员>杂志上连载了<跨越千年的 RSA 算法>,但受篇幅限制,只有一万字左右的内容.其实,从数论到 RSA 算法,里面的数学之美哪里是一万字能扯完的?在写作的过程中,我查了很多资料,找到了很多漂亮的例子,也积累了很多个人的思考

线段求交点的算法

算法一: 求两条线段所在直线的交点, 再判断交点是否在两条线段上. 求直线交点时 我们可通过直线的一般方程 ax+by+c=0 求得(方程中的abc为系数,不是前面提到的端点,另外也可用点斜式方程和斜截式方程,此处暂且不论). 然后根据交点的与线段端点的位置关系来判断交点是否在线段上. 公式如下图: 算法一思路比较清晰易懂, 但是性能并不高. 因为它在不确定交点是否有效(在线段上)之前, 就先去计算了交点, 耗费了较多的时间. 如果最后发现交点无效, 那么之前的计算就白折腾了. 而且整个计算的过