3DS各个模块的相对运动(续)

前面旋翼在直升机的外面旋转,应该是中心没求对,哪个旋翼毕竟不是四方盒,虽然它的名字叫Box03。

现在,把它当作圆来求圆心,搜索网页找来一段代码:

已知圆上三点计算圆心
已知:startPoint、secondPoint、endPoint(不分先后)

求:圆心坐标

解:

var tempA1,tempA2,tempB1,tempB2,tempC1,tempC2,temp,x,y;

tempA1=startPoint.x-secondPoint.x; 

tempB1=startPoint.y-secondPoint.y;
tempC1=(Math.pow(startPoint.x,2)-Math.pow(secondPoint.x,2)+Math.pow(startPoint.y,2)-Math.pow(secondPoint.y,2))/2;
  
tempA2=endPoint.x-secondPoint.x;
tempB2=endPoint.y-secondPoint.y;
tempC2=(Math.pow(endPoint.x,2)-Math.pow(secondPoint.x,2)+Math.pow(endPoint.y,2)-Math.pow(secondPoint.y,2))/2;
        
temp=tempA1*tempB2-tempA2*tempB1;
if(temp==0){
    x=startPoint.x;
    y=startPoint.y;
}else{
    x=(tempC1*tempB2-tempC2*tempB1)/temp;
    y=(tempA1*tempC2-tempA2*tempC1)/temp;
}
new Point(x,y); //x  y为点的坐标			 */
前面已经得到螺旋的外包盒的值, 利用它们来求旋翼尖

xmin,xmax,zmin,zmax,( ymin,ymax 在这里没有用)

//寻找翼尖点-----------------------------------------------------------
float y_xmin,z_xmin,//xmin
	y_xmax,z_xmax,//xmax
	x_zmin,y_zmin,//zmin
	x_zmax,y_zmax;//zmax
//遍历对象中的所有顶点
pVerts=gothicModel.pObject[i].pVerts;
 for(int j=0;j<gothicModel.pObject[i].numOfVerts;j++)
 {	
	 //比较大小,找边上点
	 t=pVerts->x;
	 if(xmin==t){//x小值
	 y_xmin=pVerts->y;
	 z_xmin=pVerts->z;
	 }
	 if(xmax==t){//x大值
	 y_xmax=pVerts->y;
	 z_xmax=pVerts->z;
	 }

	 t=pVerts->z;
	 if(zmin==t){//z小值
		x_zmin=pVerts->x;
		y_zmin=pVerts->y;
	 }
	 if(zmax==t){//z大值
		x_zmax=pVerts->x;
		y_zmax=pVerts->y;
	 }
	pVerts++;//下一个顶点
 }
得到四个点,而翼只有三个尖:

xmin  , y_xmin,z_xmin
xmax  , y_xmax,z_xmax
x_zmin, y_zmin,zmin
x_zmax, y_zmax,zmax

y值是没用的,去掉不用

//三点计算圆心(由上面得到的四个点)
 //1:xmin, z_xmin		
 //2:xmax, z_xmax
 //3:x_zmin,zmin
 //4:x_zmax,zmax
 float startPointx=xmin,
	 startPointy=z_xmin,
	 secondPointx=xmax ,
	 secondPointy=z_xmax,
	 endPointx=x_zmax,
	 endPointy=zmax;

 float tempA1,tempA2,tempB1,tempB2,tempC1,tempC2,temp,x,y;
tempA1=startPointx-secondPointx; 

tempB1=startPointy-secondPointy;
tempC1= (pow(startPointx,2)-pow(secondPointx,2)+pow(startPointy,2)-pow(secondPointy,2))/2;
  
tempA2=endPointx-secondPointx;
tempB2=endPointy-secondPointy;
tempC2=(pow(endPointx,2)-pow(secondPointx,2)+pow(endPointy,2)-pow(secondPointy,2))/2;
temp=tempA1*tempB2-tempA2*tempB1;
if(temp==0){
	x=startPointx;
	y=startPointy;
}else{
	 x =(tempC1*tempB2-tempC2*tempB1)/temp;
	 y =(tempA1*tempC2-tempA2*tempC1)/temp;
}
xt1=x;zt1=y;//圆心的x,z值
printf("xt1:%f,\n",xt1);
printf("zt1:%f,\n",zt1);	
1,2,3点还是不行,用1,2,4点时就对了:


