以前還在學校時,有過強烈的目睹高維物體的愿望,也想自己實現一個4維立方體試試,于是先在網絡上到處找n維立方體有關的展示視頻,在youtobe上發現了不少,一看就是一整天,結果第二天有別的事情,干別的事去了,當時連規律都沒有找,想法就此結束。
今天突然又有了興致,于是決定好好分析一番。
從最基本開始,點,我們容易推出,0維到n維,超立方體的點數是2的n次方。
另外還容易推出:每增加一維,就會誕生新的空間概念,例如,0維只有點的空間概念,1維誕生了線,2維誕生了面,3維誕生了體,4維誕生了4維體.......
并且新空間概念的定義都是由上一個概念往新的維度拉伸產生的。
而比較難推出的關鍵一點就是:往新的維度拉伸的時侯,已有的某個概念增加的數量=原來的數量*2+低一級的概念的數量。例如,2維往3維拉伸正方形時,面數量即立方體的面數=正方形的面數*2+正方形線的數量;立方體線數=正方形線數*2+正方形點的數量
證明方法,比較嚴密的方法還想不出,不過很容易想到:往新的維度拉伸時,拉伸的起點和終點使某空間概念的數量拷貝了一份,另外拉伸時,比該空間概念底一級的空間概念拉伸產生了該空間概念。
這個說得比較抽象,具體公式可以由下面的圖表示出:
有了這些概念后,可以編程出一些內容了~~~
由于在OpenGL中體是用面包裝起來表示的,因此我們必須找出n維立方體中點、線、面之間的規律,至于更高一層概念的規律可以暫時不理了。先給出一個還不完整類聲明:
1
#pragma once
2
#include "mainWindowStyle.h"
3
4
class CSuperCube:public CY_Screen
5

{
6
//-----------------------------------------------------------
7
int MaxDim;//維度數量
8
int *PointsCount;
9
int *LinesCount;
10
int *FaceCount;
11
//-----------------------------------------------------------
12
13
float Length;//邊長
14
//-----------------------------------------------------------------------------------------
15
bool isDone;//已經可以渲染的標志
16
17
float *Points;//n維空間中的點(以DimensionNum為一組為一個點坐標,PointNum為點數量,所以該float數組大小為DimensionNum*PointNum)
18
int DimensionNum;
19
int PointNum;
20
21
struct SLine
22
{
23
float *points1;
24
float *points2;
25
SLine()
26
{
27
points1=0;
28
points2=0;
29
}
30
};
31
SLine *Lines;//n維空間中的線(以2個點的x坐標索引為起始)
32
int LineNum;
33
34
struct SFace
35
{
36
float *points1;
37
float *points2;
38
float *points3;
39
float *points4;
40
SFace()
41
{
42
points1=0;
43
points2=0;
44
points3=0;
45
points4=0;
46
}
47
};
48
int FaceNum;
49
SFace *Faces;//n維空間中的面
50
//---------------------------------------------------------------------------------------------
51
52
53
void CaculatePHelp(int currentDim);
54
void CaculateLHelp(int currentDim);
55
void CaculateFHelp(int currentDim);
56
inline int PtAtIndex(int i)const
57
{
58
return i*DimensionNum;
59
}
60
public:
61
CY_TextBox *DimensionInput;
62
63
64
CY_Button *CreateBtn;
65
66
//初始化各個維度的立方體中,點、線、面的數量
67
//輸入:maxDim最大維數
68
void InitMaxPLF(int maxDim);
69
70
//計算Dim維度下的立方體的點、線、面分布
71
void CaculatePLF(int Dim);
72
};

2

3

4

5



6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22



23

24

25

26



27

28

29

30

31

32

33

34

35



36

37

38

39

40

41



42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57



58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

初始化點、線、面在各個維度立方體中的數量:其中maxDim表示最大維度,一般設一個小于16的值,
1
void CSuperCube::InitMaxPLF(int maxDim)
2

