您的位置:首页 > 其它

谈谈Processing 3D世界 六 (续)

2016-08-18 16:51 225 查看

setp5 将OBJ文件导入Processing

既然我们知道obj实际上就是一个文本本件,我们何不索性将其改成txt?

这样,我们用Processing的loadStrings()函数就能轻易读取obj的内容到我们程序的内存中,供我们解码后运用。

String dateFileName;
...
String[] lines = loadStrings(dateFileName);
好第五步轻松解决。

setp6 在Processing中解码OBJ文件

结合上一节的知识,我们知道要依靠obj文件来替我们画图,关键是在f(面)的文本行描述上。

...
f 2/2/17 8/11/18 4/4/19
f 4/4/19 8/11/18 6/12/20
...


而这些信息都是用顶点属性索引来描述的。所以我们需要用数组来装载属性,使其拥有索引,以供将来绘图函数按照f(面)的索引序列来调用属性数据。

1.新建OBJ读取类

class OBJLoader {

void init(String dateFileName) {
// 载入obj文件,obj文件需要被转换成txt文件
// 以行为单位装载文本
String[] lines = loadStrings(dateFileName);
}
}


2.为各属性计数

// 在类中新建变量用于个属性计数
int vCount, vtCount, fCount; // 顶点位置、UV、面 计数

// 各属性计数实现方法
void attrArrayCount(String[] lines) {
for(int i = 0; i < lines.length; i++) { // 轮询每行文本
// 查找关键字,给属性计数,这里我们只关心v、vt、f
if(lines[i].startsWith("v ")){          // 顶点位置 计数
vCount++;
}else if(lines[i].startsWith("vt ")) {  // 顶点UV   计数
vtCount++;
}else if(lines[i].startsWith("f ")){    // 面       计数
fCount++;
}
}
}

3.新建并初始化属性数组容器

// vertices
PVector[] v, vt;     // 顶点位置、UV,这里我们先忽略顶点法向量。

// face(*三角面)- fx v/vt/vn v/vt/vn v/vt/vn
int[] fv1, fv2, fv3;    // 顶点位置 索引数组
int[] fvt1, fvt2, fvt3; // 顶点UV   索引数组

// 初始化属性索引数组
void initAttrArray() {

// 初始化顶点位置、UV数组
v  = new PVector[vCount  + 1]; // 注意配合obj文件的语法
vt = new PVector[vtCount + 1]; // 起始数从1开始,这里实际上是让0元素空置了。
// 初始化面数组
fv1 = new int[fCount];
fv2 = new int[fCount];
fv3 = new int[fCount];

fvt1 = new int[fCount];
fvt2 = new int[fCount];
fvt3 = new int[fCount];
}

4.填入属性数据

void assiAttrArray(String[] lines) {

int vIndex  = 1; // 因为F的引用是从1开始,所以v的起始号是1
int vtIndex = 1; // 同上
int fIndex  = 0; // f本身没有描述索引号,所以我们可以按传统安排索引

for(int i = 0; i < lines.length; i++) {

// 记录顶点位置
if(lines[i].startsWith("v ")){

assiV(lines[i], vIndex);
vIndex++;

// 记录顶点UV纹理坐标
}else if(lines[i].startsWith("vt ")) {

assiVt(lines[i], vtIndex);
vtIndex++;

// 记录面构成
}else if(lines[i].startsWith("f ")){

assiF(lines[i], fIndex);
fIndex++;
}
}
}

接着我们逐步来实现其功能

// 处理顶点位置
void assiV(String line, int vIndex) {

// 把此行信息分解成单个的词语,并提取浮点信息
float[] date = float(splitTokens(line));

v[vIndex] = new PVector(date[1] * UNIT, date[2] * UNIT, date[3] * UNIT);

}


// 处理顶点UV
void assiVt(String line, int vtIndex) {

// 把此行信息分解成单个的词语,并提取浮点信息
float[] date = float(splitTokens(line));

vt[vtIndex] = new PVector(date[1], date[2]);

}


// 处理面
void assiF(String line, int fIndex) {

// 把此行信息分解成单个的词语 f1 | 1/1/1 | 2/3/1 | 3/2/2
String[] date = splitTokens(line);
// 处理面的顶点信息
PVector v1 =  fvertex(date[1], fIndex);
PVector v2 =  fvertex(date[2], fIndex);
PVector v3 =  fvertex(date[3], fIndex);

fv1[fIndex] = int(v1.x);
fv2[fIndex] = int(v2.x);
fv3[fIndex] = int(v3.x);

fvt1[fIndex] = int(v1.y);
fvt2[fIndex] = int(v2.y);
fvt3[fIndex] = int(v3.y);
}

5.处理面的顶点信息

