Python如何读取.x的DirectX的3D格式文件
(其实这是一个陈年老Bug)之前2015年大三下学期看张若愚版本的<<Python科学计算>>发现上面的读取.x的DirectX的3D格式文件的程序有错,最近仔细读了读源码,发现他默认模型的点、面、颜色属性是按顺序排列的,其实不同3D建模工具产生的.x文件的排列是不一样的。
修改后的程序
还有就是作者当时用的那个VPython3D库其实真的好用,但是目前这个项目到0.6版就不再维护了,和作者交流他说:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
from visual import *
def search_line_startswith(f, pattern):
while True:
line = f.readline()
if line == "": return False
if line.strip().startswith(pattern):
return True
def test_read(f,pattern):
i=0;
while True:
line = f.readline();print i;i+=1;
if line == "": print 'wtf';return False;
if line.strip().startswith(pattern):
return True
def read_directx_model(filename, double=False):
f = open(filename)
search_line_startswith(f, "Mesh") # 定位Mesh行
point_num = int(f.readline().split(";")[0]) # 读入顶点数
points = np.zeros((point_num, 3)) # 初始化保存顶点坐标的数组
# 读入所有顶点坐标
for i in xrange(point_num):
points[i, :] = [float(x) for x in f.readline().split(";")[:3]]
this_line =f.readline();#print this_line;
face_num = int(this_line.split(";\r\n")[0]) # 读入面数
# 初始化三角形的顶点坐标数组
pfaces = zeros( (face_num*3 , 3)) # 正面的顶点下标
# 建造所有的模型面的顶点坐标数组,将面的顶点下标替换为顶点坐标
cnt = 0
for i in xrange(face_num):
p_index = [int(x) for x in f.readline().split(";")[1].split(",")]
for j in xrange(3):
pfaces[cnt, :] = points[p_index[j], :]
cnt += 1
search_line_startswith(f, "MeshMaterialList") # 定位材质
color_num = int(f.readline().split(";")[0]) # 读入材质数
face_color_num = int(f.readline().split(";")[0]) # 读出面数
# 读入每个面的材质下标
face_color_list=[]
for i in xrange(face_color_num):
sss = f.readline();#print sss;
face_color_list.append( int(sss.strip(",;\n\r")) )
colors = np.zeros((color_num, 3)) # 初始化储存材质颜色的数组
# 读入所有材质的颜色
for i in xrange(color_num):
search_line_startswith(f, "Material")
colors[i,:] = [float(x) for x in f.readline().split(";")[:3]]
# 初始化保存每个顶点颜色的数组
pcolors = np.zeros( (face_color_num*3, 3), np.float)
# 建造顶点颜色数组,将面的材质下标替换为顶点的材质颜色
cnt = 0
for i in xrange(face_color_num):
color_idx = face_color_list[i]
for j in xrange(3):
pcolors[cnt, :] = colors[color_idx,:]
cnt += 1
f = open(filename);
search_line_startswith(f, "MeshNormals") # 定位法线方向
#test_read(f,"MeshNormals");
# 读入法线方向
this_line = f.readline();#print [this_line];#print 'here';
point_num = int(this_line.split(";")[0])
npoints = np.zeros((point_num, 3))
for i in xrange(point_num):
npoints[i,:] = [float(x) for x in f.readline().split(";")[:3]]
face_num = int(f.readline().split(";")[0]) # 读入面数
# 初始化顶点法线方向数组
nfaces = np.zeros( (face_num*3 , 3), np.float)
# 建造顶点法线方向数组,将每个面的法线下标替换为实际的法线方向
cnt = 0
for i in xrange(face_num):
p_index = [int(x) for x in f.readline().split(";")[1].split(",")]
for j in xrange(3):
nfaces[cnt, :] = npoints[p_index[j],:]
cnt += 1
f.close()
if double:
pfaces = np.vstack((pfaces, pfaces[::-1]))
nfaces = np.vstack((nfaces, nfaces[::-1]))
pcolors = np.vstack((pcolors, pcolors[::-1]))
model_frame = frame()
# 使用 顶点坐标数组,顶点颜色数组和顶点法线方向数组构造模型
# print pfaces[0].shape();print pfaces[0].shape();
#pcolors[:,0]=np.random.random(size = pcolors[:,0].shape)*0.7;
#pcolors[:,1]=np.random.random(size = pcolors[:,1].shape)*0.7;
#pcolors[:,2]=np.random.random(size = pcolors[:,2].shape)*0.7;
#print pcolors[:,0];print pcolors[1];
model = faces( pos = pfaces, normal = nfaces, color = np.random.random(3), frame = model_frame )
return model_frame
if __name__ == "__main__":
import sys
scene.background = (12, 222, 222)
#scene.title = sys.argv[1]
read_directx_model("models_dx/truck.x", True)