www.pudn.com > 林海血原源代码.zip > CMath.cpp


// CMath.cpp: implementation of the CMath class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "CMath.h" 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
CMath::CMath() 
{} 
CMath::~CMath() 
{} 
///////////////////////////// 
 
bool CMath::IsLineSegmentCutByPolygon(VERTEX v1 ,VERTEX v2,VERTEX* pv,int num) 
{ 
	if(num<3)return false; 
	PLANE plane; 
	plane=GetPlaneEquation(pv,num); 
	///////////如果两点在同一侧 
	if((ClassifyPointPlane(v1,plane)*ClassifyPointPlane(v2,plane))>=0) 
		return false; 
	//////////////获得线段与平面的交点 
	VERTEX intersection; 
	intersection=GetIntersection(v1,v2,plane); 
	///////////包围盒粗略判断 
	float maxx,minx,  maxy,miny,  maxz,minz; 
	maxx=minx=pv[0].xpos; 
	maxy=miny=pv[0].ypos; 
	maxz=minz=pv[0].zpos; 
	for(int i=1;imaxx)maxx=pv[i].xpos; 
		if(pv[i].xposmaxy)maxy=pv[i].ypos; 
		if(pv[i].yposmaxz)maxz=pv[i].zpos; 
		if(pv[i].zposmaxx || intersection.xposmaxy || intersection.yposmaxz || intersection.zposabsC) 
		{   //////比较 Z 轴坐标 
            VERTEX sect[6];/////可能有重复的交点,如顶点 
            int  index=0; 
			for( i=0;i<(num-1);i++) 
			{ 
				if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p)) 
				{ 
                     sect[index]=GetIntersection(pv[i],pv[i+1],p); 
					 index++; 
				} 
			} 
			if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p)) 
			{ 
                 sect[index]=GetIntersection(pv[0],pv[num-1],p); 
				 index++; 
			} 
			///////////////////////////// 
			float maxzz,minzz; 
			maxzz=minzz=sect[0].zpos; 
			for(i=0;imaxzz)maxzz=sect[i].zpos; 
				if(sect[i].zposmaxzz || intersection.zposmaxyy)maxyy=sect[i].ypos; 
				if(sect[i].yposmaxyy || intersection.yposabsC) 
		{   //////比较 Z 轴坐标 
            VERTEX sect[6];/////可能有重复的交点,如顶点 
            int  index=0; 
			for( i=0;i<(num-1);i++) 
			{ 
				if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p)) 
				{ 
                     sect[index]=GetIntersection(pv[i],pv[i+1],p); 
					 index++; 
				} 
			} 
			if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p)) 
			{ 
                 sect[index]=GetIntersection(pv[0],pv[num-1],p); 
				 index++; 
			} 
			///////////////////////////// 
			float maxzz,minzz; 
			maxzz=minzz=sect[0].zpos; 
			for(i=0;imaxzz)maxzz=sect[i].zpos; 
				if(sect[i].zposmaxzz || intersection.zposmaxxx)maxxx=sect[i].xpos; 
				if(sect[i].xposmaxxx || intersection.xposabsB) 
		{   //////比较 Y 轴坐标 
            VERTEX sect[6];/////可能有重复的交点,如顶点 
            int  index=0; 
			for( i=0;i<(num-1);i++) 
			{ 
				if(ClassifyPointPlane(pv[i],p)!=ClassifyPointPlane(pv[i+1],p)) 
				{ 
                     sect[index]=GetIntersection(pv[i],pv[i+1],p); 
					 index++; 
				} 
			} 
			if(ClassifyPointPlane(pv[0],p)!=ClassifyPointPlane(pv[num-1],p)) 
			{ 
                 sect[index]=GetIntersection(pv[0],pv[num-1],p); 
				 index++; 
			} 
			///////////////////////////// 
			float maxyy,minyy; 
			maxyy=minyy=sect[0].ypos; 
			for(i=0;imaxyy)maxyy=sect[i].ypos; 
				if(sect[i].yposmaxyy || intersection.yposmaxxx)maxxx=sect[i].xpos; 
				if(sect[i].xposmaxxx || intersection.xposbd.maxx && v2.xpos>bd.maxx)return false; 
	if(v1.xposbd.maxy && v2.ypos>bd.maxy)return false; 
	if(v1.yposbd.maxz && v2.zpos>bd.maxz)return false; 
	if(v1.zpos=0) 
		return false; 
	//////////////获得线段与平面的交点 
	VERTEX intersection; 
	intersection=GetIntersection(v1,v2,plane); 
	///////////包围盒判断 
	float maxx,minx,  maxy,miny,  maxz,minz; 
	maxx=minx=va.xpos; 
	maxy=miny=va.ypos; 
	maxz=minz=va.zpos; 
 
		if(vb.xpos>maxx)maxx=vb.xpos; 
		if(vb.xposmaxy)maxy=vb.ypos; 
		if(vb.yposmaxz)maxz=vb.zpos; 
		if(vb.zposmaxx)maxx=vc.xpos; 
		if(vc.xposmaxy)maxy=vc.ypos; 
		if(vc.yposmaxz)maxz=vc.zpos; 
		if(vc.zposmaxx)maxx=vd.xpos; 
		if(vd.xposmaxy)maxy=vd.ypos; 
		if(vd.yposmaxz)maxz=vd.zpos; 
		if(vd.zposmaxx || intersection.xposmaxy || intersection.yposmaxz || intersection.zposxpos+plane.B*pVertices->ypos+plane.C*pVertices->zpos); 
	} 
	return plane; 
} 
 
