Shell文件(*.shl)是Adams的一种几何形状文件,外形全是由多边形(直线连接的节点组成)表示的。本文介绍一下Shell文件的读取方法,以及在OpenGL中的显示方法。
1. Shell文件格式
Shell文件现在有两个版本。
1.1 版本1的范例:
8 6 1.0
-1.0 -1.0 1.0
-1.0 1.0 1.0
1.0 1.0 1.0
1.0 -1.0 1.0
-1.0 -1.0 -1.0
-1.0 1.0 -1.0
1.0 1.0 -1.0
1.0 -1.0 -1.0
4 1 2 3 4
4 5 6 2 1
3 2 6 7
4 3 7 8 4
4 1 4 8 5
4 8 7 6 5
蓝色行中的第一个数字表示节点的个数,第二个是多边形的数量,第三个是缩放系数(一般情况下为1)。
红色行为每个节点的坐标。绿色行第一个数字为多边形节点的数目,剩下的为每个节点的编号,与红色部分节点的顺序相对应,节点编号是从1开始。
1.2 版本2的范例:
Version: 2
3559 1362 3559 1.000000
-0.020500 0.005692 -0.001418
-0.020500 0.006541 -0.002266
-0.020500 0.005692 -0.000797
-0.020500 0.005692 -0.000797
-0.020500 0.005692 -0.001418
13 14 18 22 27 28 24 20 15 10 6 4 8 12
3 236 71 1
3 33 1 71
5 121 118 110 112 116
15 70 74 76 83 101 104 106 98 95 91 93 88 86 81 79
-0.022787 -0.041839 0.998864
1.000000 -0.000000 0.000000
0.018219 0.496961 0.867581
0.000000 0.923962 0.382485
1.000000 -0.000000 0.000000
蓝色行中的第一个数字表示节点的个数,第二个是多边形的数量,第三个对应紫色行的数目,第四个是缩放系数(一般情况下为1)。
红色和绿色行与版本1的含义一致。紫色行的用处不清楚,Adams帮助文档中只介绍了版本1的格式。
2. 读取Shell文件
C#读取shell文件代码如下,输入变量path是shell文件的路径。
public static void DrawShell(string path) { List<Vector3> points = new List<Vector3>(); //points List<List<int>> seqs = new List<List<int>>(); //sequency List<Vector3> normals = new List<Vector3>(); int lineNumber = 0; //read shl file if (!File.Exists(path)) { MessageBox.Show("Cannot find the shell file"); } string content = File.ReadAllText(path); string[] lines = content.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); bool version2 = false; while (lines[lineNumber].Contains(":")) { lineNumber++; version2 = true; } string[] numbers = lines[lineNumber].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); int ptNum = Convert.ToInt32(numbers[0]); int seqNum = Convert.ToInt32(numbers[1]); int normalNum; float scale; if (version2) { normalNum = Convert.ToInt32(numbers[2]); scale = Convert.ToSingle(numbers[3]); } else { normalNum = 0; scale = Convert.ToSingle(numbers[2]); } for (int i = 0; i < ptNum; i++) { string[] pt = lines[lineNumber + 1 + i].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (pt.Count() == 3) { points.Add(new Vector3( Convert.ToSingle(pt[0].Trim()) * scale, Convert.ToSingle(pt[1].Trim()) * scale, Convert.ToSingle(pt[2].Trim()) * scale) ); } else { points.Add(new Vector3(0f, 0f, 0f)); } } for (int i = 0; i < seqNum; i++) { string[] seq = lines[lineNumber + 1 + ptNum + i].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (seq.Count() > 1) { seqs.Add(seq.ToList().ConvertAll<int>(x => Convert.ToInt32(x))); } } /* if (normalNum > 0) { for (int i = 0; i < normalNum; i++) { string[] pt = lines[lineNumber + 1 + i].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (pt.Count() == 3) { normals.Add(new Vector3( Convert.ToDouble(pt[0].Trim()), Convert.ToDouble(pt[1].Trim()), Convert.ToDouble(pt[2].Trim())) ); } else { normals.Add(new Vector3d(0d, 0d, 0d)); } } } */ foreach(List<int> seq in seqs) { if (seq[0] > 2) { List<Vector3> vertices = new List<Vector3>(); seq.RemoveAt(0); foreach (int index in seq) { vertices.Add(points[index - 1]); } //使用OpenGL显示每个多边形 Tessellation.Triangulate(vertices); } } }
上面代码中的Tessellation.Triangulate(vertices),是使用Glu的网格化(Tessellation)显示形状。该Tessellation类的具体内容,见我的另一篇文章:OPENGL: 多边形网格化(tessellation) 。
下面是读取某个齿轮shell文件的显示结果: