注意:如果需要转载,请注明作者
作者:陈昱(CY)继续
上一章写,根据上一章线段存储的思路,完成线的复制代码如下:
1void CSuperCube::CaculateLHelp(int currentDim)
2{
3 //---------------------------边计算
4 if (currentDim==0)return;
5 if(currentDim==1)
6 {
7 Lines[0].points1=&Points[0];
8 Lines[0].points2=&Points[DimensionNum];
9 return;
10 }
11 else
12 {
13 //----------------------------------------------------------复制产生的边
14 int targetStar=LinesCount[currentDim-1];//复制的起始边
15 int targetEnd=LinesCount[currentDim-1]*2;//复制的结束边下一条边
16 for(int i=targetStar;i<targetEnd;++i)
17 {
18 Lines[i].points1=Lines[i-targetStar].points1+DimensionNum*(1<<(currentDim-1));//指针偏移
19 Lines[i].points2=Lines[i-targetStar].points2+DimensionNum*(1<<(currentDim-1));
20 }
21 //------------------------------------------复制部分完成,增加拉伸部分产生的边
22 targetStar=targetEnd;//拉伸边存储起始
23 targetEnd=targetStar+(1<<(currentDim-1));//拉伸边存储结束的下一条边
24 for(int i=targetStar;i<targetEnd;++i)
25 {
26 Lines[i].points1=&Points[(i-targetStar)*DimensionNum];
27 Lines[i].points2=&Points[(i-targetStar*2+targetEnd)*DimensionNum];
28 }
29 }
30}
经过查找维基百科,矩阵旋转采用所说的吉文斯旋转
http://zh.wikipedia.org/w/index.php?title=Givens%E6%97%8B%E8%BD%AC&variant=zh-cn于是有了点和线的数据,可以初步用OpenGL渲染了!!于是把面的数据生成先抛到一边,迫不及待完成UI界面、键盘交互。
目前为止代码如下:(由于
上一章的代码没有debug,难免有些错误,上一章的代码就不修改了,这里贴出正确的代码,后面加上demo演示)
.h文件:
1#pragma once
2#include "mainWindowStyle.h"
3#include "common/Render/CY_Camera.h"
4
5class CSuperCube:public CY_Screen
6{
7 //-----------------------------------------------------------
8 int MaxDim;//维度数量
9 int *PointsCount;
10 int *LinesCount;
11 int *FaceCount;
12 //-----------------------------------------------------------
13
14 float Length;//边长
15 //-----------------------------------------------------------------------------------------
16 bool isDone;//已经可以渲染的标志
17
18 float *Points;//n维空间中的点(以DimensionNum为一组为一个点坐标,PointNum为点数量,所以该float数组大小为DimensionNum*PointNum)
19 int DimensionNum;
20 int PointNum;
21
22 struct SLine
23 {
24 float *points1;
25 float *points2;
26 SLine()
27 {
28 points1=0;
29 points2=0;
30 }
31 };
32 SLine *Lines;//n维空间中的线(以2个点的x坐标索引为起始)
33 int LineNum;
34
35 struct SFace
36 {
37 float *points1;
38 float *points2;
39 float *points3;
40 float *points4;
41 SFace()
42 {
43 points1=0;
44 points2=0;
45 points3=0;
46 points4=0;
47 }
48 };
49 int FaceNum;
50 SFace *Faces;//n维空间中的面
51 //---------------------------------------------------------------------------------------------
52 //初始化各个维度的立方体中,点、线、面的数量
53 //输入:maxDim最大维数
54 void InitMaxPLF(int maxDim);
55
56
57 //计算Dim维度下的立方体的点、线、面
58 void CaculatePLF(int Dim);
59 void CaculatePHelp(int currentDim);
60 void CaculateLHelp(int currentDim);
61 void CaculateFHelp(int currentDim);
62
63
64 inline int PtAtIndex(int i)const
65 {
66 return i*DimensionNum;
67 }
68
69 //吉文斯矩阵旋转,
70 //输入:dimNum空间维度(>=2,<=15)、point点指针、theta角度、dim1旋转面的第一个方向、dim2旋转面的第二个方向(值从1---15)
71 //输出:point点的坐标值
72 inline void GivensRotateMatrix(int dimNum,float *point,float theta,int dim1,int dim2);
73
74 void Rotate(float theta,int dim1,int dim2);
75public:
76 CSuperCube();
77 ~CSuperCube();
78
79 //-----------------------------------
80 CY_TextBox *DimensionInput;
81 CY_Label *InputLabel;
82 CY_Button *CreateBtn;
83 CY_CheckBox *FaceLineRender;
84
85 CY_Camera theCamera;
86 //------------------------------------
87
88 unsigned long lastTime;
89 unsigned long currentTime;
90 void UpDate();
91
92 void DrawScene();
93
94 void LineRender();
95 void FaceRender();
96
97
98 void OnKeyDown();
99 void OnCreateBtnDown(CY_Controller *);
100};
.cpp文件:
1#include "Screens.h"
2#include <math.h>
3
4
5CSuperCube::CSuperCube():CY_Screen()
6{
7 isDone=false;
8 Length=50.0f;
9 MaxDim=0;//维度数量
10
11 PointsCount=0;//点数
12 LinesCount=0;//线数
13 FaceCount=0;//面数
14
15 Points=0;//n维空间中的点(以DimensionNum为一组为一个点坐标,PointNum为点数量,所以该float数组大小为DimensionNum*PointNum)
16 DimensionNum=0;
17 PointNum=0;
18
19 Lines=0;//n维空间中的线(以2个点的x坐标索引为起始)
20 LineNum=0;
21
22 Faces=0;
23 FaceNum=0;
24
25 //------------------------------------------------
26 InputLabel=new CY_Label(L"请输入超立方体维度:",20,20);
27 this->addContent(InputLabel);
28 DimensionInput=new CY_TextBox(160,15,100);
29 DimensionInput->SetNumberic();
30 this->addContent(DimensionInput);
31 CreateBtn=new CY_Button(L"马上生成~~",windowWidth/2-50,windowHeight-50,100,30);
32 CreateBtn->OnMouseUpEvent.Bind(this,&CSuperCube::OnCreateBtnDown);
33 this->addContent(CreateBtn);
34 FaceLineRender=new CY_CheckBox(400,18,L"线框渲染",true);
35 this->addContent(FaceLineRender);
36
37
38 theCamera.SetTargetPosition(Vector3(0,0,0));
39 theCamera.SetPosition(Vector3(0,0,200));
40 theCamera.SetUpVector(Vector3(0,1,0));
41
42
43 currentTime=GetTickCount();
44 lastTime=currentTime;
45 //--------------------------------------------------
46
47 InitMaxPLF(15);
48}
49CSuperCube::~CSuperCube()
50{
51 if (PointsCount) delete []PointsCount;
52 if(LinesCount) delete[]LinesCount;
53 if(FaceCount)delete[]FaceCount;
54
55 if(Points)delete []Points;
56 if(Lines)delete []Lines;
57 if(Faces)delete []Faces;
58}
59//----------------------------------------------------------------------------------------------------------------------------
60void CSuperCube::InitMaxPLF(int maxDim)
61{
62 if (MaxDim || maxDim<3 || maxDim>15)
63 return;
64
65 MaxDim=maxDim+1;
66
67 PointsCount=new int[MaxDim];
68 LinesCount=new int[MaxDim];
69 FaceCount=new int[MaxDim];
70
71 int i;
72
73 PointsCount[0]=1;
74 for (i=1;i<MaxDim;++i)
75 PointsCount[i]=PointsCount[i-1]*2;
76
77 LinesCount[0]=0;
78 LinesCount[1]=1;
79 for (i=2;i<MaxDim;++i)
80 LinesCount[i]=LinesCount[i-1]*2+PointsCount[i-1];
81
82 FaceCount[0]=0;
83 FaceCount[1]=0;
84 FaceCount[2]=1;
85 for(i=3;i<MaxDim;++i)
86 FaceCount[i]=FaceCount[i-1]*2+LinesCount[i-1];
87}
88inline void CSuperCube::GivensRotateMatrix(int dimNum,float *point,float theta,int dim1,int dim2)
89{
90 if(dimNum<2 || dimNum>=16 || dim1<0 || dim1>dimNum || dim2<0 ||dim2>dimNum || dim1==dim2)return;
91
92 float temp1=cos(theta);
93 float temp2=sin(theta);
94 float temp=point[dim1]*temp1-point[dim2]*temp2;
95
96 point[dim2]=point[dim1]*temp2+point[dim2]*temp1;
97 point[dim1]=temp;
98}
99void CSuperCube::Rotate(float theta,int dim1,int dim2)
100{
101 for(int i=0;i<PointNum;++i)
102 GivensRotateMatrix(DimensionNum,&Points[i*DimensionNum],theta,dim1,dim2);
103}
104//-----------------------------------------------------------------------------------------------------------------------------
105void CSuperCube::CaculatePHelp(int currentDim)
106{
107 int i;
108 //----------------------点计算
109 if(currentDim==0)
110 return;
111 else
112 {
113 int targetStart=1<<(currentDim-1);//复制的起始点
114 int targetEnd=1<<currentDim;//复制的结束点下一点
115 for (i=targetStart;i<targetEnd;++i)
116 {
117 int index=DimensionNum*i;//目标点的x坐标索引
118 int source=DimensionNum*targetStart;//来源点的x坐标索引负偏移量
119 for (int j=0;j<currentDim-1;++j)
120 {
121 Points[index+j]=Points[index-source+j];//复制
122 }
123 Points[index+currentDim-1]=Length;//新加的维度设为边长
124 }
125 }
126}
127void CSuperCube::CaculateLHelp(int currentDim)
128{
129 //---------------------------边计算
130 if (currentDim==0)return;
131 if(currentDim==1)
132 {
133 Lines[0].points1=&Points[0];
134 Lines[0].points2=&Points[DimensionNum];
135 return;
136 }
137 else
138 {
139 //----------------------------------------------------------复制产生的边
140 int targetStar=LinesCount[currentDim-1];//复制的起始边
141 int targetEnd=LinesCount[currentDim-1]*2;//复制的结束边下一条边
142 for(int i=targetStar;i<targetEnd;++i)
143 {
144 Lines[i].points1=Lines[i-targetStar].points1+DimensionNum*(1<<(currentDim-1));//指针偏移
145 Lines[i].points2=Lines[i-targetStar].points2+DimensionNum*(1<<(currentDim-1));
146 }
147 //------------------------------------------复制部分完成,增加拉伸部分产生的边
148 targetStar=targetEnd;//拉伸边存储起始
149 targetEnd=targetStar+(1<<(currentDim-1));//拉伸边存储结束的下一条边
150 for(int i=targetStar;i<targetEnd;++i)
151 {
152 Lines[i].points1=&Points[(i-targetStar)*DimensionNum];
153 Lines[i].points2=&Points[(i-targetStar*2+targetEnd)*DimensionNum];
154 }
155 }
156}
157void CSuperCube::CaculateFHelp(int currentDim)
158{
159
160}
161void CSuperCube::CaculatePLF(int Dim)
162{
163 if(!MaxDim || Dim<2 || Dim>=MaxDim)return;
164
165 if(isDone)
166 {
167 delete []Points;
168 delete []Lines;
169 delete []Faces;
170 }
171
172 //-------------------------------------分配好内存空间
173 DimensionNum=Dim;
174 PointNum=PointsCount[DimensionNum];
175 LineNum=LinesCount[DimensionNum];
176 FaceNum=FaceCount[DimensionNum];
177
178 Points=new float[PointNum*DimensionNum];
179 for (int i=0;i<PointNum*DimensionNum;++i)
180 {
181 Points[i]=0;
182 }
183
184 Lines=new SLine[LineNum];
185 Faces=new SFace[FaceNum];
186
187 //-------------------------------------计算值
188 int currentDim=0;
189 while (currentDim<=DimensionNum)
190 {
191 CaculatePHelp(currentDim);
192 CaculateLHelp(currentDim);
193 //CaculateFHelp(currentDim);
194 ++currentDim;
195 }
196 //-----------------------------------把n维体中心移到原点
197 for(int i=0;i<DimensionNum*PointNum;++i)
198 {
199 Points[i]-=(Length/2);
200 }
201}
202//---------------------------------------------------------------------------------------------------------------------------
203void CSuperCube::UpDate()
204{
205 currentTime=GetTickCount();
206 unsigned long dalta=currentTime-lastTime;
207 lastTime=currentTime;
208
209 int i=-1,j=-1;
210 for (i=0;i<DimensionNum;++i)
211 {
212 if(CY_KeyBoard[48+i])
213 break;
214 }
215 for (j=i+1;j<DimensionNum;++j)
216 {
217 if(CY_KeyBoard[48+j])
218 break;
219 }
220 if(i>=0 && j<DimensionNum)//开始旋转
221 {
222 float theta=dalta*0.0016f;
223 if(CY_KeyBoard[16])//反方向
224 Rotate(-theta,i,j);
225 else
226 Rotate(theta,i,j);
227 }
228}
229void CSuperCube::LineRender()
230{
231 if(!isDone)return;
232
233 glDisable(GL_CULL_FACE);
234 glDisable(GL_LIGHTING);
235 glLineWidth(2.0f);
236 glColor4f(1,1,1,1);
237 for (int i=0;i<LineNum;++i)
238 {
239 glBegin(GL_LINES);
240 glVertex3fv(Lines[i].points1);
241 glVertex3fv(Lines[i].points2);
242 //glVertex3f(30,30,-10);
243 //glVertex3f(-30,30,10);
244 //glVertex3f(30,-30,0);
245 glEnd();
246 }
247
248}
249void CSuperCube::FaceRender()
250{
251
252}
253void CSuperCube::DrawScene()
254{
255 glLoadIdentity();
256 theCamera.ApplyCamera();
257
258 if(FaceLineRender->GetIsCheck())
259 LineRender();
260 else FaceRender();
261}
262//---------------------------------------------------------------------------------------------------------------------------------
263void CSuperCube::OnKeyDown()
264{
265 if(CY_KeyBoard[27])
266 PostMessage(hwnd,WM_CLOSE,0,0);
267}
268void CSuperCube::OnCreateBtnDown(CY_Controller *btn)
269{
270 const wchar_t *content=DimensionInput->GetText();
271 int Dim=_wtoi(content);
272 CaculatePLF(Dim);
273 isDone=true;
274}
然后是非常狂喜的截图:
理论上是可以生成任意大于或等于3的任意维度超立方体的,但是int的有效长度只有16,UINT也只有32,所以目前就限制输入维度是15了。可执行程序在完成面的分布算法后再给出。
posted on 2009-08-01 22:16
陈昱(CY) 阅读(2296)
评论(9) 编辑 收藏 引用 所属分类:
图形学 、
算法