PLANE CMath::GetPlaneEquation(VERTEX v1,VERTEX v2,VERTEX v3) 
{ 
	PLANE plane; 
   	NORMAL N12,N13,N; 
   	////////////calculate n12 n13 
   	N12.nx=v2.xpos-v1.xpos; 
   	N12.ny=v2.ypos-v1.ypos; 
   	N12.nz=v2.zpos-v1.zpos; 
 
   	N13.nx=v3.xpos-v1.xpos; 
   	N13.ny=v3.ypos-v1.ypos; 
   	N13.nz=v3.zpos-v1.zpos; 
 
    N=GetTwoNormalProduct(N12,N13); 
 
    plane.A=N.nx; 
    plane.B=N.ny; 
    plane.C=N.nz; 
	plane.D= -(plane.A*v1.xpos+plane.B*v1.ypos+plane.C*v1.zpos); 
 
	return plane; 
} 
 
PLANE CMath::GetPlaneEquation(VERTEX v,PLANE p1,PLANE p2) 
{ 
	PLANE plane; 
    NORMAL n1,n2,normal; 
    n1.nx=p1.A;  n1.ny=p1.B;  n1.nz=p1.C; 
    n2.nx=p2.A;  n2.ny=p2.B;  n2.nz=p2.C; 
 
	normal=GetTwoNormalProduct(n1,n2); 
 
	plane.A=normal.nx; 
	plane.B=normal.ny; 
	plane.C=normal.nz; 
	plane.D=-(plane.A*v.xpos+plane.B*v.ypos+plane.C*v.zpos); 
 
	return plane; 
} 
 
VERTEX CMath::GetIntersection(VERTEX v1,VERTEX v2,PLANE plane) 
{ 
	VERTEX point;	 
	double temp1=(plane.A*(v2.xpos-v1.xpos)+plane.B*(v2.ypos-v1.ypos)+plane.C*(v2.zpos-v1.zpos)); 
	double temp2=-plane.D-plane.A*v1.xpos-plane.B*v1.ypos-plane.C*v1.zpos; 
    ///// Line param is temp2/temp1 
	point.xpos=v1.xpos+float((double(v2.xpos-v1.xpos)*temp2)/temp1); 
	point.ypos=v1.ypos+float((double(v2.ypos-v1.ypos)*temp2)/temp1); 
	point.zpos=v1.zpos+float((double(v2.zpos-v1.zpos)*temp2)/temp1); 
  
	return point; 
} 
 
