前面旋翼在直升机的外面旋转,应该是中心没求对,哪个旋翼毕竟不是四方盒,虽然它的名字叫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;
}