-
Notifications
You must be signed in to change notification settings - Fork 5
/
obj_writer.py
160 lines (119 loc) · 4.42 KB
/
obj_writer.py
1
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# ALERT: Amazing Luna Engine Research Tools
# This program is free software, and can be redistributed and/or modified by you. It is provided 'as-is', without any warranty.
# For more details, terms and conditions, see GNU General Public License.
# A copy of the that license should come with this program (LICENSE.txt). If not, see <http://www.gnu.org/licenses/>.
import dat1lib
import dat1lib.types.model
import dat1lib.types.sections.model.geo
import dat1lib.types.sections.model.look
import dat1lib.types.sections.model.meshes
import dat1lib.types.sections.model.unknowns
import dat1lib.utils as utils
import io
import server.mtl_writer
SECTION_INDEXES = dat1lib.types.sections.model.geo.IndexesSection.TAG
SECTION_VERTEXES = dat1lib.types.sections.model.geo.VertexesSection.TAG
SECTION_LOOK = dat1lib.types.sections.model.look.ModelLookSection.TAG
SECTION_MESHES = dat1lib.types.sections.model.meshes.MeshesSection.TAG
SECTION_BUILT = dat1lib.types.sections.model.unknowns.ModelBuiltSection.TAG
SECTION_MATERIALS = dat1lib.types.sections.model.unknowns.ModelMaterialSection.TAG
class ObjHelper(object):
def __init__(self):
self.cur_vertex_offset = 1
self.current_material = None
self.mesh_vertexes = 0
self.remembered_vertexes = []
self.meshes_count = 0
self.f = io.BytesIO(bytes())
self.uv_scale = 1.0/16384.0
#
def write(self, s):
self.f.write(s.encode('ascii'))
def start_mesh(self, mesh_name):
self.mesh_vertexes = 0
self.write("o {:02}_{}\n".format(self.meshes_count, mesh_name))
self.meshes_count += 1
def end_mesh(self):
self.cur_vertex_offset += self.mesh_vertexes
def write_vertex(self, v, uv):
def transform(x, y, z):
return (x, y, z)
x, y, z = v.x, v.y, v.z
x, y, z = transform(x, y, z)
self.write("v {} {} {}\n".format(x, y, z))
self.mesh_vertexes += 1
uu, vv = v.u * self.uv_scale, 1.0 - v.v * self.uv_scale
if uv is not None:
uu, vv = uv
uu = uu * self.uv_scale
vv = 1.0 - vv * self.uv_scale
self.write("vt {} {}\n".format(uu, vv))
def usemtl(self, mat):
if mat != self.current_material:
self.write("usemtl {}\n".format(mat))
self.current_material = mat
def write_poly(self, vs):
self.write("f {}/{} {}/{} {}/{}\n".format(
vs[2] + self.cur_vertex_offset, vs[2] + self.cur_vertex_offset,
vs[1] + self.cur_vertex_offset, vs[1] + self.cur_vertex_offset,
vs[0] + self.cur_vertex_offset, vs[0] + self.cur_vertex_offset
))
def get_output(self):
self.f.seek(0)
return self.f
#
def write_model(self, model, looks, lod):
mode = dat1lib.VERSION_RCRA
if not isinstance(model, dat1lib.types.model.ModelRcra):
mode = dat1lib.VERSION_MSMR
if mode != dat1lib.VERSION_RCRA: # TODO: test RCRA
s = None if model is None else model.dat1.get_section(SECTION_BUILT)
if s:
uv_scale = s.get_uv_scale()
#
s = model.dat1.get_section(SECTION_MESHES)
meshes = s.meshes
s = model.dat1.get_section(SECTION_VERTEXES)
vertexes = s.vertexes
s = model.dat1.get_section(SECTION_INDEXES)
indexes = s.values
uvs = model.dat1.get_section(0x16F3BA18) # SO UVs
materials_section = model.dat1.get_section(SECTION_MATERIALS)
looks_section = model.dat1.get_section(SECTION_LOOK)
def get_material_name(mesh):
mat = mesh.get_material()
return server.mtl_writer.get_material_name(mat, model.dat1, materials_section)
#
# pizza B3D0E63D7EA1F3E8
# body 878B7EEABDC354A2
meshes_to_display = set()
for look in looks:
look_lod = looks_section.looks[look].lods[lod]
meshes_to_display |= set(range(look_lod.start, look_lod.start + look_lod.count))
for i, mesh in enumerate(meshes):
if i not in meshes_to_display:
continue
matname = get_material_name(mesh)
self.start_mesh("mesh{:02}_{}".format(i, matname))
self.usemtl(matname)
for vi in range(mesh.vertexStart, mesh.vertexStart + mesh.vertexCount):
v = vertexes[vi]
uv = None if uvs is None else uvs.get_uv(vi)
self.write_vertex(v, uv)
#
relative_indexes = ((mesh.get_flags() & 0x10) == 0)
faces_count = mesh.indexCount // 3
for j in range(faces_count):
index_index = mesh.indexStart + j*3
a, b, c = indexes[index_index+2], indexes[index_index+1], indexes[index_index]
if relative_indexes:
a -= mesh.vertexStart
b -= mesh.vertexStart
c -= mesh.vertexStart
self.write_poly([a, b, c])
self.end_mesh()
###
def write(model, looks, lod):
helper = ObjHelper()
helper.write_model(model, looks, lod)
return helper.get_output()