TEXCOORD CMath::GetIntersectionTexCoord(VERTEX pointA,TEXCOORD texcoordA, 
										VERTEX pointB,TEXCOORD texcoordB,  PLANE plane) 
{ 
	VERTEX intersect=GetIntersection(pointA,pointB,plane); 
	float distA=GetDistance(pointA,intersect); 
	float distAB=GetDistance(pointA,pointB); 
	if(distAB<0.0001)return texcoordA; ///////safe 
	TEXCOORD texcoord; 
	texcoord.u=(texcoordA.u*distAB + distA*(texcoordB.u-texcoordA.u))/distAB; 
	texcoord.v=(texcoordA.v*distAB + distA*(texcoordB.v-texcoordA.v))/distAB; 
 
	return texcoord; 
} 
 
VERTEX CMath::GetPositionOnGrid(VERTEX *pQuads,float u,float v) 
{ 
	/////////u,v 的范围为0-1 
	if(u<0)u=0;	if(u>1)u=1; 
	if(v<0)v=0;	if(v>1)v=1; 
	////////////////////////////////////// 
	VERTEX v1,v2; //与u相关的两条边上的点 
	v1=VERTEX(pQuads[0].xpos+(pQuads[1].xpos-pQuads[0].xpos)*u, 
              pQuads[0].ypos+(pQuads[1].ypos-pQuads[0].ypos)*u, 
              pQuads[0].zpos+(pQuads[1].zpos-pQuads[0].zpos)*u); 
 
	v2=VERTEX(pQuads[3].xpos+(pQuads[2].xpos-pQuads[3].xpos)*u, 
              pQuads[3].ypos+(pQuads[2].ypos-pQuads[3].ypos)*u, 
              pQuads[3].zpos+(pQuads[2].zpos-pQuads[3].zpos)*u); 
	/////////////////////////////////////// 
	VERTEX vertex;    ///所求的点 
    vertex.xpos=v1.xpos+(v2.xpos-v1.xpos)*v; 
    vertex.ypos=v1.ypos+(v2.ypos-v1.ypos)*v; 
    vertex.zpos=v1.zpos+(v2.zpos-v1.zpos)*v; 
 
	return vertex; 
} 
 
NORMAL CMath::GetTwoNormalProduct(NORMAL n1,NORMAL n2) 
{ 
	double n1x,n1y,n1z,n2x,n2y,n2z; 
	n1x=n1.nx;  n1y=n1.ny;  n1z=n1.nz; 
	n2x=n2.nx;  n2y=n2.ny;  n2z=n2.nz; 
 
    double nx,ny,nz; 
 
    nx=  n1y*n2z-n2y*n1z; 
    ny=-(n1x*n2z-n2x*n1z); 
    nz=  n1x*n2y-n2x*n1y; 
//	return NORMAL(float(nx),float(ny),float(nz)); 
	return Normalization(nx,ny,nz); 
} 
NORMAL CMath::GetNormal(VERTEX v1,VERTEX v2,VERTEX v3) 
{ 
	NORMAL n1,n2; 
	n1.nx=v2.xpos-v1.xpos; 
	n1.ny=v2.ypos-v1.ypos; 
	n1.nz=v2.zpos-v1.zpos; 
 
	n2.nx=v3.xpos-v1.xpos; 
	n2.ny=v3.ypos-v1.ypos; 
	n2.nz=v3.zpos-v1.zpos; 
 
	return GetTwoNormalProduct(n1,n2); 
 
} 
NORMAL  CMath::GetNormal(float *v1,float *v2,float *v3) 
{ 
	NORMAL n1,n2; 
	n1.nx=v2[0]-v1[0]; 
	n1.ny=v2[1]-v1[1]; 
	n1.nz=v2[2]-v1[2]; 
 
	n2.nx=v3[0]-v1[0]; 
	n2.ny=v3[1]-v1[1]; 
	n2.nz=v3[2]-v1[2]; 
 
	return GetTwoNormalProduct(n1,n2); 
 
} 
float CMath::GetTwoVectorAngleCosine(NORMAL na,NORMAL nb) 
{ 
    NORMAL n1,n2; 
	n1=Normalization(na); 
	n2=Normalization(nb); 
	double temp,length1,length2; 
	temp=n1.nx*n2.nx+n1.ny*n2.ny+n1.nz*n2.nz; 
	length1=pow( n1.nx*n1.nx +n1.ny*n1.ny +n1.nz*n1.nz,0.5); 
	length2=pow( n2.nx*n2.nx +n2.ny*n2.ny +n2.nz*n2.nz,0.5); 
 
	return float(temp/(length1*length2)); 
} 
 
 
float CMath::GetDistance(VERTEX v1,VERTEX v2) 
{ 
	float dist; 
	dist=(float)pow((v2.xpos-v1.xpos)*(v2.xpos-v1.xpos)+ 
		            (v2.ypos-v1.ypos)*(v2.ypos-v1.ypos)+ 
					(v2.zpos-v1.zpos)*(v2.zpos-v1.zpos),0.5); 
	return dist; 
 
} 
float CMath::GetDistance(VERTEX point,PLANE plane) 
{ 
	float abc=(float)sqrt(plane.A*plane.A+plane.B*plane.B+plane.C*plane.C); 
	float dist=(plane.A*point.xpos+plane.B*point.ypos+plane.C*point.zpos+plane.D)/abc; 
    if(dist<0)dist=-dist; 
    return dist; 
} 
float CMath::GetDistance(VERTEX point,PLANE plane,float powABC) 
{ 
    return (plane.A*point.xpos+plane.B*point.ypos+plane.C*point.zpos+plane.D)/powABC; 
} 
float CMath::GetTwoVectorAngleCosine(VERTEX  v1,VERTEX vCenter,VERTEX v2) 
{ 
	double temp,length1,length2; 
	double n1nx,n1ny,n1nz,n2nx,n2ny,n2nz; 
 
	n1nx=v1.xpos-vCenter.xpos; 
	n1ny=v1.ypos-vCenter.ypos; 
	n1nz=v1.zpos-vCenter.zpos; 
 
	n2nx=v2.xpos-vCenter.xpos; 
	n2ny=v2.ypos-vCenter.ypos; 
	n2nz=v2.zpos-vCenter.zpos; 
 
	temp=n1nx*n2nx+n1ny*n2ny+n1nz*n2nz; 
	length1=pow( n1nx*n1nx +n1ny*n1ny +n1nz*n1nz,0.5); 
	length2=pow( n2nx*n2nx +n2ny*n2ny +n2nz*n2nz,0.5); 
 
	return float(temp/(length1*length2)); 
} 
 
