#!/usr/bin/python # obj.py: upload a wavefront .obj to the server import verse as v import string import sys # polygon layer is second layer, but is this ok? FACE_LAYER = 1 geom_node_id = -1 avatar = -1 vlist = [] uvlist = [] flist = [] vertices_received = 0 faces_received = 0 uvs_received = 0 link_set = 0 faces_sent = 0 face_layer_created = 0 # small utility function def isspace(character): return character in string.whitespace # wavefront .obj file reader def read_obj_file(filename): f = file(filename, "r") vlist = [] uvlist = [] flist = [] lines = f.readlines() for line in lines: # ignore comment or empty line if line[0] == "#" or line[0] == "\n": pass # add vertex elif line[0] == "v" and isspace(line[1]): co = line.split() vlist.append((float(co[1]), float(co[2]), float(co[3]))) # add uv coord elif line[0:2] == "vt" and isspace(line[2]): uvco = line.split() uvlist.append((float(uvco[1]), float(uvco[2]))) # add face elif line[0] == "f" and isspace(line[1]): fdata = line.split() del fdata[0] if len(fdata) >= 3: f = [] for vert in fdata: ids = vert.split("/") # .obj id's start at 1 v_id = int(ids[0]) - 1 if len(ids) >= 2: uv_id = int(ids[1]) - 1 else: uv_id = -1 f.append((v_id, uv_id)) flist.append(f) return vlist, uvlist, flist # send verts to server def send_verts(node_id, layer_id): global vlist id = 0 for vert in vlist: x, y, z = vert[0], vert[1], vert[2] v.send_g_vertex_set_xyz_real32(node_id, layer_id, id, x, y, z) if id % 20 == 0: v.callback_update(10000) id = id + 1 # send faces to server (ngons are simply ignored) def send_faces(node_id, layer_id): global flist, faces_sent if faces_sent: return faces_sent = 1 id = 0 for f in flist: v1 = f[0][0] v2 = f[1][0] v3 = f[2][0] if len(f) > 3: v4 = f[3][0] else: v4 = -1 v.send_g_polygon_set_corner_uint32(node_id, layer_id, id, v1, v2, v3, v4) if id % 20 == 0: v.callback_update(10000) id = id + 1 # send uv's to server (index = 0 -> u, index = 1 -> v) def send_uv(node_id, layer_id, index): global flist, uvlist pid = 0 for f in flist: id = f[0][1] if id < len(uvlist): v1 = uvlist[id][index] else: v1 = 0 id = f[1][1] if id < len(uvlist): v2 = uvlist[id][index] else: v2 = 0 id = f[2][1] if id < len(uvlist): v3 = uvlist[id][index] else: v3 = 0 if len(f) > 3: id = f[3][1] if id < len(uvlist): v4 = uvlist[id][index] else: v4 = 0 else: v4 = 0 v.send_g_polygon_set_corner_real32(node_id, layer_id, pid, v1, v2, v3, v4) if pid % 20 == 0: v.callback_update(10000) pid = pid + 1 def cb_connect_accept(v_avatar, address, host_id): global avatar avatar = v_avatar v.send_node_create(-1, v.GEOMETRY, v.OWNER_MINE) v.send_node_index_subscribe((1 << v.GEOMETRY)|(1 << v.OBJECT)) def cb_node_create(node_id, type, owner): global geom_node_id, link_set if owner == v.OWNER_MINE and type == v.GEOMETRY: print "creating layer" v.send_g_layer_create(node_id, 2, "map_u", v.G_LAYER_POLYGON_CORNER_REAL, 0, 0) v.send_g_layer_create(node_id, 3, "map_v", v.G_LAYER_POLYGON_CORNER_REAL, 0, 0) v.send_node_subscribe(node_id) geom_node_id = node_id v.send_node_create(-1, v.OBJECT, v.OWNER_MINE) elif owner == v.OWNER_MINE and type == v.OBJECT: v.send_o_link_set(node_id, -1, geom_node_id, "geometry", 0) link_set = 1 def cb_g_layer_create(node_id, layer_id, name, type, def_uint, def_real): global vlist, vertices_received, face_layer_created print "layer created: " + name if layer_id == v.G_LAYER_VERTEX_XYZ: send_verts(node_id, layer_id) v.send_g_layer_subscribe(node_id, layer_id, v.FORMAT_REAL32) elif layer_id == FACE_LAYER: face_layer_created = 1 v.send_g_layer_subscribe(node_id, layer_id, v.FORMAT_REAL32) send_faces(node_id, layer_id) elif type == v.G_LAYER_POLYGON_CORNER_REAL: if name == "map_u": v.send_g_layer_subscribe(node_id, layer_id, v.FORMAT_REAL32) send_uv(node_id, layer_id, 0) elif name == "map_v": v.send_g_layer_subscribe(node_id, layer_id, v.FORMAT_REAL32) send_uv(node_id, layer_id, 1) def cb_g_vertex_set(node_id, layer_id, vertex_id, x, y, z): global vertices_received, face_layer_created, vlist vertices_received = vertices_received + 1 #print "%d/%d" % (vertices_received, len(vlist)) def cb_g_polygon_set(node_id, layer_id, polygon_id, v0, v1, v2, v3): global faces_received, flist faces_received = faces_received + 1 #print "%d/%d" % (faces_received, len(flist)) def cb_g_polygon_set_real(node_id, layer_id, polygon_id, v0, v1, v2, v3): global uvs_received uvs_received = uvs_received + 1 #print "%d/%d" % (uvs_received, len(flist)*2) def main(): global avatar, vlist, uvlist, flist global faces_received, vertices_received, uvs_received if len(sys.argv) > 1: filename = sys.argv[1] else: filename = "data/cube.obj" vlist, uvlist, flist = read_obj_file(filename) v.callback_set(v.SEND_CONNECT_ACCEPT, cb_connect_accept) v.callback_set(v.SEND_NODE_CREATE, cb_node_create) v.callback_set(v.SEND_G_LAYER_CREATE, cb_g_layer_create) v.callback_set(v.SEND_G_VERTEX_SET_REAL32_XYZ, cb_g_vertex_set) v.callback_set(v.SEND_G_POLYGON_SET_CORNER_UINT32, cb_g_polygon_set) v.callback_set(v.SEND_G_POLYGON_SET_CORNER_REAL32, cb_g_polygon_set_real) # connect and make active session session = v.send_connect("uname", "pass", "localhost", 0) v.session_set(session) i = 0 while i < 10000: v.callback_update(10000) if (len(flist)*2) <= uvs_received: # two layers: map_u, map_v if len(flist) <= faces_received: if len(vlist) <= vertices_received and link_set: print "\rSending complete and confirmed. ", break print "\rv " + str(vertices_received) + "/" + str(len(vlist)), print "f " + str(faces_received) + "/" + str(len(flist)), print "uv " + str(uvs_received) + "/" + str(len(flist)*2), i = i + 1 print "" v.send_connect_terminate("", "adios!") v.callback_update(10000) v.callback_update(10000) main()