注意:如果需要转载,请注明作者
作者:陈昱(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) 阅读(2312)
评论(9) 编辑 收藏 引用 所属分类:
图形学 、
算法