int CMath::ClassifyTwoNormal(NORMAL n1,NORMAL n2) 
{ 
	float temp; 
	temp=n1.nx*n2.nx+n1.ny*n2.ny+n1.nz*n2.nz; 
	if(temp==0)return PERPENDICULAR; 
	if(temp>0)return SHARP_ANGLE; 
   	if(temp<0)return OBTUSE_ANGLE;  
	return UNKNOW; 
} 
 
int CMath::ClassifyTwoNormal(VERTEX  v1,VERTEX vCenter,VERTEX v2) 
{ 
	float temp; 
	NORMAL n1,n2; 
 
	n1.nx=v1.xpos-vCenter.xpos; 
	n1.ny=v1.ypos-vCenter.ypos; 
	n1.nz=v1.zpos-vCenter.zpos; 
 
	n2.nx=v2.xpos-vCenter.xpos; 
	n2.ny=v2.ypos-vCenter.ypos; 
	n2.nz=v2.zpos-vCenter.zpos; 
 
	temp=n1.nx*n2.nx+n1.ny*n2.ny+n1.nz*n2.nz; 
 
	if(temp==0)return PERPENDICULAR; 
	if(temp>0)return SHARP_ANGLE; 
   	if(temp<0)return OBTUSE_ANGLE;  
	return UNKNOW; 
} 
 
int CMath::ClassifyPointPlane(VERTEX point,PLANE plane) 
{ 
	float distance=plane.A*point.xpos+plane.B*point.ypos+plane.C*point.zpos+plane.D; 
    if(distance==0)return COINCIDENT; 
	if(distance>0)return  IN_FRONT_OF; 
	return  IN_BACK_OF; 
} 
 
int CMath::ClassifyPolygonPlane(PLANE plane,VERTEX *vertices,int num) 
{ 
	if(num<3)return UNKNOW; 
	int current=0; 
    int dist=ClassifyPointPlane(vertices[0],plane); 
	if(dist==IN_FRONT_OF) 
	{ 
        current=1; 
		while(current