If someone deals with a similar problem it might help seeing my (messy) code for this:

```
def plottosided(f,color):
P = implicit_plot3d(f(x,y,z),(x,-1.5,1.5),(y,-1.5,1.5),(z,-1.5,1.5),plot_points=20,frame=False,viewer='tachyon')
opts = P._process_viewing_options({})
T = P._prepare_for_tachyon(opts['frame'],opts['axes'], opts['frame_aspect_ratio'],opts['aspect_ratio'],opts['zoom'])
R=newtriangle(f,T.tachyon(),0.001)
R=R.replace('resolution 400 400','resolution 500 500')
print('Converting complete')
tachyon_rt(R)
def tovector(A):
B=[]
for a in A:
if a!='':
B += [float(a)]
return vector(B)
def tostring(v):
s=''
for i in v:
s+= str(i)+' '
return s
def newtriangle(f,S,C): #f defining implicit function, S the tachyon string, C the second rgb color
Colorstring = str(color[0])+' '+str(color[1])+' '+str(color[2])
Triangles = S.split('TRI')
Pre = Triangles[0]
App = Triangles[len(Triangles)-1]
Triangles=Triangles[1:len(Triangles)-1]
newtexture=' Texdef texture89\n Ambient 0.230769230769 Diffuse 0.769230769231 Specular 0.0 Opacity 1\n Color '+Colorstring+'\n TexFunc 0\n\n'
Ret=Pre + newtexture
count = 1
max = len(Triangles)
step= floor(max/10)+1
for Triangle in Triangles:
if (count%step==0):
print (count/step).str() + '0%'
Triangle2 = normalshifted(f,Triangle,-0.001)
Ret += 'TRI'+Triangle + 'TRI' + Triangle2
count += 1
Ret += 'TRI' +App
return Ret
def normalshifted(f,T,shift): #f defining function, T TriangleString
V0=tovector(T[T.find('V0')+2:T.find('V1')].split(' '))
V1=tovector(T[T.find('V1')+2:T.find('V2')].split(' '))
V2=tovector(T[T.find('V2')+2:T.find('\n')].split(' '))
Suf=T[T.find('\n'):]
#normal = ((V2-V0).cross_product(V1-V0)).normalize()
SP=1/3*(V0+V1+V2)
normal=vector(f.gradient()(SP[0],SP[1],SP[2])).n()
V0=shift*normal+V0
V1=shift*normal+V1
V2=shift*normal+V2
String = ' V0 ' +tostring(V0)+'V1 '+tostring(V1)+'V2 '+tostring(V2)+'\ntexture89\n'
return String
```

And a Test with a simple sphere:

```
f(x,y,z)=x^2+y^2+z^2-3
color=(0.9, 0.2, 1.0)
plottosided(f,color)
```