已经全部完成了,下面是总代码:

//3DS直升机直升机转动旋翼(有纹理贴图的3ds模型,+光照 +虚拟球旋转)
 
#define  name3DS "Data/3ds/T_HELI_L.3DS"  //

 
#include "CLoad3DS1.cpp"

	GLfloat xt1=0.0,yt1=0.0,zt1=0.0f;//转动轴移动量 
	float rquad=0.0;//转动量

//显示3ds模型
void drawModel(t3DModel Model,bool touming,bool outTex)
{
	if( touming ){
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glColor4f(1,1,1,0.5);
	}
	//
	glPushMatrix();//保存当前位置
	// 遍历模型中所有的对象
	for(int i = 0; i < Model.numOfObjects; i++)
	{
		// 获得当前显示的对象
		t3DObject *pObject = &Model.pObject[i];
		// 判断该对象是否有纹理映射
		if(!outTex) {
			if(pObject->bHasTexture) {
				
				// 打开纹理映射
				glEnable(GL_TEXTURE_2D);
				
				glBindTexture(GL_TEXTURE_2D, Model.texture[pObject->materialID]);
			} else {
				
				// 关闭纹理映射
				glDisable(GL_TEXTURE_2D);
				glColor3ub(255, 255, 255);
			}
		} 
		if(i==7){//7是旋翼
			
			glPushMatrix();//保存当前位置

	glTranslatef(xt1,0.0f,zt1);// z1
	glRotatef(rquad,0.0f,1.0f,0.0f);// 绕y轴旋转 
	glTranslatef(-xt1,0.0f,-zt1);// z1

			
		}else if(i==8){
			glPopMatrix();//恢复原来位置
		}
		//开始以g_ViewMode模式绘制
		glBegin(GL_TRIANGLES);          
		// 遍历所有的面
		for(int j = 0; j < pObject->numOfFaces; j++)
		{
			// 遍历三角形的所有点
			for(int whichVertex = 0; whichVertex < 3; whichVertex++)
			{
				// 获得面对每个点的索引
				int index = pObject->pFaces[j].vertIndex[whichVertex];
				// 给出法向量
				glNormal3f(pObject->pNormals[ index ].x, pObject->pNormals[ index ].y, pObject->pNormals[ index ].z);
				// 如果对象具有纹理
				if(pObject->bHasTexture) {
					
					// 确定是否有UVW纹理坐标
					if(pObject->pTexVerts) { 
						glColor3f(1.0,1.0,1.0);
						glTexCoord2f(pObject->pTexVerts[ index ].x, pObject->pTexVerts[ index ].y);
					}
				} else{
					
					if(Model.pMaterials.size() && pObject->materialID >= 0) 
					{
						BYTE *pColor = Model.pMaterials[pObject->materialID].color;
						glColor3ub(pColor[0], pColor[1], pColor[2]);
					}
				}
				glVertex3f(pObject->pVerts[ index ].x, pObject->pVerts[ index ].y, pObject->pVerts[ index ].z);
			}
			
		}
		glEnd();                // 绘制结束
	}
	glPopMatrix();//恢复原来位置
	if( touming )
		glDisable(GL_BLEND);
	
}


#include "ArcBall.cpp"

const GLfloat lightPosition[] = {10.0,-10.0,10.0,0.0};  //光源所在的位置 无限远处+方向
const GLfloat whiteLight[] = {0.8,0.8,0.8,1.0};  
GLfloat matSpecular [] = {0.3,0.3,0.3,1.0};  //镜面反光率(RGBA)
GLfloat matShininess [] = {20.0};  
GLfloat matEmission [] = {0.3,0.3,0.3,1.0};  
GLfloat spin = 0;  
GLint  width = 600;
GLint  height = 480;

CLoad3DS *gothicLoader=new(CLoad3DS);  
t3DModel gothicModel;  
float gothicTrans[10] = {   
    0, 0 , -30 ,     //表示在世界矩阵的位置  
       0 , 0 , 0 ,      //表示xyz放大倍数  
        0 , 0 , 0 , 0  //表示旋转  
};

//初始化,必须用全局变量的方式,不能用new
ArcBallT arcBall(600.0f,400.0f);
ArcBallT*    ArcBall =&arcBall;// new ArcBallT(600.0f,400.0f);//&arcBall;

char * filename3ds=name3DS;


//移动
void move(int x, int y)                         
{
    ArcBall->MousePt.s.X = x;
    ArcBall->MousePt.s.Y = y;
    ArcBall->upstate();
    glutPostRedisplay();
}
//点击
void mouse(int button, int state, int x, int y) 
{
    if(button == GLUT_LEFT_BUTTON && state==GLUT_DOWN){
        ArcBall->isClicked = true;
        move(x,y);
    }
    else if(button == GLUT_LEFT_BUTTON && state==GLUT_UP)
        ArcBall->isClicked = false;
    else if(button == GLUT_RIGHT_BUTTON && state==GLUT_DOWN){
        ArcBall->isRClicked = true;
        move(x,y);
    }
    else if(button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
        ArcBall->isRClicked = false;
    ArcBall->upstate();
    glutPostRedisplay();
}
//计算螺旋转外框大小,找中心
void Box03zhong()
{
	//遍历模型的对象,遍历对象顶点,找到x,y,z的最小,最大值,计算模型外框大小,长,宽,高
	//然后计算xyz放大倍数


	float xmin,xmax,ymin,ymax,zmin,zmax,t;
	xmin=ymin=zmin=9999999.0;//设置一个很大的值
	xmax=ymax=zmax=-9999999.0;//设置一个很小的值

   printf("对象个数:%d\n",gothicModel.numOfObjects);
   //printf("对象vector大小:%d\n",gothicModel.pObject.size());
   //遍历模型中的所有对象
   //for(unsigned int i=0;i<gothicModel.pObject.size();i++)
   unsigned int i=7;
		   //printf("第%d个对象的顶点个数:%d\n",i,gothicModel.pObject[i].numOfVerts);
			NBVector3 *pVerts;      // 对象的顶点
			pVerts=gothicModel.pObject[i].pVerts;
			//遍历对象中的所有顶点
			 for(int j=0;j<gothicModel.pObject[i].numOfVerts;j++)
			 {	
				 //比较大小,留下最小和最大值
				 t=pVerts->x;
				 xmin=(t<xmin)?t:xmin;
				 xmax=(t>xmax)?t:xmax;

				 t=pVerts->y;
				 ymin=(t<ymin)?t:ymin;
				 ymax=(t>ymax)?t:ymax;

				 t=pVerts->z;
				 zmin=(t<zmin)?t:zmin;
				 zmax=(t>zmax)?t:zmax;
				pVerts++;//下一个顶点
			 }
			 //显示对象名称
			//printf("对象%d名称:%s\n",i,gothicModel.pObject[i].strName);
			//外框一半是中心吗
			xt1=xmin+(xmax-xmin)/2;//
			//yt1=ymin+(ymax-ymin)/2;
			zt1=zmin+(zmax-zmin)/2;

			printf("xt1:%f,\n",xt1);
			//printf("yt1:%f,\n",yt1);
			printf("zt1:%f,\n",zt1);	

	//寻找翼尖点-----------------------------------------------------------
	float y_xmin,z_xmin,//xmin
		y_xmax,z_xmax,//xmax
		x_zmin,y_zmin,//zmin
		x_zmax,y_zmax;//zmax
	//遍历对象中的所有顶点
	pVerts=gothicModel.pObject[i].pVerts;
	 for(int j=0;j<gothicModel.pObject[i].numOfVerts;j++)
	 {	
		 //比较大小,找边上点
		 t=pVerts->x;
		 if(xmin==t){//x小值
		 y_xmin=pVerts->y;
		 z_xmin=pVerts->z;
		 }
		 if(xmax==t){//x大值
		 y_xmax=pVerts->y;
		 z_xmax=pVerts->z;
		 }



		 t=pVerts->z;
		 if(zmin==t){//z小值
			x_zmin=pVerts->x;
			y_zmin=pVerts->y;
		 }
		 if(zmax==t){//z大值
			x_zmax=pVerts->x;
			y_zmax=pVerts->y;
		 }
		pVerts++;//下一个顶点
	 }


	 //三点计算圆心(由上面得到的四个点)
			 //1:xmin, z_xmin		
			 //2:xmax, z_xmax
			 //3:x_zmin,zmin
			 //4:x_zmax,zmax
			 float startPointx=xmin,
				 startPointy=z_xmin,
				 secondPointx=xmax ,
				 secondPointy=z_xmax,
				 endPointx=x_zmax,
				 endPointy=zmax;

			 float tempA1,tempA2,tempB1,tempB2,tempC1,tempC2,temp,x,y;
		tempA1=startPointx-secondPointx; 

		tempB1=startPointy-secondPointy;
		tempC1= (pow(startPointx,2)-pow(secondPointx,2)+pow(startPointy,2)-pow(secondPointy,2))/2;
		  
		tempA2=endPointx-secondPointx;
		tempB2=endPointy-secondPointy;
		tempC2=(pow(endPointx,2)-pow(secondPointx,2)+pow(endPointy,2)-pow(secondPointy,2))/2;
		temp=tempA1*tempB2-tempA2*tempB1;
		if(temp==0){
			x=startPointx;
			y=startPointy;
		}else{
			 x =(tempC1*tempB2-tempC2*tempB1)/temp;
			 y =(tempA1*tempC2-tempA2*tempC1)/temp;
		}
		xt1=x;zt1=y;
			printf("xt1:%f,\n",xt1);
			printf("zt1:%f,\n",zt1);	

	
}

//计算模型外框大小,把模型放在屏幕中央
void zhong(GLvoid)
{
	//遍历模型的对象,遍历对象顶点,找到x,y,z的最小,最大值,计算模型外框大小,长,宽,高
	//然后计算xyz放大倍数


	float xmin,xmax,ymin,ymax,zmin,zmax,t;
	xmin=ymin=zmin=9999999.0;//设置一个很大的值
	xmax=ymax=zmax=-9999999.0;//设置一个很小的值

   printf("对象个数:%d\n",gothicModel.numOfObjects);
   //printf("对象vector大小:%d\n",gothicModel.pObject.size());
   //遍历模型中的所有对象
   for(unsigned int i=0;i<gothicModel.pObject.size();i++)
	{
		   //printf("第%d个对象的顶点个数:%d\n",i,gothicModel.pObject[i].numOfVerts);
			NBVector3 *pVerts;      // 对象的顶点
			pVerts=gothicModel.pObject[i].pVerts;
			//遍历对象中的所有顶点
			 for(int j=0;j<gothicModel.pObject[i].numOfVerts;j++)
			 {	
				 //比较大小,留下最小和最大值
				 t=pVerts->x;
				 xmin=(t<xmin)?t:xmin;
				 xmax=(t>xmax)?t:xmax;

				 t=pVerts->y;
				 ymin=(t<ymin)?t:ymin;
				 ymax=(t>ymax)?t:ymax;

				 t=pVerts->z;
				 zmin=(t<zmin)?t:zmin;
				 zmax=(t>zmax)?t:zmax;
				pVerts++;//下一个顶点
			 }
			 //显示对象名称
			printf("对象%d名称:%s\n",i,gothicModel.pObject[i].strName);
	}
	
	//显示最小最大值
   printf("xmin:%f,xmax:%f\n",xmin,xmax);
   printf("ymin:%f,ymax:%f\n",ymin,ymax);
   printf("zmin:%f,xmax:%f\n",zmin,zmax);

      printf("宽度(x差值):%f,\n",xmax-xmin);
      printf("高度(y差值):%f,\n",ymax-ymin);
      printf("深度(z差值):%f,\n",zmax-zmin);
	  float xm,ym,zm,b;
	  xm=xmax-xmin;ym=ymax-ymin;zm=zmax-zmin;
		float max3=max(max(xm,ym),zm);

	  b=1.0/max3;
	  	  scaleNum=max3*b*100;//100分之一为 1 单位
      printf("放大倍数:%f,\n",b);
      printf("1单位:%f\n",scaleNum);

	gothicTrans[3]=gothicTrans[4]=gothicTrans[5]=b;//设置放大倍数	
	//移到屏幕中央
	gothicTrans[0]=-(xmin+(xmax-xmin)/2)*b;
	gothicTrans[1]=-(ymin+(ymax-ymin)/2)*b;
	gothicTrans[2]=-(zmin+(zmax-zmin)/2)*b-20;

	Box03zhong();

}


void init()  
{  
	gothicLoader->Import3DS(&gothicModel, filename3ds);//导入模型,第二个参数是3ds文件的路径,
	zhong();


    glClearColor(0.3,0.3,0.3,1.0);  
    glClearDepth(1.0);  


    glShadeModel(GL_SMOOTH);  
    glEnable(GL_LIGHTING);  //打开光照处理功能
    glEnable(GL_LIGHT0);  //使用第0号光照   
    glEnable(GL_DEPTH_TEST); 

    glMatrixMode(GL_MODELVIEW);  //对模型视景矩阵操作  
    glLoadIdentity();  //将坐标原点移到中心 


	gluPerspective(3.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);


    glLightfv(GL_LIGHT0,GL_POSITION,lightPosition);  //光源所在的位置。

	//GL_DIFFUSE:该光源所发出的光,照射到粗糙表面时经过漫反射,所得到的光的强度(颜色)
    glLightfv(GL_LIGHT0,GL_DIFFUSE,whiteLight);  

	//GL_SPECULAR:该光源所发出的光,照射到光滑表面时经过镜面反射,所得到的光的强度(颜色)。
    glLightfv(GL_LIGHT0,GL_SPECULAR,whiteLight);  
}  
void display()  
{     
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清空颜色和深度缓冲  
    glMatrixMode(GL_PROJECTION);  //对投影矩阵操作  
    glLoadIdentity();;  //将坐标原点移到中心
      
    glMatrixMode(GL_MODELVIEW);  //对模型视景矩阵操作 
    glPushMatrix();  
    glRotatef(spin,0.0,1.0,0.0);  
	//设置材质
    glMaterialfv(GL_FRONT,GL_SPECULAR,matSpecular);  //设置镜面光
    glMaterialfv(GL_FRONT,GL_SHININESS,matShininess);  //镜面指数
    glMaterialfv(GL_FRONT,GL_EMISSION,matEmission);//自发光
	
	changeObject( gothicTrans );  

	//-----轨迹球----------开始
    glScalef(ArcBall->zoomRate, ArcBall->zoomRate, ArcBall->zoomRate);//2. 缩放
    glMultMatrixf(ArcBall->Transform.M);                        //3. 旋转
	//-----轨迹球----------结束

	drawModel(gothicModel,true,false);  
	//huaxyz();
	glPopMatrix();  
    glFlush();  
}  

void SpinDisplay()
{
	rquad+=1.5f;// 旋转量
	if( rquad > 360 )
	   rquad -= 360;

	glutPostRedisplay();
}

int main(int argc,char *argv[])  
{     
	if( argc == 2 )
		filename3ds=argv[1];
    glutInit(&argc,argv);  
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGBA|GLUT_DEPTH);  
	glutInitWindowSize(width,height);
    glutInitWindowPosition(150,150);  
    glutCreateWindow("3DS直升机转动旋翼");  
    glutDisplayFunc(display);  

    init();  

    glutMouseFunc(mouse);        //注册鼠标事件。
    glutMotionFunc(move);        //注册移动事件
		glutIdleFunc( SpinDisplay );//注册旋转

    glutMainLoop();  
    return EXIT_SUCCESS;  
}  
 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值