from __future__ import print_function import numpy as np class Obj: def __init__(self, fn): self.ind_v = 0 self.ind_vt = 0 self.ind_vn = 0 self.fn = fn self.out = open(fn + ".tmp", "w") self.out.write("mtllib dinnerware.mtl\n") def __del__(self): self.out.close() import shutil shutil.move(self.fn + ".tmp", self.fn) def push_v(self, v): self.out.write("v %f %f %f\n" % (v[0],v[1],v[2])) self.ind_v += 1 return self.ind_v def push_vt(self, vt): self.out.write("vt %f %f\n" % (vt[0],vt[1])) self.ind_vt += 1 return self.ind_vt def push_vn(self, vn): vn /= np.linalg.norm(vn) self.out.write("vn %f %f %f\n" % (vn[0],vn[1],vn[2])) self.ind_vn += 1 return self.ind_vn def convex_hull(points, vind, nind, tind, obj): "super ineffective" cnt = len(points) for a in range(cnt): for b in range(a+1,cnt): for c in range(b+1,cnt): vec1 = points[a] - points[b] vec2 = points[a] - points[c] n = np.cross(vec1, vec2) n /= np.linalg.norm(n) C = np.dot(n, points[a]) inner = np.inner(n, points) pos = (inner <= C+0.0001).all() neg = (inner >= C-0.0001).all() if not pos and not neg: continue obj.out.write("f %i//%i %i//%i %i//%i\n" % ( (vind[a], nind[a], vind[b], nind[b], vind[c], nind[c]) if (inner - C).sum() < 0 else (vind[a], nind[a], vind[c], nind[c], vind[b], nind[b]) ) ) #obj.out.write("f %i/%i/%i %i/%i/%i %i/%i/%i\n" % ( # (vind[a], tind[a], nind[a], vind[b], tind[b], nind[b], vind[c], tind[c], nind[c]) # if (inner - C).sum() < 0 else # (vind[a], tind[a], nind[a], vind[c], tind[c], nind[c], vind[b], tind[b], nind[b]) ) ) def test_convex_hull(): obj = Obj("convex_test.obj") vlist = np.random.uniform( low=-0.1, high=+0.1, size=(100,3) ) nlist = vlist.copy() tlist = np.random.uniform( low=0, high=+1, size=(100,2) ) vind = [obj.push_v(xyz) for xyz in vlist] nind = [obj.push_vn(xyz) for xyz in nlist] tind = [obj.push_vt(uv) for uv in tlist] convex_hull(vlist, vind, nind, tind, obj) class Contour: def __init__(self): self.vprev_vind = None def f(self, obj, vlist_vind, vlist_tind, vlist_nind): cnt = len(vlist_vind) for i1 in range(cnt): i2 = i1-1 obj.out.write("f %i/%i/%i %i/%i/%i %i/%i/%i\n" % ( vlist_vind[i2], vlist_tind[i2], vlist_nind[i2], vlist_vind[i1], vlist_tind[i1], vlist_nind[i1], self.vprev_vind[i1], self.vprev_tind[i1], self.vprev_nind[i1], ) ) obj.out.write("f %i/%i/%i %i/%i/%i %i/%i/%i\n" % ( vlist_vind[i2], vlist_tind[i2], vlist_nind[i2], self.vprev_vind[i1], self.vprev_tind[i1], self.vprev_nind[i1], self.vprev_vind[i2], self.vprev_tind[i2], self.vprev_nind[i2], ) ) def belt(self, obj, vlist, nlist, tlist): vlist_vind = [obj.push_v(xyz) for xyz in vlist] vlist_tind = [obj.push_vt(xyz) for xyz in tlist] vlist_nind = [obj.push_vn(xyz) for xyz in nlist] if self.vprev_vind: self.f(obj, vlist_vind, vlist_tind, vlist_nind) else: self.first_vind = vlist_vind self.first_tind = vlist_tind self.first_nind = vlist_nind self.vprev_vind = vlist_vind self.vprev_tind = vlist_tind self.vprev_nind = vlist_nind def finish(self, obj): self.f(obj, self.first_vind, self.first_tind, self.first_nind) def test_contour(): RAD1 = 2.0 RAD2 = 1.5 obj = Obj("torus.obj") obj.out.write("usemtl porcelain\n") contour = Contour() for step in range(100): angle = step/100.0*2*np.pi belt_v = [] belt_n = [] belt_t = [] for b in range(50): beta = b/50.0*2*np.pi r = RAD2*np.cos(beta) + RAD1 z = RAD2*np.sin(beta) belt_v.append( np.array( [ np.cos(angle)*r, np.sin(angle)*r, z] ) ) belt_n.append( np.array( [ np.cos(angle)*np.cos(beta), np.sin(angle)*np.cos(beta), np.sin(beta)] ) ) belt_t.append( (0,0) ) contour.belt(obj, belt_v, belt_n, belt_t) contour.finish(obj) #test_convex_hull() #test_contour() class RotationFigureParams: pass def generate_plate(p, obj, collision_prefix): contour = Contour() belt_vlist_3d_prev = None for step in range(p.N_VIZ+1): angle = step/float(p.N_VIZ)*2*np.pi if step % p.COLLISION_EVERY == 0: vlist_3d = [] for x,y in p.belt_simple: vlist_3d.append( [ np.cos(angle)*x*1.06, np.sin(angle)*x*1.06, y ] ) if belt_vlist_3d_prev: obj2 = Obj(collision_prefix % (step / p.COLLISION_EVERY)) obj2.out.write("usemtl pan_tefal\n") vlist = np.array( vlist_3d + belt_vlist_3d_prev ) vlist[len(vlist_3d):] *= 1.01 # break points on one plane vlist[0,0:2] += 0.01*vlist[len(vlist_3d),0:2] vlist[len(vlist_3d),0:2] += 0.01*vlist[0,0:2] nlist = np.random.uniform( low=-1, high=+1, size=vlist.shape ) tlist = np.random.uniform( low=0, high=+1, size=(len(vlist),2) ) vind = [obj2.push_v(xyz) for xyz in vlist] nind = [obj2.push_vn(xyz) for xyz in nlist] convex_hull(vlist, vind, nind, None, obj2) belt_vlist_3d_prev = vlist_3d if step==p.N_VIZ: break belt_v = [] belt_n = [] belt_t = [] for x,y,nx,ny in p.belt: belt_v.append( np.array( [ np.cos(angle)*x, np.sin(angle)*x, y ] ) ) belt_n.append( np.array( [ np.cos(angle)*nx, np.sin(angle)*nx, ny ] ) ) if ny-nx >= 0: belt_t.append( ( 127.0/512 + np.cos(angle)*x/p.RAD_HIGH*105/512, (512-135.0)/512 + np.sin(angle)*x/p.RAD_HIGH*105/512) ) else: belt_t.append( ( 382.0/512 + np.cos(angle)*x/p.RAD_HIGH*125/512, (512-380.0)/512 + np.sin(angle)*x/p.RAD_HIGH*125/512) ) contour.belt(obj, belt_v, belt_n, belt_t) contour.finish(obj) def tefal(): p = RotationFigureParams() p.RAD_LOW = 0.240/2 p.RAD_HIGH = 0.255/2 p.H = 0.075 p.THICK = 0.005 p.N_VIZ = 30 p.COLLISION_EVERY = 5 p.belt = [ (p.RAD_HIGH-p.THICK, p.H, -1,0), # x y norm (p.RAD_HIGH , p.H, 0,1), (p.RAD_HIGH+p.THICK, p.H, +1,0), (p.RAD_LOW+p.THICK, p.THICK, +1,0), (p.RAD_LOW , 0, 0,-1), ( 0, 0, 0,-1), ( 0, p.THICK, 0,1), (p.RAD_LOW-p.THICK, p.THICK, 0,1), (p.RAD_LOW-p.THICK, 3*p.THICK,-1,0), ] p.belt.reverse() p.belt_simple = [ (p.RAD_HIGH-p.THICK, p.H), (p.RAD_HIGH+p.THICK, p.H), (p.RAD_LOW , 0), (p.RAD_LOW-p.THICK , 0) ] obj = Obj("pan_tefal.obj") obj.out.write("usemtl pan_tefal\n") generate_plate(p, obj, "pan_tefal-collision%02i.obj") def plate(): p = RotationFigureParams() p.RAD_LOW = 0.110/2 p.RAD_HIGH = 0.190/2 p.H = 0.060 p.THICK = 0.003 p.N_VIZ = 30 p.COLLISION_EVERY = 5 p.belt = [ (p.RAD_HIGH-p.THICK, p.H, -0.9,0.5), # x y norm (p.RAD_HIGH , p.H, 0,1), (p.RAD_HIGH+p.THICK, p.H, +1,0), (p.RAD_LOW+p.THICK, p.THICK, +1,0), (p.RAD_LOW , 0, 0,-1), ( 0, 0, 0,-1), ( 0, p.THICK, 0,1), (p.RAD_LOW-3*p.THICK, p.THICK, 0,1), (p.RAD_LOW-p.THICK, 3*p.THICK,-0.5,1.0), ] p.belt.reverse() p.belt_simple = [ (p.RAD_HIGH-p.THICK, p.H), (p.RAD_HIGH+p.THICK, p.H), (p.RAD_LOW , 0), (p.RAD_LOW-p.THICK , 0) ] obj = Obj("plate.obj") obj.out.write("usemtl solid_color\n") generate_plate(p, obj, "plate-collision%02i.obj") plate()