#include "stdafx.h"
#include "OpenGL.h"
#include "Map.h"
#include "math.h"
#include "ArrayInterTriangle.h"
#include <iostream.h>
#include <stdio.h>
#include <bitset>
extern unsigned int m_ID;
#include <math.h>
#include<stdexcept>
#include<time.h>
extern bool Lbutdown; // 鼠标左键
extern bool Rbutdown; // 鼠标左键
//
extern HWND hWnd;
//定义最近的距离视点最近的鼠标物体:
//定义一个结构来保存所有的物体:
#include<list>
int TreeDepth=0;
#include<vector>
using std::bitset;
using std::list;
using std::vector;
using std::runtime_error;
using std::length_error;
class Triangle{
public:
Triangle(){
for(int i=0;i<3;i++)
{
a[i]=0;
b[i]=0;
c[i]=0;
}
}
Triangle(const Triangle& tri)
{
for(int i=0;i<3;i++)
{
this->a[i]=tri.a[i];
this->b[i]=tri.b[i];
this->c[i]=tri.c[i];
}
}
Triangle& operator =(const Triangle & tri){
for(int i=0;i<3;i++)
{
this->a[i]=tri.a[i];
this->b[i]=tri.b[i];
this->c[i]=tri.c[i];
}
return *this;
}
float a[3];
float b[3];
float c[3];
};
class TheTreeObect{
int maxlen;
int currentFlip;
Triangle *Triangles;
public:
static int gouzaoshu;
int n;
~TheTreeObect(){
delete [] this->Triangles;
}
void SetAsNode(const Triangle ¤tFlip){
delete [] Triangles;
Triangles=new Triangle[1];
Triangles[0]=currentFlip;
n=1;
maxlen=1;
}
void resetTriangle(Triangle *pTri,int n1){
if(n1>maxlen)
{
delete[] this->Triangles;
Triangles=new Triangle[n1+10];
this->maxlen=n1+10;
}
for(int i=0;i<n1;i++){
this->Triangles[i]=pTri[i];
}
this->n=n1;
}
TheTreeObect(const TheTreeObect &obj):n(obj.n),maxlen(obj.maxlen)
{
Triangles=new Triangle[maxlen];
for(int i=0;i<n;i++)
{
Triangles[i]=obj.Triangles[i];
}
}
TheTreeObect & operator=(const TheTreeObect & obj)
{
if(obj.n>maxlen){
delete [] Triangles;
Triangles=new Triangle[obj.maxlen];
this->maxlen=obj.maxlen;
}
for(int m=0;m<obj.n;m++){
Triangles[m]=obj.getTriangles()[m];
}
this->n=obj.n;
return *this;
}
TheTreeObect(){
this->Triangles= new Triangle[10];
this->maxlen=10;
n=0;
}
int add(Triangle triangle)
{
if(n==maxlen){
maxlen=n+10;
Triangle* temp=Triangles;
Triangles=new Triangle[n+10];
for(int i=0;i<n;i++){
Triangles[i]=temp[i];
}
delete [] temp;
temp=NULL;
}
Triangles[n++]=triangle;
return n;
}
int getN() const{
return n;
}
Triangle *getTriangles ()const
{
return Triangles;
}
void outPutSanjiao(Triangle triangle) const
{
float *a=triangle.a;
float a0=a[0];
float a1=a[1];
float a2=a[2];
cout<<endl<<a0<<" "<<a1<<" "<<a2<<" "<<endl;
float *b=triangle.b;
float b0=b[0];
float b1=b[1];
float b2=b[2];
cout<<b0<<" "<<b1<<" "<<b2<<" "<<endl;
float *c=triangle.c;
float c0=c[0];
float c1=c[1];
float c2=c[2];
cout<<c0<<" "<<c1<<" "<<c2<<" "<<endl;
}
void outPut() const
{
for(int i=0;i<n;i++)
{
outPutSanjiao(Triangles[i]);
}
}
TheTreeObect(float (*triangle)[3][3],int n1)
{
//cout<<"TheTreeObect(float (*triangle)[3][3],int n1) ///begin"<<endl;
Triangles= new Triangle[n1+10];
this->maxlen=n1+10;
this->n=n1;
for(int i=0;i<n;i++){
for(int j=0;j<3;j++){
Triangles[i].a[j]=triangle[i][0][j];
Triangles[i].b[j]=triangle[i][1][j];
Triangles[i].c[j]=triangle[i][2][j];
}
}
// cout<<"TheTreeObect(float (*triangle)[3][3],int n1) ///end"<<endl;
}
};
int TheTreeObect::gouzaoshu=0;
int NodeGouZaoShu;
//而叉树节点是一个特殊的物体。。它只有一个平面。
class BSPNode:public TheTreeObect{
public:
virtual ~BSPNode(){
NodeGouZaoShu--;
delete pBackChild;
delete pFrontChild;
}
BSPNode():TheTreeObect(){
NodeGouZaoShu++;
IsLeaf=true;
pBackChild=NULL;
pFrontChild=NULL;
n=0;
}
bool IsLeaf;
BSPNode(const TheTreeObect& obj):TheTreeObect(obj){
NodeGouZaoShu++;
pBackChild=NULL;
pFrontChild=NULL;
IsLeaf=true;
}
BSPNode* pBackChild;
BSPNode* pFrontChild;
//查看物体的第index个三角形是否与既定面共面。
void outPutSanjiao(Triangle triangle) const
{
float *a=triangle.a;
float a0=a[0];
float a1=a[1];
float a2=a[2];
cout<<endl<<a0<<" "<<a1<<" "<<a2<<" "<<"|";
float *b=triangle.b;
float b0=b[0];
float b1=b[1];
float b2=b[2];
cout<<b0<<" "<<b1<<" "<<b2<<" "<<"|";
float *c=triangle.c;
float c0=c[0];
float c1=c[1];
float c2=c[2];
cout<<c0<<" "<<c1<<" "<<c2<<" "<<endl;
}
void outPutSanJiaos(Triangle* pTriangle,int n) const
{
for(int i=0;i<n;i++)
{
outPutSanjiao(pTriangle[i]);
}
}
void outPutVector(char *p,float *pf,int n) const
{
for(int j=0;p[j]!='\0';p++)
{
cout<<p[j];
}
cout<<":"<<endl;
for(int i=0;i<n;i++)
{
cout<<pf[i]<<endl;
}
}
bool IsFomFront(Triangle sanjiao,Triangle flipflat,bool &same,bool &divied){
divied=false;
same=false;
bitset<3> position[3];
float dir[3];
bool Front[3];
bool IsNotInFlat[3];
float point[3];
memcpy(point,sanjiao.a,3*sizeof(float));
//int currentFlip=getFlip();
VectBinus(flipflat.a,point,dir);
IsNotInFlat[0]=IsIntersectWithTriangle(
point,
dir,
flipflat.a,
flipflat.b,
flipflat.c,
point,
Front[0]
);
memcpy(point,sanjiao.b,3*sizeof(float));
VectBinus(flipflat.b,point,dir);
IsNotInFlat[1]=IsIntersectWithTriangle(
point,
dir,
flipflat.a,
flipflat.b,
flipflat.c,
point,
Front[1]
);
memcpy(point,sanjiao.c,3*sizeof(float));
VectBinus(flipflat.c,point,dir);
IsNotInFlat[2]=IsIntersectWithTriangle(
point,
dir,
flipflat.a,
flipflat.b,
flipflat.c,
point,
Front[2]
);
for(int i=0;i<3;i++)
{
if(!IsNotInFlat[i])position[i].set(0);else
if(Front[i])position[i].set(1);else
position[i].set(2);
}
//每个点的三个状态对应为 position[0],position[1],position[2];
bitset<3> positi=position[0]&position[1]&position[2];
if(positi[0])
{
same=true;
//查看方向是否相同
//求得他们的发线:
float flat_3_flip[3];
float flat_3_temp[3];
qiuFaXiangLiang(
flipflat.a,
flipflat.b,
flipflat.c,
flat_3_flip);
qiuFaXiangLiang(
sanjiao.a,
sanjiao.b,
sanjiao.c,
flat_3_temp);
float dotval=DotProduct(flat_3_flip,flat_3_temp);
if(dotval<0){
//点积为负值
return false;
}else
//点积为正值
return true;
}else {
positi=position[0]|position[1]|position[2];
//不共面并且没有在后面的点!!
if(!positi[2])
{
return true;
}
//不共面没有前面的点
else if(!positi[1])
{
return false;
}else
{
//不共面,既有前面的点,也有后面的点。
divied=true;
return false;
}
}
}
//函数功能:判断一个三角形来自另外一个三角形所在平面的何方。
//功能描述:如果共面,则same为true,divided为false,方向相同则返回true,否则返回false;
// 如果不共面,则根据在前还是后,还是divided ,进行返回。
bool IsFomFront(const TheTreeObect& obj,int index,const int ¤tFlip,bool &same,bool &divied){
divied=false;
same=false;
bitset<3> position[3];
float dir[3];
bool Front[3];
bool IsNotInFlat[3];
float point[3];
memcpy(point,obj.getTriangles()[index].a,3*sizeof(float));
//int currentFlip=getFlip();
VectBinus(obj.getTriangles()[currentFlip].a,point,dir);
IsNotInFlat[0]=IsIntersectWithTriangle(
point,
dir,
obj.getTriangles()[currentFlip].a,
obj.getTriangles()[currentFlip].b,
obj.getTriangles()[currentFlip].c,
point,
Front[0]
);
memcpy(point,obj.getTriangles()[index].b,3*sizeof(float));
VectBinus(obj.getTriangles()[currentFlip].b,point,dir);
IsNotInFlat[1]=IsIntersectWithTriangle(
point,
dir,
obj.getTriangles()[currentFlip].a,
obj.getTriangles()[currentFlip].b,
obj.getTriangles()[currentFlip].c,
point,
Front[1]
);
memcpy(point,obj.getTriangles()[index].c,3*sizeof(float));
VectBinus(obj.getTriangles()[currentFlip].c,point,dir);
IsNotInFlat[2]=IsIntersectWithTriangle(
point,
dir,
obj.getTriangles()[currentFlip].a,
obj.getTriangles()[currentFlip].b,
obj.getTriangles()[currentFlip].c,
point,
Front[2]
);
for(int i=0;i<3;i++)
{
if(!IsNotInFlat[i])position[i].set(0);else
if(Front[i])position[i].set(1);else
position[i].set(2);
}
//每个点的三个状态对应为 position[0],position[1],position[2];
bitset<3> positi=position[0]&position[1]&position[2];
if(positi[0])
{
same=true;
//查看方向是否相同
//求得他们的发线:
float flat_3_flip[3];
float flat_3_temp[3];
qiuFaXiangLiang(
obj.getTriangles()[currentFlip].a,
obj.getTriangles()[currentFlip].b,
obj.getTriangles()[currentFlip].c,
flat_3_flip);
qiuFaXiangLiang(
obj.getTriangles()[index].a,
obj.getTriangles()[index].b,
obj.getTriangles()[index].c,
flat_3_temp);
float dotval=DotProduct(flat_3_flip,flat_3_temp);
if(dotval<0){
//点积为负值
return false;
}else
//点积为正值
return true;
}else {
positi=position[0]|position[1]|position[2];
//不共面并且没有在后面的点!!
if(!positi[2])
{
return true;
}
//不共面没有前面的点
else if(!positi[1])
{
return false;
}else
{
//不共面,既有前面的点,也有后面的点。
divied=true;
return false;
}
}
}
//函数功能:从所有的备选三角形列表中找到一个最佳的分割平面。
int getTheBestDivider(vector<int> TheDividerList,bool &found, const TheTreeObect& obj){
int pinggu_value;
found=false;
int theOptimizedValue;
int theOpTriagl;
bool IsInit=false;
bool AllFront=true;
bool AllBack=true;
for(int flip=0;flip<TheDividerList.size();flip++){
int N_FRONT=0;
int N_BACK=0;
int N_DIVIDE=0;
if(
!IsTriangle(
obj.getTriangles()[TheDividerList[flip]].a,
obj.getTriangles()[TheDividerList[flip]].b,
obj.getTriangles()[TheDividerList[flip]].c
)
)continue;
for(int index=0;index<obj.getN();index++){
bool front;
bool same;
bool divided;
front=IsFomFront(obj,index,flip,same,divided);
if(divided){
N_DIVIDE++;
AllBack=false;
AllFront=false;
}
else if(front){
AllBack=false;
N_FRONT++;
}else {
N_BACK++;
AllFront=false;
}
}//for end
if(!AllBack&&!AllFront){
found=true;
}
pingguvalue=fabs(N_FRONT-N_BACK)+N_DIVIDE;
if(!IsInit){
theOpTriagl=flip;
theOptimizedValue=pinggu_value;
IsInit=true;
}
else if(pinggu_value<theOptimizedValue){
theOpTriagl=flip;
theOptimizedValue=pinggu_value;
}
}
if(found){
return theOpTriagl;
}else return 0;
}
//参数:triangle:待分割的三角形
//divider: 分割面
//pTri:分割后的三角形
//p_front:前,还是后
//返回:分割后的三角形个数
int divideTriangle(Triangle triangle,Triangle divider,Triangle* &pTri,bool *& p_front){
//定义Bool型变量记录以顶点出发的变是否与平面相交。
bool notdivided[3];
//边
float dingdian[3][3];
//边是向量。从对应的顶点出发的边。
float bian[3][3];
//构造三角形集合:
//记录顶点三角是否有效:
bool valid[3];
//bool front[3];
float dingdiansanjiao[3][3][3];
//对顶点和边向量进行赋值
//平面方程系数
float flat[4];
unsigned char dingdianweizhi[3];
if(!qiuPingMianFangCheng(divider.a,divider.b,divider.c,flat))
return -1;
for(int i=0;i<3;i++)
{
dingdian[0][i]=triangle.a[i];
dingdian[1][i]=triangle.b[i];
dingdian[2][i]=triangle.c[i];
}
for(i=0;i<3;i++)
{
int j=i+1;
if(j==3)j=0;
VectBinus(dingdian[j],dingdian[i],bian[i]);
}
//判断各个顶点与平面的位置关系
const unsigned char QIAN=0;
const unsigned char SHANG=1;
const unsigned char HOU=2;
for(i=0;i<3;i++)
{
float k=
flat[0]*dingdian[i][0]
+flat[1]*dingdian[i][1]
+flat[2]*dingdian[i][2]
+flat[3];
if(k>0.00001)dingdianweizhi[i]=QIAN;
else if(k<-0.00001)dingdianweizhi[i]=HOU;
else dingdianweizhi[i]=SHANG;
}
unsigned char jiaodianweizhi[3];
float jiaodian[3][3];
unsigned char m=0;
pTri =new Triangle[1+2];
p_front=new bool[3];
int n=0;
for(i=0;i<3;i++)
{
if(fabs(dingdianweizhi[i]-dingdianweizhi[i==2?0:i+1])==2)
{
jiaodianweizhi[i]=SHANG;
calInsert(dingdian[i],bian[i],flat,jiaodian[i]);
notdivided[i]=false;
}else
{
//交点退化为顶点
/* for(int j=0;j<3;j++)
{
jiaodian[i][j]=dingdian[i][j];
}
*/
memcpy(jiaodian[i],dingdian[i],sizeof(jiaodian[i]));
jiaodianweizhi[i]=dingdianweizhi[i];
notdivided[i]=true;
}
}
memcpy(pTri[n].a,jiaodian[0],sizeof(jiaodian[0]));
memcpy(pTri[n].b,jiaodian[1],sizeof(jiaodian[1]));
memcpy(pTri[n].c,jiaodian[2],sizeof(jiaodian[2]));
if(jiaodianweizhi[0]==QIAN||jiaodianweizhi[1]==QIAN||jiaodianweizhi[2]==QIAN){
p_front[n]=true;
}else if(jiaodianweizhi[0]==HOU||jiaodianweizhi[1]==HOU||jiaodianweizhi[2]==HOU)
{
p_front[n]=false;
}
n++;
for(i=0;i<3;i++)
{
if(!notdivided[i])
{
valid[i]=true;
int next;
int pre;
next=(i==2?0:i+1);
pre=(i==0?2:i-1);
dingdiansanjiao[i][0][0]=dingdian[i][0];
dingdiansanjiao[i][0][1]=dingdian[i][1];
dingdiansanjiao[i][0][2]=dingdian[i][2];
dingdiansanjiao[i][1][0]=jiaodian[i][0];
dingdiansanjiao[i][1][1]=jiaodian[i][1];
dingdiansanjiao[i][1][2]=jiaodian[i][2];
if(!notdivided[pre]){
dingdiansanjiao[i][2][0]=jiaodian[pre][0];
dingdiansanjiao[i][2][1]=jiaodian[pre][1];
dingdiansanjiao[i][2][2]=jiaodian[pre][2];
}else{
dingdiansanjiao[i][2][0]=dingdian[pre][0];
dingdiansanjiao[i][2][1]=dingdian[pre][1];
dingdiansanjiao[i][2][2]=dingdian[pre][2];
}
memcpy(pTri[n].a,dingdiansanjiao[i][0],sizeof(float [3]));
memcpy(pTri[n].b,dingdiansanjiao[i][1],sizeof(dingdiansanjiao[i][0]));
memcpy(pTri[n].c,dingdiansanjiao[i][2],sizeof(dingdiansanjiao[i][0]));
if(dingdianweizhi[i]==QIAN){
p_front[n]=true;
}else if(dingdianweizhi[i]==HOU)
{
p_front[n]=false;
}
n++;
}
}
Triangle* tri=pTri;
bool * temp_front=p_front;
pTri=new Triangle[n];
p_front=new bool[n];
for( m=0;m<n;m++)
{
pTri[m]=tri[m];
p_front[m]=temp_front[m];
}
delete [] tri;
delete [] temp_front;
return n;
}
void addObject(const TheTreeObect & obj){
vector<int> TheDividerList;
if(IsLeaf){
bool IsFront=false;
bool NoUsed=true;
int divide_index=0;
TheTreeObect _obj;
for(int j=0;j<getN();j++){
_obj.add(getTriangles()[j]);
}
for(j=0;j<obj.getN();j++){
_obj.add(obj.getTriangles()[j]);
}
for(int i=0;i<_obj.getN();i++)
{
NoUsed=true;
for(int j=0;j<TheDividerList.size();j++)
{
bool sameFlat=false;
bool divided=false;
IsFront=IsFomFront(_obj,i,TheDividerList[j],sameFlat,divided);
//int m=TheDividerList[j];
if(sameFlat){
NoUsed=false;
break;
}
}
if(NoUsed){
TheDividerList.push_back(i);
}
}
bool found=false;
divide_index=getTheBestDivider(TheDividerList,found,_obj);
if(!found)
{
this->resetTriangle(_obj.getTriangles(),_obj.getN());
return;
}else
{
TheTreeObect Front_obj;
TheTreeObect Back_obj;
for(i=0;i<_obj.getN();i++){
bool sameFlat=false;
bool divided=false;
IsFront=IsFomFront(_obj,i,TheDividerList.at(divide_index),sameFlat,divided);
//如果交叉.
if(divided){
//分解三角形
Triangle* pTri;
bool * p_front;
int number=divideTriangle(_obj.getTriangles()[i],_obj.getTriangles()[TheDividerList.at(divide_index)],pTri,p_front);
Triangle* temp_p= pTri;
bool * temp_f=p_front;
for(i=0;i<number;i++){
if(*temp_f){
Front_obj.add(*temp_p);
}
else{
Back_obj.add(*temp_p);
}
temp_f++;
temp_p++;
}
temp_f=NULL;
temp_p=NULL;
delete [] pTri;
delete [] p_front;
}
else if(IsFront){
Front_obj.add(_obj.getTriangles()[i]);
}
else{
Back_obj.add(_obj.getTriangles()[i]);
}
}
IsLeaf=false;
pFrontChild=new BSPNode();
pBackChild=new BSPNode();
pFrontChild->addObject(Front_obj);
pBackChild->addObject(Back_obj);
this->SetAsNode(_obj.getTriangles()[TheDividerList.at(divide_index)]);
}//(else if(!found end))
}//IsLeaf End;
}
//功能描述:更新节点..
void UpdateByModels(const Triangle* theTriangles,int n){
typedef float float_33[3][3];
float (*p)[3][3];
p=new float_33 [n];
for(int i=0;i<n;i++)
{
for(int j=0;j<3;j++)
{
p[i][0][j]=theTriangles[i].a[j];
p[i][1][j]=theTriangles[i].b[j];
p[i][2][j]=theTriangles[i].c[j];
}
}
TheTreeObect* BAK_Obj=new TheTreeObect(p,n);
if(IsLeaf){
this->addObject(*BAK_Obj);
}
else if(!IsLeaf)
{
TheTreeObect* FrontObj=new TheTreeObect();
TheTreeObect* BackObj=new TheTreeObect();
for(int j=0;j<n;j++)
{
bool front=false;
bool same=false;
bool divided=false;
Triangle sanjiao=BAK_Obj->getTriangles()[j];
Triangle flipflat=this->getTriangles()[0];
front=IsFomFront(sanjiao,flipflat,same,divided);
if(divided)
{
//分解三角形
Triangle* pTri;
bool * p_front;
int number=divideTriangle(sanjiao,flipflat,pTri,p_front);
Triangle* temp_pTri= pTri;
bool * temp_p_Front=p_front;
for(int i=0;i<number;i++){
if(*temp_p_Front)
FrontObj->add(*temp_pTri);
else
BackObj->add(*temp_pTri);
temp_p_Front++;
temp_pTri++;
}
delete [] pTri;
delete [] p_front;
}//divided End;
else if(front){
FrontObj->add(theTriangles[j]);
}
else {
BackObj->add(theTriangles[j]);
}
}//for End;
((BSPNode*)pFrontChild)->UpdateByModels(FrontObj->getTriangles(),FrontObj->getN());
((BSPNode*)pBackChild)->UpdateByModels(BackObj->getTriangles(),BackObj->getN());
delete FrontObj;
delete BackObj;
FrontObj=NULL;
BackObj=NULL;
}//if(!leaf end)
delete BAK_Obj;
BAK_Obj=NULL;
delete[] p;
p=NULL;
}//UpdateByModelEnd;
void outPut(){
if(IsLeaf)
{
cout<<"IsLeaf:True"<<endl;
outPutSanJiaos(this->getTriangles(),this->getN());
}
else if(!IsLeaf)
{
cout<<"IsLeaf:false"<<endl;
outPutSanjiao(this->getTriangles()[0]);
((BSPNode*)pFrontChild)->outPut();
((BSPNode*)pBackChild)->outPut();
}
}
};
class BSPTree{
public:
BSPTree(){
pTree=new BSPNode();
}
~BSPTree(){
delete[] pTree;
}
BSPNode* pTree;
//更新二叉树:
void UpdateByModels(const Triangle* Triangle,int n){
pTree->UpdateByModels(Triangle,n);
};
void addObject(TheTreeObect obj){
pTree->addObject(obj);
}
void outPut(){
pTree->outPut();
}
};
//....
class nearestobject{
private:
bool IsInited;
static nearestobject* const theOnlyOne;
int index;
float nearpoint[3];
float point[3];
float nearestDistance;
nearestobject():IsInited(false),index(0),nearestDistance(0.0){
point[0]=0.0;
point[1]=0.0;
point[2]=0.0;
}
void setLookPoint(float nearpoint[3]){
this->nearpoint[0]=nearpoint[0];
this->nearpoint[1]=nearpoint[1];
this->nearpoint[2]=nearpoint[2];
}
void VectBinus(float a[3],float b[3],float c[3]){
c[0]=a[0]-b[0];
c[1]=a[1]-b[1];
c[2]=a[2]-b[2];
}
//计算模
double calMole(float a[3]){
return sqrt(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
}
public:
static nearestobject* GetNearestP(){
return theOnlyOne;
}
//初始化一个近裁剪面点,一个线上的点,以及点对应物体的index;
//返回:是否已经被初始化过
bool Init(float nearpoint[3],float farpoint[3]){
if(!IsInited){
setLookPoint(nearpoint);
for(int i=0;i<3;i++)
{
this->point[i]=point[i];
}
this->index=index;
this->IsInited=true;
float temp[3];
VectBinus(farpoint,nearpoint,temp);
this->nearestDistance=calMole(temp);
return false;
}
return true;
}
int getIndex(){
return index;
}
//返回:以前的物体编号。
int set(int index,float point[3]){
int tempindex;
tempindex=this->index;
double distance;
float temp[3];
VectBinus(point,nearpoint,temp);
distance=calMole(temp);
if((distance-nearestDistance)<-0.000001)
{
nearestDistance=distance;
this->index=index;
}
return tempindex;
}
};
nearestobject* const nearestobject::theOnlyOne=new nearestobject();
//定义射线求交用的变量,这些变量用来进行拾取
float org[3],dir[3],a[3],b[3],c[3],point[3],end[3];
bool IsFromFront;
bool calculateInterWithTriangle(float a[3],float b[3],float c[3]){
return IsIntersectWithTriangle(org,dir,a,b,c,point,IsFromFront);
}
OpenGL::OpenGL()
{
}
OpenGL::~OpenGL()
{ CleanUp();
}
BOOL OpenGL::SetupPixelFormat(HDC hDC0)//检测安装OpenGL
{ int nPixelFormat; // 象素点格式
hDC=hDC0;
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // pfd结构的大小
1, // 版本号
PFD_DRAW_TO_WINDOW | // 支持在窗口中绘图
PFD_SUPPORT_OPENGL | // 支持 OpenGL
PFD_DOUBLEBUFFER, // 双缓存模式
PFD_TYPE_RGBA, // RGBA 颜色模式
16, // 24 位颜色深度
0, 0, 0, 0, 0, 0, // 忽略颜色位
0, // 没有非透明度缓存
0, // 忽略移位位
0, // 无累加缓存
0, 0, 0, 0, // 忽略累加位
16, // 32 位深度缓存
0, // 无模板缓存
0, // 无辅助缓存
PFD_MAIN_PLANE, // 主层
0, // 保留
0, 0, 0 // 忽略层,可见性和损毁掩模
};
if (!(nPixelFormat = ChoosePixelFormat(hDC, &pfd)))
{ MessageBox(NULL,"没找到合适的显示模式","Error",MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
SetPixelFormat(hDC,nPixelFormat,&pfd);//设置当前设备的像素点格式
//利用hDC创造hRC,这句话使得windows设备句柄转化为opengl支持的设备句柄。
hRC = wglCreateContext(hDC); //获取渲染描述句柄
//得到hRC后,我们激活它,,让它与当前的hDC相关联。
wglMakeCurrent(hDC, hRC); //激活渲染描述句柄
;//cout<<"Init"<<endl;
// m_baiscobj=new baiscobj();
// m_baiscobj->light0();
return TRUE;
}
extern int k;
void OpenGL::init(int Width, int Height)
{
glViewport(0,0,Width,Height); // 设置OpenGL视口大小。
glMatrixMode(GL_PROJECTION); // 设置当前矩阵为投影矩阵。
glLoadIdentity(); // 重置当前指定的矩阵为单位矩阵
gluPerspective // 设置透视图
( 90.0f, // 透视角设置为 45 度
(GLfloat)Width/(GLfloat)Height, // 窗口的宽与高比
0.1f, // 视野透视深度:近点1.0f
3000.0f // 视野透视深度:始点0.1f远点1000.0f
);
// 这和照象机很类似,第一个参数设置镜头广角度,第二个参数是长宽比,后面是远近剪切。
glMatrixMode(GL_MODELVIEW); // 设置当前矩阵为模型视图矩阵
//glLoadIdentity(); // 重置当前指定的矩阵为单位矩阵
//====================================================
}
struct point3f//定义一个三维变量结构
{double x;
double y;
double z;
};
#define MAP_W 32 // size of map along x-axis 32
#define MAP_SCALE 24.0f // the scale of the terrain map
#define MAP MAP_W*MAP_SCALE/2
point3f n_vector;
// float xyz[3];
float nimh=0,sx,sz; //上一次3D鼠
void picter(float x,float y,float z);
double modelview[16]; // 定义保存视图矩阵数组
double projection[16]; // 定义保存投影矩阵数组
int viewport[4]={0,0,800,600}; // 定义保存屏幕尺寸数组
POINT mouse;
point3f nearPoint;
point3f farPoint;
point3f xyz;
#define FRAND (((float)rand()-(float)rand())/RAND_MAX)
void OpenGL::Render()//OpenGL图形处理
{
GetCursorPos(&mouse);
ScreenToClient(hWnd,&mouse);
//下面对鼠标位置进行编程。
//首先转化为opengl的视口坐标,视口坐标实际上就是窗口坐标,因为前面已经设定。
//下面把屏幕坐标转Opengl坐标:
mouse.x=mouse.x,
mouse.y=Height-mouse.y;
//;//cout<<mouse.x<<endl;
//;//cout<<mouse.y;
// ;//cout<<mouse.x<<" "<<mouse.y<<endl;
//下面把屏幕坐标转化为3D坐标
glGetDoublev(GL_MODELVIEW_MATRIX,modelview); // 获取视图矩阵
glGetDoublev(GL_PROJECTION_MATRIX,projection); // 获取投影矩阵
glGetIntegerv(GL_VIEWPORT,viewport); // 获取视口大小
gluUnProject( (double)mouse.x, // 窗口坐标X
(double)mouse.y, // 窗口坐标Y
0.0f, // 获取近裁剪面上的交点
modelview, // 视图矩阵
projection, // 投影矩阵
viewport, // 屏幕视区
&nearPoint.x, // 获得的近点3D坐标值X
&nearPoint.y, // 获得的近点3D坐标值Y
&nearPoint.z // 获得的近点3D坐标值Z
);
gluUnProject( (double)mouse.x, // 窗口坐标X
(double)mouse.y, // 窗口坐标Y
1.0f, // 获取近裁剪面上的交点
modelview, // 视图矩阵
projection, // 投影矩阵
viewport, // 屏幕视区
&farPoint.x, // 获得的近点3D坐标值X
&farPoint.y, // 获得的近点3D坐标值Y
&farPoint.z // 获得的近点3D坐标值Z
);
//Lbutdown=false;
dir[0]=n_vector.x=farPoint.x-nearPoint.x;
dir[1]=n_vector.y=farPoint.y-nearPoint.y;
dir[2]=n_vector.z=farPoint.z-nearPoint.z;
org[0]=nearPoint.x;
org[1]=nearPoint.y;
org[2]=nearPoint.z;
end[0]=farPoint.x;
end[1]=farPoint.y;
end[2]=farPoint.z;
IsFromFront=false;
nearestobject* pNearest=nearestobject::GetNearestP();
pNearest->Init(org,end);
/*
for(int i=0;i<N;i++)
{
int n_triangle;
Triangle* p_nTriangle=object[i].getTriangles(n_triangle);
for(int i=0;i<n_triangle;i++)
Triangle[i].get(a,b,c);
calculateInterWithTriangle(,b,c);
}
*/
glClearColor(0.50f, 0.70f, 0.90f, 1.0f); // 设置刷新背景色
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);// 刷新背景
// glLoadIdentity();
// 重置当前的模型观察矩阵
glPushMatrix();//压入堆栈
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
picter(-15,-25,-40);// 更新窗口
glEnable(GL_TEXTURE_2D); //使用纹理
glTranslatef(0,0,-280);
glBindTexture(GL_TEXTURE_2D, m_ID);//
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-Width/2, -Height/2, 0.0f);// 前
glTexCoord2f(1.0f, 0.0f); glVertex3f( Width/2,-Height/2, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( Width/2, Height/2, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-Width/2, Height/2, 0.0f);
glEnd();
glPopMatrix();
glFlush();
SwapBuffers(hDC); // 切换缓冲区
}
void OpenGL::CleanUp()
{ wglMakeCurrent(hDC, NULL); //清除OpenGL
wglDeleteContext(hRC); //清除OpenGL
}
float r=0;
void picter(float x,float y,float z)//组合图形
{
BSPTree myTree;
static int n_iTriangles;
//TheTreeObect(float *triangle[3][3],int n1)
float triangle [2][3][3];
for(int j=0;j<1;j=+2)
{
triangle[j][0][0]=0+j;
triangle[j][0][1]=2+j;
triangle[j][0][2]=0+j;
triangle[j][1][0]=0+j;
triangle[j][1][1]=1+j;
triangle[j][1][2]=0+j;
triangle[j][2][0]=0+j;
triangle[j][2][1]=0+j;
triangle[j][2][2]=1+j;
triangle[j+1][0][0]=1+j;
triangle[j+1][0][1]=0+j;
triangle[j+1][0][2]=1;
triangle[j+1][1][0]=0+j;
triangle[j+1][1][1]=1+j;
triangle[j+1][1][2]=0+j;
triangle[j+1][2][0]=-1+j;
triangle[j+1][2][1]=0+j;
triangle[j+1][2][2]=0+j;
}
TheTreeObect obj(triangle,2);
// cout<<n_iTriangles++<<endl;
myTree.UpdateByModels(obj.getTriangles(),obj.getN());
myTree.addObject(obj);
// myTree.outPut();
glPushAttrib(GL_CURRENT_BIT);//保存现有颜色属实性
glTranslatef(0,0,-30); //平台的定位
glPushMatrix();//平台-==============================
glTranslatef(x,y+0.5f,z); //平台的定位
glColor3f(0.0f,1.0f,0.2f); //绿色
auxSolidCube(1); //方台(边长)
glTranslatef(0.0f,0.8f,0.0f); //架的位置调整,上升0.8
glColor3f(0.0f,0.0f,1.0f); //蓝色
auxSolidBox(.2f,1.3f,.2f); //长方架(宽、高、长)
glPopMatrix();
glPushMatrix();//雷达==============================
glTranslatef(x,y+2.5f,z); //雷达的定位1
glRotatef(r-90,0.0,1.0,0.0); //雷达旋转2
//=======================================
glColor3f(1.0f,1.0f,1.0f); //白色
glRotatef(45, 1.0, 0.0, 0.0); //盘的角度调整,仰30度
auxWireCone(1.5,0.6f); //线园锥盘(底半径、高)
//=======================================
glRotatef(180, 1.0, 0.0, 0.0); //杆的角度调整,反方向转
glTranslatef(0.0f,0.0f,-0.7f); //杆的位置调整,缩进一点
auxWireCone(0.2f,2.0f); //园锥杆(底半径、高)
glColor3f(FRAND,0,0); //随机红色
glTranslatef(0.0f,0.0f,2.0f); //杆的位置调整,缩进一点
auxSolidSphere(0.1f); //园(半径)
glPopMatrix();
glPushMatrix();//火箭=============================
glTranslatef(x,y+10.0f,z); //火箭的定位
glRotatef(r, 0.0, 1.0, 0.0); //火箭的旋转
glTranslatef(15,0,0); //火箭的定位
//=============================================
glColor3f(1.0f,0.0f,0.0f); //红色
glRotatef(180, 0.0, 1.0, 0.0); //角度调整,与雷达平行,箭头朝前
auxSolidCone(.2,0.6); //园锥(底半径、高)
//=============================================
glColor3f(1.0f,1.0f,1.0f); //白色
glRotatef(90, 1.0, 0.0, 0.0); //角度调整,与火箭头对接
glTranslatef(0.0f,-1.0f,0); //位置调整,与火箭头对接
auxSolidCylinder(.2f,1); //园柱(半径、高)
glRotatef(-270, 1.0, 0.0, 0.0);
glColor3f(FRAND+.6f,0.2f,0.0f); //随机色
glTranslatef(0.0f,-0.0f,-0.2f); //位置调整,缩进一点
auxSolidCone(.2,1.5); //园锥(底半径、高)
glPopMatrix();
glPopAttrib();//恢复前一属性
r+=0.5f;if(r>360) r=0;
}