注意:如果需要轉載,請注明作者
作者:陳昱(CY)繼續
上一章寫,根據上一章線段存儲的思路,完成線的復制代碼如下:
1
void 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
5
class 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);
75
public:
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
5
CSuperCube::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
}
49
CSuperCube::~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
//----------------------------------------------------------------------------------------------------------------------------
60
void 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
}
88
inline 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
}
99
void 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
//-----------------------------------------------------------------------------------------------------------------------------
105
void 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
}
127
void 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
}
157
void CSuperCube::CaculateFHelp(int currentDim)
158

{
159
160
}
161
void 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
//---------------------------------------------------------------------------------------------------------------------------
203
void 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
}
229
void 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
}
249
void CSuperCube::FaceRender()
250

{
251
252
}
253
void CSuperCube::DrawScene()
254

{
255
glLoadIdentity();
256
theCamera.ApplyCamera();
257
258
if(FaceLineRender->GetIsCheck())
259
LineRender();
260
else FaceRender();
261
}
262
//---------------------------------------------------------------------------------------------------------------------------------
263
void CSuperCube::OnKeyDown()
264

{
265
if(CY_KeyBoard[27])
266
PostMessage(hwnd,WM_CLOSE,0,0);
267
}
268
void 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) 閱讀(2322)
評論(9) 編輯 收藏 引用 所屬分類:
圖形學 、
算法