{
3
if (MaxDim || maxDim<3)
4
return;
5
6
MaxDim=maxDim+1;
7
8
PointsCount=new int[MaxDim];
9
LinesCount=new int[MaxDim];
10
FaceCount=new int[MaxDim];
11
12
int i;
13
14
PointsCount[0]=1;
15
for (i=1;i<MaxDim;++i)
16
PointsCount[i]=PointsCount[i-1]*2;
17
18
LinesCount[0]=0;
19
LinesCount[1]=1;
20
for (i=2;i<MaxDim;++i)
21
LinesCount[i]=LinesCount[i-1]*2+PointsCount[i-1];
22
23
FaceCount[0]=0;
24
FaceCount[1]=0;
25
FaceCount[2]=1;
26
for(i=3;i<MaxDim;++i)
27
FaceCount[i]=FaceCount[i-1]*2+LinesCount[i-1];
28
}

2



3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

下一步開始定位在Dim維空間中點、線、面的分布:
1
void CSuperCube::CaculatePLF(int Dim)
2

{
3
if(!MaxDim || Dim<2 || Dim>=MaxDim)return;
4
5
if(isDone)
6
{
7
delete []Points;
8
delete []Lines;
9
delete []Faces;
10
}
11
12
//-------------------------------------分配好內存空間
13
DimensionNum=Dim;
14
PointNum=PointsCount[DimensionNum];
15
LineNum=LinesCount[DimensionNum];
16
FaceNum=FaceCount[DimensionNum];
17
18
Points=new float[PointNum*DimensionNum];
19
for (int i=0;i<PointNum*DimensionNum;++i)
20
{
21
Points[i]=0;
22
}
23
24
Lines=new SLine[LineNum];
25
Faces=new SFace[FaceNum];
26
27
//-------------------------------------計算值
28
int currentDim=0;
29
while (currentDim<=DimensionNum)
30
{
31
CaculatePHelp(currentDim);
32
//CaculateLHelp(currentDim);
33
//CaculateFHelp(currentDim);
34
++currentDim;
35
}
36
}
其中從while (currentDim<=DimensionNum)那句開始就是算法的所在,目前只完成點空間分布的算法,思路是:先把所有點所有坐標初始化為0.
2



3

4

5

6



7

8

9

10

11

12

13

14

15

16

17

18

19

20



21

22

23

24

25

26

27

28

29

30



31

32

33

34

35

36

從0維開始往上計算坐標,0維時,得到第一個點,坐標為0;以后每次增加一個維度,都把前面計算好的所有點的原來維度復制到新的一批點,對新的維度值設為Length,這個值即n維立方體的邊長:
1
void CSuperCube::CaculatePHelp(int currentDim)
2

{
3
int i;
4
//----------------------點計算
5
if(currentDim==0)
6
return;
7
else
8
{
9
int targetStart=2<<(currentDim-1);//復制的起始點
10
int targetEnd=2<<currentDim;//復制的結束點下一點
11
for (i=targetStart;i<targetEnd;++i)
12
{
13
int index=DimensionNum*i;//目標點的x坐標索引
14
int source=DimensionNum*targetStart;//來源點的x坐標索引負偏移量
15
for (int j=0;j<currentDim;++j)
16
{
17
Points[index+j]=Points[index-source+j];//復制
18
}
19
Points[index+currentDim]=Length;//新加的維度設為邊長
20
}
21
}
22
}

2



3

4

5

6

7

8



9

10

11

12



13

14

15

16



17

18

19

20

21

22

線的空間分布比點的分布計算難了些,不過已經初步分析出來,思路大概如下:
初始化1維的線的兩端點分別是索引點1,索引點2;以后每增加一個維度,把原來已經初始化了的線復制過來,再把線的兩個索引點的值全部偏移“2的(當前維度-1)次方”,再初始化“2的(當前維度-1)次方”條邊,起始點索引分別為前“2的(當前維度-1)次方”個點,終點的索引點分別為接著的“2的(當前維度-1)次方”個點。
線的空間分布代碼明天貼出。
接下來,面的空間分布計算又更進一步難了,還有最后一個問題就是所有OpenGL渲染要素完成后,為了展示效果,還要旋轉這個n維超立方體,于是需要旋轉矩陣,n維矩陣的旋轉公式應該如何推導,這兩個問題各位圖形愛好者共同想想,一起努力~~~