├── colors64.png ├── README.md └── export_obj_w_colors.py /colors64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easyw/freecad2obj_w_materials/master/colors64.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # freecad2obj_w_materials 2 | 3 | FreeCAD Macro to export selected parts to obj with colors materials 4 | just put in the same folder the files: 5 | * export_obj_w_colors.py 6 | * colors64.png 7 | 8 | and run the macro 9 | 10 | 11 | first version derived from microelly2 freecad-export 12 | 13 | https://github.com/microelly2/freecad-export 14 | -------------------------------------------------------------------------------- /export_obj_w_colors.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #------------------------------------------------- 3 | #-- export selected parts to obj with colors materials from FreeCAD 4 | #-- 5 | #-- microelly 2015 - easyw 2016 6 | #-- 7 | #-- GNU Lesser General Public License (LGPL) 8 | #------------------------------------------------- 9 | 10 | import Draft 11 | import Mesh,MeshPart, Part 12 | from math import sin,cos,pi 13 | import random 14 | import sys, os 15 | from os.path import expanduser 16 | 17 | version="1.1.0" 18 | FreeCAD.Console.PrintMessage("version "+version+"\n") 19 | 20 | def removeObj(obj): 21 | print "remove ", obj.Name, " == ", obj.Label 22 | App.ActiveDocument.removeObject(obj.Name) 23 | ### 24 | 25 | def splitToFaces(sel): 26 | global gg 27 | result=[] 28 | for sx in sel: 29 | shape=sx.Shape 30 | s=App.ActiveDocument.addObject('Part::Feature','copy') 31 | s.Shape=shape 32 | App.ActiveDocument.ActiveObject.Label=sx.Label 33 | FreeCADGui.ActiveDocument.ActiveObject.DiffuseColor=sx.ViewObject.DiffuseColor 34 | ll=Draft.downgrade(s,delete=False) 35 | faces=ll[0] 36 | n=0 37 | multi= len(s.ViewObject.DiffuseColor)<>1 38 | for f in faces: 39 | gg.addObject(f) 40 | print f.ViewObject 41 | if multi: 42 | f.ViewObject.DiffuseColor=s.ViewObject.DiffuseColor[n] 43 | else: 44 | f.ViewObject.DiffuseColor=s.ViewObject.DiffuseColor 45 | n += 1 46 | result.append(f) 47 | removeObj(s) 48 | FreeCAD.ActiveDocument.recompute() 49 | return result 50 | ### 51 | 52 | def color_value(r,g,b): 53 | mmin=min(r,g,b) 54 | mmax=max(r,g,b) 55 | mdiff=mmax-mmin 56 | if mmax==mmin: 57 | h=0 58 | elif mmax==r: 59 | h=2+(g-b)/mdiff 60 | elif mmax==g: 61 | h=4+(b-r)/mdiff 62 | elif mmax==b: 63 | h=(r-g)/mdiff 64 | else: 65 | raise Exception("color_calculation") 66 | h = h * pi/3 67 | return h 68 | ### 69 | 70 | def create_obj(sources): 71 | global gg 72 | 73 | obname = sources[0].Label 74 | targetname = "TTC" 75 | #out_path = expanduser("~") 76 | out_path=os.path.dirname(os.path.realpath(__file__))+os.sep 77 | #obname = "exp_obj_wmtl" 78 | 79 | gg=App.ActiveDocument.addObject("App::DocumentObjectGroup","Group") 80 | sources=splitToFaces(sources) 81 | 82 | f0=open(out_path+obname+".mtl",'wb') 83 | f0.write("\n\n\nnewmtl Material\n") 84 | f0.write("Ns 96.078431\n") 85 | f0.write("Ka 0.000000 0.000000 0.000000\n") 86 | f0.write("Kd 0.800000 0.80 0.80\n") 87 | f0.write("Ks 0.00000 0.0 0.0\n") 88 | f0.write("Ni 1.000000\n") 89 | f0.write("d 1.000000\n") 90 | f0.write("illum 2\n") 91 | f0.write("map_Kd colors64.png\n") 92 | f0.close() 93 | 94 | f1=open(out_path+obname+".obj",'wb') 95 | f1.write("# FreeCAD export colored OBJ File:\n") 96 | f1.write("mtllib "+obname+".mtl\n") 97 | #f1.write("mtllib "+obname+".mtl\n") 98 | #f1.write("mtllib colors64.mtl\n") 99 | f1.write("o "+obname+"\n") 100 | 101 | sloop=-1 102 | v_string="#v_string .\n" 103 | vt_string="#vt_string\n" 104 | f_string="#f_string\n" + "s off\n" + "usemtl Material" + "\n\n" 105 | 106 | z=0 107 | h=color_value(0,0,1.0) 108 | x=0.5+ 0.5*cos(h)*0.9 109 | y=0.5 + 0.5*sin(h)*0.9 110 | vt_string += "# " + str(z) + " miscolor " + "\n" 111 | # new color palette 112 | #vt_string += "vt 0.5 0.5\n" 113 | vt_string += "vt 0.5 0.3\n" 114 | v_ix=0 115 | f_ix=1 116 | for source in sources: 117 | sloop += 1 118 | __doc__=App.ActiveDocument 119 | __mesh__=__doc__.addObject("Mesh::Feature","Mesh") 120 | 121 | # net method - test maturity and quality #+# 122 | 123 | # mefisto 124 | #__mesh__.Mesh=MeshPart.meshFromShape(Shape=source.Shape,MaxLength=0.5) 125 | 126 | # standard 127 | __mesh__.Mesh=Mesh.Mesh(source.Shape.tessellate(0.1)) 128 | 129 | # netgen 130 | #__mesh__.Mesh=MeshPart.meshFromShape(Shape=source.Shape,Fineness=2,SecondOrder=0,Optimize=1,AllowQuad=0) 131 | 132 | __mesh__.ViewObject.CreaseAngle=25.0 133 | target=__doc__.addObject("Part::Feature",targetname) 134 | __shape__=Part.Shape() 135 | __shape__.makeShapeFromMesh(__mesh__.Mesh.Topology,0.100000) 136 | 137 | target.Shape=__shape__ 138 | target.purgeTouched() 139 | removeObj(__mesh__) 140 | 141 | del __shape__ 142 | del __doc__, __mesh__ 143 | 144 | s=target.Shape 145 | vc=0 146 | points=[] 147 | for vx in s.Vertexes: 148 | v=vx.Point 149 | v_string +="# sloop=" + str(sloop) + " vx=" + str(vc) + "\n" 150 | v_string += ''.join(["v ", str(v[0])," ",str(v[1])," ",str(v[2]),"\n"]) 151 | points.append(v) 152 | vc += 1 153 | fc=0 154 | 155 | pref=source.Shape.Faces 156 | flist={} 157 | fnlist={} 158 | fcolorlist={} 159 | dlist={} 160 | ez=0 161 | 162 | dlist=s.Faces 163 | 164 | sc=source.ViewObject.DiffuseColor[0] 165 | target.ViewObject.DiffuseColor=sc 166 | 167 | h=color_value(sc[0],sc[1],sc[2]) 168 | x=0.5+ 0.5*cos(h)*0.9 169 | y=0.5 + 0.5*sin(h)*0.9 170 | if 1 or False: 171 | # [r,g,b]=[100,100,100] 172 | FreeCAD.Console.PrintMessage(sc) 173 | [r,g,b,tt]=sc 174 | # print sc 175 | rr=int(r*15) 176 | r1=int(rr/4) 177 | r2=int(rr%4) 178 | # r1=0 179 | # r2=0 180 | g=(g*15) 181 | b=(b*15) 182 | # $r1*16+$g,$r2*16+$b,$t); 183 | FreeCAD.Console.PrintMessage("\n") 184 | FreeCAD.Console.PrintMessage([rr,b,g,r1,r2]) 185 | FreeCAD.Console.PrintMessage("\n") 186 | x=(0.0+ r1*16+g)/63 187 | y=1-(0.0+ r2*16+b)/63 188 | #[x,y]=[0.1,0.9] 189 | FreeCAD.Console.PrintMessage([x,y]) 190 | FreeCAD.Console.PrintMessage("\n") 191 | 192 | vt_string +="# " + str(z) + " " + str(sc) + "\n" 193 | #vt_string +="vt " +str(x) + " " + str(y) + "\n" 194 | vt_string +="vt " +str(x) + " " + str(y) + "\n" 195 | z += 1 196 | 197 | fc=0 198 | for e in s.Faces: 199 | try: 200 | f_string += ''.join(['f ',str(points.index(e.Vertexes[0].Point)+1 + v_ix), 201 | '/',str(fc+1 + f_ix),' ',str(points.index(e.Vertexes[1].Point)+1 + v_ix), 202 | '/',str(fc+1 + f_ix),' ',str(points.index(e.Vertexes[2].Point)+1 + v_ix),'/',str(fc+1 + f_ix),'\n']) 203 | except: 204 | print "Error ",fc 205 | pass 206 | v_ix += len(points) 207 | f_ix += 1 208 | vt_string += "\n# next part v_ix=" + str(v_ix) + " f_ix=" + str(f_ix) +"\n\n" 209 | f_string += "\n# next part v_ix=" + str(v_ix) + " f_ix=" + str(f_ix) +"\n\n" 210 | removeObj(target) 211 | 212 | f1.write(v_string) 213 | f1.write(vt_string) 214 | f1.write(f_string) 215 | f1.close() 216 | FreeCAD.Console.PrintMessage("generated "+out_path+obname+".obj\n") 217 | FreeCAD.Console.PrintMessage("generated "+out_path+obname+".mtl\n") 218 | FreeCAD.Console.PrintMessage("color png file "+out_path+"color64.png\n") 219 | ### 220 | 221 | sources = FreeCADGui.Selection.getSelection() 222 | if len(sources)>0: 223 | FreeCAD.Console.PrintMessage("running\n") 224 | create_obj(sources); 225 | else: 226 | FreeCAD.Console.PrintError("select at least one Part\n") 227 | 228 | 229 | --------------------------------------------------------------------------------