// 处理面的顶点的信息
PVector fvertex(String date, int fIndex) {
PVector value = new PVector();

// 因为不清楚数字的位数:123/21/21 | 25452/...
int last_n = 0;
for(int n = 0; n < 100; n++) {
String s = date.substring(n, n + 1); // 获取从参数开始到参数结束的字符串,这里是逐个审核字符
if( s.equals("/")) { // 如果字符为“/”
value.x = int(date.substring(0, n));      // 截取v属性索引
last_n = n + 1;
break;
}
}

for(int n = last_n; n < 100; n++) {
String s = date.substring(n, n + 1);
if( s.equals("/")) {
value.y = int(date.substring(last_n, n)); // 截取vt属性索引
break;
}
}
return value;
}
这样我们就解码并在程序内存中组织好了所有的网格数据,等待绘制。

6.载入obj数据 - 小结

// obj文件需要被转换成txt文件
// 本类暂时只处理v、vt、f数据
class OBJLoader {

// 顶点属性
PVector[] v, vt; // 位置、UV

// 面-属性索引
// (*三角面)- fx v/vt/vn v/vt/vn v/vt/vn
int[] fv1, fv2, fv3;
int[] fvt1, fvt2, fvt3;

// 属性计数
int vCount, vtCount, fCount;

void init(String dateFileName) {
// 以行为单位装载文本
String[] lines = loadStrings(dateFileName);

// 属性计数
attrArrayCount(lines);

// 属性数组初始化
initAttrArray();

// 属性数组赋值
assiAttrArray(lines);
}

// 各属性计数实现方法
void attrArrayCount(String[] lines) {
for(int i = 0; i < lines.length; i++) { // 轮询每行文本
// 查找关键字,给属性计数
if(lines[i].startsWith("v ")){ // 顶点位置 计数
vCount++;
}else if(lines[i].startsWith("vt ")) { // 顶点UV 计数
vtCount++;
}else if(lines[i].startsWith("f ")){ // 面 计数
fCount++;
}
}
}

// 初始化属性数组
void initAttrArray() {

// 初始化顶点位置、UV数组
v = new PVector[vCount + 1]; // 注意配合obj文件的语法
vt = new PVector[vtCount + 1]; // 起始数从1开始,这里实际上是让0元素空置了。

// 初始化面数组
fv1 = new int[fCount];
fv2 = new int[fCount];
fv3 = new int[fCount];

fvt1 = new int[fCount];
fvt2 = new int[fCount];
fvt3 = new int[fCount];
}

void assiAttrArray(String[] lines) {

int vIndex = 1; // 因为F的引用是从1开始,所以v的起始号是1
int vtIndex = 1; // 同上
int fIndex = 0; // f本身没有描述索引号,所以我们可以按传统安排索引

for(int i = 0; i < lines.length; i++) {

// 记录顶点位置
if(lines[i].startsWith("v ")){

assiV(lines[i], vIndex);
vIndex++;

// 记录顶点UV纹理坐标
}else if(lines[i].startsWith("vt ")) {

assiVt(lines[i], vtIndex);
vtIndex++;

// 记录面构成
}else if(lines[i].startsWith("f ")){

assiF(lines[i], fIndex);
fIndex++;
}
}
}

// 处理顶点位置
void assiV(String line, int vIndex) {

// 把此行信息分解成单个的词语,并提取浮点信息
float[] date = float(splitTokens(line));

v[vIndex] = new PVector(date[1] * UNIT, date[2] * UNIT, date[3] * UNIT);

}

// 处理顶点UV void assiVt(String line, int vtIndex) { // 把此行信息分解成单个的词语,并提取浮点信息 float[] date = float(splitTokens(line)); vt[vtIndex] = new PVector(date[1], date[2]); }

// 处理面 void assiF(String line, int fIndex) { // 把此行信息分解成单个的词语 f1 | 1/1/1 | 2/3/1 | 3/2/2 String[] date = splitTokens(line); // 处理面的顶点信息 PVector v1 = fvertex(date[1], fIndex); PVector v2 = fvertex(date[2], fIndex); PVector v3 = fvertex(date[3], fIndex); fv1[fIndex] = int(v1.x); fv2[fIndex] = int(v2.x); fv3[fIndex] = int(v3.x); fvt1[fIndex] = int(v1.y); fvt2[fIndex] = int(v2.y); fvt3[fIndex] = int(v3.y); }

// 处理面的顶点的信息 PVector fvertex(String date, int fIndex) { PVector value = new PVector(); // 因为不清楚数字的位数:123/21/21 | 25452/... int last_n = 0; for(int n = 0; n < 100; n++) { String s = date.substring(n, n + 1); // 获取从参数开始到参数结束的字符串,这里是逐个审核字符 if( s.equals("/")) { // 如果字符为“/” value.x = int(date.substring(0, n)); // 截取v属性索引 last_n = n + 1; break; } } for(int n = last_n; n < 100; n++) { String s = date.substring(n, n + 1); if( s.equals("/")) { value.y = int(date.substring(last_n, n)); // 截取vt属性索引 break; } } return value; }
}

利用obj数据绘制模型再开一个坑好了。一篇帖子太长了就不容易编辑,老是要审核审核的。

下篇帖子继续。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  processing 3d 图形