-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathObjToRib2.py
189 lines (170 loc) · 6.46 KB
/
ObjToRib2.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/env python
#
# Version 0.1 - Copyright (c) 2019 by
#
# Info:
# This script will read in a.obj file, construct geometry from it
# and write out a .rib entity file of it. RIB Entity Files are incomplete
# as they do not contain enough information to render them. RIB Entity
# files need to be integrated or added to into "legal," or complete RIB files.
#
# Updates:
#
# License: MIT License
#
#
import getpass
import time, random
import sys
import argparse
import collections
import MaterialsTexts
obj_file = sys.argv[1]
def export_obj_to_rib(obj_file, material_id_list, decoration_id_list):
Round = 6
# open the file
ip = open(obj_file,'r')
#grab the data as lines
data = ip.readlines()
verts = []
norm = []
text = []
face = []
face_d = {}
group = 'no_group'
name = obj_file.split(".")
name = name[0]
if (material_id_list):
bxdf_mat = MaterialsTexts.material_ids_to_ri(material_id_list)
material_string = '_' + '_'.join(material_id_list)
name = name + material_string
material_rib = 'material' + material_string
if (decoration_id_list != False):
decoration_string = '_' + '_'.join(decoration_id_list)
name = name + decoration_string
material_rib = material_rib + decoration_string
bxdf_mat = MaterialsTexts.decoration_ids_to_ri(material_id_list, decoration_id_list)
# for each line check for one of our tokens
for line in data:
# we assume that our Tokens are always the first element of the line (which IIRC the rispec specifies)
# so we split each line and look at the first element
tokens=line.split()
# make sure we have a token to check against
if(len(tokens) > 0):
if(tokens[0] == 'g'):
#print "found group"
group = tokens[1]
# Reset face list in case new group is found, so data of the 'old' face group isn't spilled to the 'new' group.
face = []
elif(tokens[0] == 'v'):
#print "found vert"
# create a tuple of the vertex point values
#*****************************************************************
# NOTE RENDERMAN is left handed coordinate system, obj is right handed -> z-axis inverted
#
vert = [round(float(tokens[1]), Round),round(float(tokens[2]), Round), (-1) * round(float(tokens[3]), Round)]
# then add it to our list
verts += [vert]
elif(tokens[0] == 'vn'):
#print "found normal"
# create a tuple of the normal values
#*****************************************************************
# NOTE RENDERMAN is left handed coordinate system, obj is right handed -> z-axis inverted
#
normal = [round(float(tokens[1]), Round),round(float(tokens[2]), Round), (-1) * round(float(tokens[3]), Round)]
# then add it to our list
norm += [normal]
elif(tokens[0] == 'vt'):
#print "found texture"
# create a tuple of the texture values
#*****************************************************************
# NOTE RENDERMAN Maps Textures in the T from top to bottom so we
# calculate 1.0 - t here so the image will map properly
#
tx = [round(float(tokens[1]),Round),1-round(float(tokens[2]),Round)]
#
#*****************************************************************
# then add it to our list
text += [tx]
# now we have a face value
elif(tokens[0] == 'f'):
# add the face to the list and we will process it later (see below)
face += [line]
face_d[group] = face
# close the file
ip.close()
# now we've grabbed all the data we can process each of the faces and write out the rib
# Assume faces are group specific
nested_dict = lambda: collections.defaultdict(nested_dict)
obj_group = nested_dict()
for group in face_d.keys():
face = face_d[group]
i = 0
for f in face :
# create some empty data structures to be filled as we go
vertices = []
normals = []
points = []
tx = []
fd = f.split()
# the face is in the structure shown below Vert / TX / Norm we are gaurenteed to have a
# Vert but the others may not be there
#1/1/1 3/2/2 4/3/3 2/4/4
for perface in fd[1:] :
index=perface.split("/")
# get the point array index
pind=int(index[0])-1
points.append(round(float(verts[pind][0]),Round))
points.append(round(float(verts[pind][1]),Round))
points.append(round(float(verts[pind][2]),Round))
# check for textures and add if there
if(index[1] != "") :
tind=int(index[1])-1
tx.append(round(float(text[tind][0]),Round))
tx.append(round(float(text[tind][1]),Round))
# check for normals and check they are there
if(index[2] != "") :
nind=int(index[2])-1
normals.append(round(float(norm[nind][0]),Round))
normals.append(round(float(norm[nind][1]),Round))
normals.append(round(float(norm[nind][2]),Round))
normals_str = ' '.join(map(str, normals))
points_str = ' '.join(map(str, points))
obj_group[group][i]["P"] = points_str
# now see if we have any texture co-ordinates and add them to the dictionary if we do
if index[1] != "" :
tx_str = ' '.join(map(str, tx))
obj_group[group][i]["T"] = tx_str
else:
obj_group[group][i]["T"] = '' #just to ensure there is no dict error later
# check for normals and add them to the dictionary as well
if index[2] != "" :
obj_group[group][i]["N"] = normals_str
else:
obj_group[group][i]["N"] = '' #just to ensure no dict error later
i += 1
# Now the dict should have everything
op = open(name + '.rib', 'w')
#matrib = open(material_rib + '.rib', 'w')
op.write('##RenderMan RIB-Structure 1.1 Entity\n')
# Later this should cover obj. files with no groups also. Currently however the LXF
# (LIF) to OBJ exporter writes groups in any case, so we asume we have.
for group in obj_group.keys():
op.write('AttributeBegin #begin Brick ' + name + '.' + group + '\n')
op.write('Attribute "identifier" "uniform string name" ["Brick ' + name + '.' + group + '"]\n')
op.write(bxdf_mat[int(group)])
uv_num = 1
for f in obj_group[group].keys():
op.write('\tPolygon\n')
op.write('\t\t"P" [ ' + str(obj_group[group][f]["P"]) + ' ]\n')
# check for textures
if(str(obj_group[group][f]["T"]) != ''):
#op.write('\t\t"facevarying float [2] uv' + str(uv_num) + '" [ ' + str(obj_group[group][f]["T"]) + ' ]\n')
#uv_num += 1
op.write('\t\t"st" [ ' + str(obj_group[group][f]["T"]) + ' ]\n')
# check for normals
if(str(obj_group[group][f]["N"]) != ''):
op.write('\t\t"N" [ ' + str(obj_group[group][f]["N"]) + ' ]\n')
op.write('AttributeEnd #end Brick ' + name + '.' + group + '\n\n')
return name
#export_obj_to_rib(obj_file)