3D模型的格式种类繁多:常见的格式包括OBJ、STL、U3D等等,其中最简单当属OBJ文件。OBJ文件是Alias | Wavefront公司为它的一套基于工作站的3D建模和动画软件“AdvancedVisualizer”开发的一种标准3D模型文件格式,适合3D软件模型之间的互导。应用OBJ文件一般包括三个子文件,分别是.obj(模型文件)、.mtl(材料库文件)、.jpg(纹理文件)。该博文的重点是讲解obj模型文件的基础操作。
用txt打开obj文件,开头是一系列的特征标签,提示存储的是什么样的数据。了解常用的标签f,v,vt,vn的含义即可。
1.面(符号f)【f v/vt/vn v/vt/vn v/vt/vn】: 每个三角面片由三部分组成,每部分分别由顶点索引v 以及对应的纹理索引和法向量索引vn组成。
obj文件不包括纹理坐标和法向量:f v v v
obj文件有纹理坐标,没有法向量:f v/vt v/vt v/vt
obj文件没有纹理坐标,有法向量:f v//vn v//vn v//vn
2.顶点(符号v)【v x y z 】: 每个顶点的xyz三个坐标。
3.顶点纹理(符号vt)【vt u v w】: 每个顶点的纹理是取纹理图片上(u,v)坐标的像素值,w形容三维纹理。
4.顶点法向量(符号vn)【vn x y z】: 三角面片的朝向由构成顶点对应的法向量做矢量和决定,即三个法向量分别对xyz坐标相加再除以3。
总结:
顶点数、顶点法向量数和顶点纹理数三者数量一致,面数与其他数据无关,多个面可能公用一个顶点,面的颜色是由三个顶点的纹理插值计算而来。
def read_objPoint(model_path):
obj_mesh = {'v': [], 'vt': [], 'vn': [], 'f': []}
with open(model_path, 'r') as f:
for line in f.readlines():
values = line.strip().split()
if values == []:
continue
if values[0] == 'v':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vt':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vn':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'f':
obj_mesh[values[0]].append(
[list(map(lambda x: int('0' + x), value.split('/'))) for value in values[1:]])
return obj_mesh
def save_objpoint(new_model_savepath, obj_mesh):
with open(new_model_savepath, 'w') as f:
for obj_key in obj_mesh:
if obj_key == 'v':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key]+values + ['\n']])
if obj_key == 'vt':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == 'vn':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == "f":
f.writelines([''.join(list(map(lambda x: (str(x) + "/"), value))).replace('0', '').strip('/')for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
任何平移、旋转、缩放及其混合操作前,通常根据模型中心先将模型位移到空间坐标系的正中心区域,即模型中心位应该与空间坐标系原点重合,具体做法就是将模型所有点xyz坐标与模型中心点xyz坐标对应相减,然后再将模型放回原位复原,即模型所有点xyz坐标与模型中心点xyz坐标对应相减。
def get_Preprocessmatrix(centroid):
#centroid是模型中心点xyz坐标
# 中心位移到原点
to_origin_matrix = np.array([
[1, 0, 0, -centroid[0]],
[0, 1, 0, -centroid[1]],
[0, 0, 1, -centroid[2]],
[0, 0, 0, 1]
])
# 位置复原
form_origin_matrix = np.array([
[1, 0, 0, centroid[0]],
[0, 1, 0, centroid[1]],
[0, 0, 1, centroid[2]],
[0, 0, 0, 1]
])
return to_origin_matrix,form_origin_matrix
import numpy as np
#加载模型
def read_objPoint(model_path):
obj_mesh = {'v': [], 'vt': [], 'vn': [], 'f': []}
with open(model_path, 'r') as f:
for line in f.readlines():
values = line.strip().split()
if values == []:
continue
if values[0] == 'v':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vt':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vn':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'f':
obj_mesh[values[0]].append(
[list(map(lambda x: int('0' + x), value.split('/'))) for value in values[1:]])
return obj_mesh
#保存模型
def save_objpoint(new_model_savepath, obj_mesh):
with open(new_model_savepath, 'w') as f:
for obj_key in obj_mesh:
if obj_key == 'v':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key]+values + ['\n']])
if obj_key == 'vt':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == 'vn':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == "f":
f.writelines([''.join(list(map(lambda x: (str(x) + "/"), value))).replace('0', '').strip('/')for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
# 计算模型中心点xyz
def core_point(points):
centroid = np.mean(points, axis=0)
return centroid
# 预处理矩阵
def get_Preprocessmatrix(centroid):
# centroid是模型中心点xyz坐标
# 中心位移到原点
to_origin_matrix = np.array([
[1, 0, 0, -centroid[0]],
[0, 1, 0, -centroid[1]],
[0, 0, 1, -centroid[2]],
[0, 0, 0, 1]
])
# 位置复原
form_origin_matrix = np.array([
[1, 0, 0, centroid[0]],
[0, 1, 0, centroid[1]],
[0, 0, 1, centroid[2]],
[0, 0, 0, 1]
])
return to_origin_matrix, form_origin_matrix
# 改变模型的空间位置
def transform_model(matrix, points):
# 增加point矩阵维度
ones_data = np.ones(points.shape[0])
points = np.insert(points, 3, values=ones_data, axis=1)
new_xyz_data = np.dot(matrix, points.T)
points = new_xyz_data[:3].T
return points
if __name__ == "__main__":
readModelpath = r"faceModel/face-s.obj"
save_model_to_origin_path = r"csdn/face-s-to-origin.obj"
save_model_form_origin_path = r"csdn/face-s-form-origin.obj"
obj_mesh = read_objPoint(readModelpath)
# 获得所有点坐标
points = np.array(obj_mesh["v"])
# 获得所有店的法向量
normalvector = np.array(obj_mesh["vn"])
# 计算模型中心点xyz
centroid = core_point(points)
to_origin_matrix, form_origin_matrix = get_Preprocessmatrix(centroid)
to_origin_points = transform_model(to_origin_matrix, points)
to_origin_normalvector = transform_model(to_origin_matrix, normalvector)
obj_mesh["v"] = to_origin_points.tolist()
obj_mesh["vn"] = to_origin_normalvector.tolist()
save_objpoint(save_model_to_origin_path, obj_mesh)
form_origin_points = transform_model(form_origin_matrix, to_origin_points)
form_origin_normalvector = transform_model(form_origin_matrix, to_origin_normalvector)
obj_mesh["v"] = form_origin_points.tolist()
obj_mesh["vn"] = form_origin_normalvector.tolist()
save_objpoint(save_model_form_origin_path, obj_mesh)
红框是原始模型,绿框是位移到原点的模型:
绿框是位移到原点的模型,黑框是复原后的模型:
def get_scalematrix(alpha):
# 缩放参数
scale = 1/alpha
# 缩放矩阵
scale_matrix = np.array([
[scale, 0, 0, 0],
[0, scale, 0, 0],
[0, 0, scale, 0],
[0, 0, 0, 1]
])
return scale_matrix
import numpy as np
#加载模型
def read_objPoint(model_path):
obj_mesh = {'v': [], 'vt': [], 'vn': [], 'f': []}
with open(model_path, 'r') as f:
for line in f.readlines():
values = line.strip().split()
if values == []:
continue
if values[0] == 'v':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vt':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vn':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'f':
obj_mesh[values[0]].append(
[list(map(lambda x: int('0' + x), value.split('/'))) for value in values[1:]])
return obj_mesh
#保存模型
def save_objpoint(new_model_savepath, obj_mesh):
with open(new_model_savepath, 'w') as f:
for obj_key in obj_mesh:
if obj_key == 'v':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key]+values + ['\n']])
if obj_key == 'vt':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == 'vn':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == "f":
f.writelines([''.join(list(map(lambda x: (str(x) + "/"), value))).replace('0', '').strip('/')for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
# 计算模型中心点xyz
def core_point(points):
centroid = np.mean(points, axis=0)
return centroid
# 预处理矩阵
def get_Preprocessmatrix(centroid):
# centroid是模型中心点xyz坐标
# 中心位移到原点
to_origin_matrix = np.array([
[1, 0, 0, -centroid[0]],
[0, 1, 0, -centroid[1]],
[0, 0, 1, -centroid[2]],
[0, 0, 0, 1]
])
# 位置复原
form_origin_matrix = np.array([
[1, 0, 0, centroid[0]],
[0, 1, 0, centroid[1]],
[0, 0, 1, centroid[2]],
[0, 0, 0, 1]
])
return to_origin_matrix, form_origin_matrix
def get_scalematrix(alpha):
# 缩放参数
scale = 1/alpha
# 缩放矩阵
scale_matrix = np.array([
[scale, 0, 0, 0],
[0, scale, 0, 0],
[0, 0, scale, 0],
[0, 0, 0, 1]
])
return scale_matrix
# 改变模型的空间位置
def transform_model(matrix, points):
# 增加point矩阵维度
ones_data = np.ones(points.shape[0])
points = np.insert(points, 3, values=ones_data, axis=1)
new_xyz_data = np.dot(matrix, points.T)
points = new_xyz_data[:3].T
return points
if __name__ == "__main__":
readModelpath = r"faceModel/face-s.obj"
save_model_path = r"csdn/face-s-scale.obj"
# 缩放因子
alpha = 10
obj_mesh = read_objPoint(readModelpath)
# 获得所有点坐标
points = np.array(obj_mesh["v"])
# 获得所有店的法向量
normalvector = np.array(obj_mesh["vn"])
# 计算模型中心点xyz
centroid = core_point(points)
to_origin_matrix, form_origin_matrix = get_Preprocessmatrix(centroid)
scale_matrix = get_scalematrix(alpha)
# 移到原点-->缩放-->复原
change_matrix = form_origin_matrix.dot(scale_matrix).dot(to_origin_matrix)
scale_points = transform_model(change_matrix, points)
scale_normalvector = transform_model(change_matrix, normalvector)
obj_mesh["v"] = scale_points.tolist()
obj_mesh["vn"] = scale_normalvector.tolist()
save_objpoint(save_model_path, obj_mesh)
def get_changematrix(x_tra, y_tra, z_tra):
# 偏移参数
x_translation = x_tra
y_translation = y_tra
z_translation = z_tra
# 平移矩阵
translation_matrix = np.array([
[1, 0, 0, -x_translation],
[0, 1, 0, -y_translation],
[0, 0, 1, -z_translation],
[0, 0, 0, 1]
])
return translation_matrix
import numpy as np
#加载模型
def read_objPoint(model_path):
obj_mesh = {'v': [], 'vt': [], 'vn': [], 'f': []}
with open(model_path, 'r') as f:
for line in f.readlines():
values = line.strip().split()
if values == []:
continue
if values[0] == 'v':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vt':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vn':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'f':
obj_mesh[values[0]].append(
[list(map(lambda x: int('0' + x), value.split('/'))) for value in values[1:]])
return obj_mesh
#保存模型
def save_objpoint(new_model_savepath, obj_mesh):
with open(new_model_savepath, 'w') as f:
for obj_key in obj_mesh:
if obj_key == 'v':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key]+values + ['\n']])
if obj_key == 'vt':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == 'vn':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == "f":
f.writelines([''.join(list(map(lambda x: (str(x) + "/"), value))).replace('0', '').strip('/')for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
# 计算模型中心点xyz
def core_point(points):
centroid = np.mean(points, axis=0)
return centroid
# 预处理矩阵
def get_Preprocessmatrix(centroid):
# centroid是模型中心点xyz坐标
# 中心位移到原点
to_origin_matrix = np.array([
[1, 0, 0, -centroid[0]],
[0, 1, 0, -centroid[1]],
[0, 0, 1, -centroid[2]],
[0, 0, 0, 1]
])
# 位置复原
form_origin_matrix = np.array([
[1, 0, 0, centroid[0]],
[0, 1, 0, centroid[1]],
[0, 0, 1, centroid[2]],
[0, 0, 0, 1]
])
return to_origin_matrix, form_origin_matrix
def get_translationmatrix(x_tra, y_tra, z_tra):
# 偏移参数
x_translation = x_tra
y_translation = y_tra
z_translation = z_tra
# 平移矩阵
translation_matrix = np.array([
[1, 0, 0, -x_translation],
[0, 1, 0, -y_translation],
[0, 0, 1, -z_translation],
[0, 0, 0, 1]
])
return translation_matrix
# 改变模型的空间位置
def transform_model(matrix, points):
# 增加point矩阵维度
ones_data = np.ones(points.shape[0])
points = np.insert(points, 3, values=ones_data, axis=1)
new_xyz_data = np.dot(matrix, points.T)
points = new_xyz_data[:3].T
return points
if __name__ == "__main__":
readModelpath = r"faceModel/face-s.obj"
save_model_to_origin_path = r"csdn/face-s-translation.obj"
x_tra, y_tra, z_tra =800,700,600
obj_mesh = read_objPoint(readModelpath)
# 获得所有点坐标
points = np.array(obj_mesh["v"])
# 获得所有店的法向量
normalvector = np.array(obj_mesh["vn"])
# 计算模型中心点xyz
centroid = core_point(points)
to_origin_matrix, form_origin_matrix = get_Preprocessmatrix(centroid)
translation_matrix = get_translationmatrix(x_tra, y_tra, z_tra)
# 移到原点-->平移-->复原
change_matrix = form_origin_matrix.dot(translation_matrix).dot(to_origin_matrix)
translation_points = transform_model(change_matrix, points)
translation_normalvector = transform_model(change_matrix, normalvector)
obj_mesh["v"] = translation_points.tolist()
obj_mesh["vn"] = translation_normalvector.tolist()
save_objpoint(save_model_to_origin_path, obj_mesh)
def get_roatematrix(x_r, y_r, z_r):
# 旋转参数
x_roate = x_r
y_roate = y_r
z_roate = z_r
# 旋转矩阵
x_roate_matrix = np.array([
[1, 0, 0, 0],
[0, np.cos(x_roate), -np.sin(x_roate), 0],
[0, np.sin(x_roate), np.cos(x_roate), 0],
[0, 0, 0, 1]
])
y_roate_matrix = np.array([
[np.cos(y_roate), 0, np.sin(y_roate), 0],
[0, 1, 0, 0],
[-np.sin(y_roate), 0, np.cos(y_roate), 0],
[0, 0, 0, 1]
])
z_roate_matrix = np.array([
[np.cos(z_roate), -np.sin(z_roate), 0, 0],
[np.sin(z_roate), np.cos(z_roate), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
roate_matrix = z_roate_matrix.dot(y_roate_matrix).dot(x_roate_matrix)
return roate_matrix
import numpy as np
#加载模型
def read_objPoint(model_path):
obj_mesh = {'v': [], 'vt': [], 'vn': [], 'f': []}
with open(model_path, 'r') as f:
for line in f.readlines():
values = line.strip().split()
if values == []:
continue
if values[0] == 'v':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vt':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vn':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'f':
obj_mesh[values[0]].append(
[list(map(lambda x: int('0' + x), value.split('/'))) for value in values[1:]])
return obj_mesh
#保存模型
def save_objpoint(new_model_savepath, obj_mesh):
with open(new_model_savepath, 'w') as f:
for obj_key in obj_mesh:
if obj_key == 'v':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key]+values + ['\n']])
if obj_key == 'vt':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == 'vn':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == "f":
f.writelines([''.join(list(map(lambda x: (str(x) + "/"), value))).replace('0', '').strip('/')for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
# 计算模型中心点xyz
def core_point(points):
centroid = np.mean(points, axis=0)
return centroid
# 预处理矩阵
def get_Preprocessmatrix(centroid):
# centroid是模型中心点xyz坐标
# 中心位移到原点
to_origin_matrix = np.array([
[1, 0, 0, -centroid[0]],
[0, 1, 0, -centroid[1]],
[0, 0, 1, -centroid[2]],
[0, 0, 0, 1]
])
# 位置复原
form_origin_matrix = np.array([
[1, 0, 0, centroid[0]],
[0, 1, 0, centroid[1]],
[0, 0, 1, centroid[2]],
[0, 0, 0, 1]
])
return to_origin_matrix, form_origin_matrix
def get_roatematrix(x_r, y_r, z_r):
# 旋转参数
x_roate = x_r
y_roate = y_r
z_roate = z_r
# 旋转矩阵
x_roate_matrix = np.array([
[1, 0, 0, 0],
[0, np.cos(x_roate), -np.sin(x_roate), 0],
[0, np.sin(x_roate), np.cos(x_roate), 0],
[0, 0, 0, 1]
])
y_roate_matrix = np.array([
[np.cos(y_roate), 0, np.sin(y_roate), 0],
[0, 1, 0, 0],
[-np.sin(y_roate), 0, np.cos(y_roate), 0],
[0, 0, 0, 1]
])
z_roate_matrix = np.array([
[np.cos(z_roate), -np.sin(z_roate), 0, 0],
[np.sin(z_roate), np.cos(z_roate), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
roate_matrix = z_roate_matrix.dot(y_roate_matrix).dot(x_roate_matrix)
return roate_matrix
# 改变模型的空间位置
def transform_model(matrix, points):
# 增加point矩阵维度
ones_data = np.ones(points.shape[0])
points = np.insert(points, 3, values=ones_data, axis=1)
new_xyz_data = np.dot(matrix, points.T)
points = new_xyz_data[:3].T
return points
if __name__ == "__main__":
readModelpath = r"faceModel/face-s.obj"
save_model_to_origin_path = r"csdn/face-s-roate.obj"
# 旋转角度 弧度制
x_r, y_r, z_r = -1, 1, 2
obj_mesh = read_objPoint(readModelpath)
# 获得所有点坐标
points = np.array(obj_mesh["v"])
# 获得所有店的法向量
normalvector = np.array(obj_mesh["vn"])
# 计算模型中心点xyz
centroid = core_point(points)
to_origin_matrix, form_origin_matrix = get_Preprocessmatrix(centroid)
roate_matrix = get_roatematrix(x_r, y_r, z_r)
# 移到原点-->旋转-->复原
change_matrix = form_origin_matrix.dot(roate_matrix).dot(to_origin_matrix)
roate_points = transform_model(change_matrix, points)
roate_normalvector = transform_model(change_matrix, normalvector)
obj_mesh["v"] = roate_points.tolist()
obj_mesh["vn"] = roate_normalvector.tolist()
save_objpoint(save_model_to_origin_path, obj_mesh)
import numpy as np
#加载模型
def read_objPoint(model_path):
obj_mesh = {'v': [], 'vt': [], 'vn': [], 'f': []}
with open(model_path, 'r') as f:
for line in f.readlines():
values = line.strip().split()
if values == []:
continue
if values[0] == 'v':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vt':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'vn':
obj_mesh[values[0]].append(list(map(float, values[1:])))
if values[0] == 'f':
obj_mesh[values[0]].append(
[list(map(lambda x: int('0' + x), value.split('/'))) for value in values[1:]])
return obj_mesh
#保存模型
def save_objpoint(new_model_savepath, obj_mesh):
with open(new_model_savepath, 'w') as f:
for obj_key in obj_mesh:
if obj_key == 'v':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key]+values + ['\n']])
if obj_key == 'vt':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == 'vn':
f.writelines([str(value) + ' ' for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
if obj_key == "f":
f.writelines([''.join(list(map(lambda x: (str(x) + "/"), value))).replace('0', '').strip('/')for values in obj_mesh[obj_key] for value in [obj_key] + values + ['\n']])
# 计算模型中心点xyz
def core_point(points):
centroid = np.mean(points, axis=0)
return centroid
# 预处理矩阵
def get_Preprocessmatrix(centroid):
# centroid是模型中心点xyz坐标
# 中心位移到原点
to_origin_matrix = np.array([
[1, 0, 0, -centroid[0]],
[0, 1, 0, -centroid[1]],
[0, 0, 1, -centroid[2]],
[0, 0, 0, 1]
])
# 位置复原
form_origin_matrix = np.array([
[1, 0, 0, centroid[0]],
[0, 1, 0, centroid[1]],
[0, 0, 1, centroid[2]],
[0, 0, 0, 1]
])
return to_origin_matrix, form_origin_matrix
def get_changematrix(x_translation, y_translation, z_translation, roate_x, roate_y, roate_z, scale):
# 旋转矩阵
roate_x_matrix = np.array([
[1, 0, 0, 0],
[0, np.cos(roate_x), -np.sin(roate_x), 0],
[0, np.sin(roate_x), np.cos(roate_x), 0],
[0, 0, 0, 1]
])
roate_y_matrix = np.array([
[np.cos(roate_y), 0, np.sin(roate_y), 0],
[0, 1, 0, 0],
[-np.sin(roate_y), 0, np.cos(roate_y), 0],
[0, 0, 0, 1]
])
roate_z_matrix = np.array([
[np.cos(roate_z), -np.sin(roate_z), 0, 0],
[np.sin(roate_z), np.cos(roate_z), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]
])
# 平移矩阵
translation_matrix = np.array([
[1, 0, 0, -x_translation],
[0, 1, 0, -y_translation],
[0, 0, 1, -z_translation],
[0, 0, 0, 1]
])
# 缩放矩阵
scale_matrix = np.array([
[scale, 0, 0, 0],
[0, scale, 0, 0],
[0, 0, scale, 0],
[0, 0, 0, 1]
])
change_matrix =scale_matrix.dot(roate_z_matrix).dot(roate_y_matrix).dot(roate_x_matrix).dot(translation_matrix)
return change_matrix
# 改变模型的空间位置
def transform_model(matrix, points):
# 增加point矩阵维度
ones_data = np.ones(points.shape[0])
points = np.insert(points, 3, values=ones_data, axis=1)
new_xyz_data = np.dot(matrix, points.T)
points = new_xyz_data[:3].T
return points
if __name__ == "__main__":
readModelpath = r"faceModel/face-s.obj"
save_model_to_origin_path = r"csdn/face-s-change.obj"
x_r, y_r, z_r = -1, 1, 2
x_tra, y_tra, z_tra = 200,300,200
scale = 5
obj_mesh = read_objPoint(readModelpath)
# 获得所有点坐标
points = np.array(obj_mesh["v"])
# 获得所有店的法向量
normalvector = np.array(obj_mesh["vn"])
# 计算模型中心点xyz
centroid = core_point(points)
to_origin_matrix, form_origin_matrix = get_Preprocessmatrix(centroid)
change_matrix = get_changematrix(x_tra, y_tra, z_tra, x_r, y_r, z_r,scale)
# 移到原点-->转换-->复原
change_matrix = form_origin_matrix.dot(change_matrix).dot(to_origin_matrix)
change_points = transform_model(change_matrix, points)
change_normalvector = transform_model(change_matrix, normalvector)
obj_mesh["v"] = change_points.tolist()
obj_mesh["vn"] = change_normalvector.tolist()
save_objpoint(save_model_to_origin_path, obj_mesh)
CSDN大部分博文关于obj的基本操作都比较简单粗糙,所以自己写了版比较简洁的代码方便自己复习以及提供大家参考。