povray exporter- working alpha

Blender's renderer and external renderer export

Moderators: jesterKing, stiv

Post Reply
Posts: 0
Joined: Tue Feb 25, 2003 2:37 pm

povray exporter- working alpha

Post by ideasman »

Hi, heres my latest attempt at a povray exporter-
Its only just useable now but it has some nice features.
- Simple meshs export - Autosmoothing applied!!!! (big deal- thanks to whoever wrote the script)

-Lights export-

- Acrive camera is exported too but rotation setting is buggy, sombody please help?

most of the code is for the getRenderMesh(obj) function so scoot to the bottom for povray spesific stuff.


Code: Select all

from math import *
from Blender import *
# This gets a mesh that has had its verts transformed and autosmoothed.
def getRenderMesh(obj):
  # Apply Transform  #
  matrix = obj.getMatrix('worldspace')
  def apply_transform(vert):
    vertCopy = Mathutils.CopyVec(vert)
    return Mathutils.VecMultMat(vertCopy, matrix)
  #heres a new mesh to put the mesh from this object into.
  txmesh = NMesh.GetRawFromObject(obj.name)
  for v in txmesh.verts:
    vTx = apply_transform(v.co)
    v.co[0] = vTx[0]
    v.co[1] = vTx[1]
    v.co[2] = vTx[2]
  # Make all smooth, niot needed but nice.
  for f in txmesh.faces:
    f.smooth = 1
  obj = NMesh.PutRaw(txmesh)
  # +-------------------------------------------------------------+
  # | Copyright (c) 2001 Anthony C. D'Agostino                    |
  # | http://ourworld.compuserve.com/homepages/scorpius           |
  # | scorpius@compuserve.com                                     |
  # | March 27, 2001                                              |
  # +-------------------------------------------------------------+
  # | Backface Culling Script v0.2                                |
  # | Vector Functions                                            |
  # +-------------------------------------------------------------+
  # returns a vector [u+v]
  def vadd(u, v):
      return [u[0]+v[0], u[1]+v[1], u[2]+v[2]]
  # returns a vector from point v to point u [u-v]
  def vsub(u, v):
      return [u[0]-v[0], u[1]-v[1], u[2]-v[2]]
  # returns a vector [u*v] Cross Product
  def vcross(u, v):
      return [u[1]*v[2]-u[2]*v[1], u[2]*v[0]-u[0]*v[2], u[0]*v[1]-u[1]*v[0]]
  # returns a vector [u*scalar]
  def vmul(u, s):
      return [u[0]*s, u[1]*s, u[2]*s]
  # returns a vector of unit length (normalized)
  def vunit(u):
      return vmul(u, 1/vlen(u))
  # returns a real number (Dot Product)
  def vdot(u, v):
      return u[0]*v[0] + u[1]*v[1] + u[2]*v[2]
  # returns a real number (Vector Length)
  def vlen(u):
      return sqrt(u[0]**2 + u[1]**2 + u[2]**2)
  # Test functions
  if __name__ == "__main__":
      t = (sqrt(5)-1)/2
      a = [0, 1, t]
      b = [0, 1, -t]
      print 'a             :', a
      print 'b             :', b
      print 'vadd(a, b)    :', vadd(a, b)
      print 'vsub(a, b)    :', vsub(a, b)
      print 'vcross(a, b)  :', vcross(a, b)
      print 'vmul(b, 3)    :', vmul(b, 3)
      print 'vdot(a, b)    :', vdot(a, b)
      print 'vlen(a)       :', vlen(a)
      print 'vlen(b)       :', vlen(b)
      print 'vunit(a)      :', vunit(a)
      print 'vunit(b)      :', vunit(b)
      print 'vdot(ua, ub)  :', vdot(vunit(a), vunit(b))
      print 'vcross(ua, ub):', vcross(vunit(a), vunit(b)), vunit(vcross(a, b) )
      print 'Angle         :', acos(vdot(vunit(a), vunit(b)))*180/pi
  ##Two classes, 'MeshPlus' and 'FacePlus' allow storage of additional parameters not
  ## directly accessable through Blender's Python API. 
  ## v1 by Flippyneck, July 2003
  ## addition to give better normals for quads by z3r0_d may 2004
  ## (the method used to generate a normal from a quad is supposedly the one in blender's source)
  # import Blender
  # import vector   #vector.py by A.D'Agostino
  class MeshPlus:
    def __init__(self, original_mesh):
      self.original_mesh = original_mesh	#reference to blender obj
      self.faces = []				#list of faces
      self.verts = original_mesh.verts	#list of verts
      for f in original_mesh.faces:		#convert faces to FacePlus instances
        fp = FacePlus(f)
      self.edge_list = {}		#creates a list of edges and adjacent faces
      for f in self.faces:
        for e in f.edges:
          if self.edge_list.has_key(e):
            self.edge_list[e] = [f]
      for f in self.faces:			#write to neighbour faces list in each face
        for e in f.edges:
          n = self.edge_list[e]
          for m in n:
            if m == f:
  class FacePlus:
    def __init__(self, original_face):
      self.original_face = original_face
      self.v = original_face.v
      self.edges = self.GetEdges()		#list of vertex pairs that make face edges
      self.fnorm = self.GetFaceNormal()	#Face normal
      self.neighbours = []			#List of faces adjacent to this one
      self.centre = self.GetCentre()	        #geometric centre of face
    def GetCentre(self):
      x = y = z = 0
      for v in self.v:
        x = x + v.co[0]
        y = y + v.co[1]
        z = z + v.co[2]
      l = float(len(self.v))
      x = x / l
      y = y / l
      z = z / l
      return (x,y,z)
    def GetEdges(self):
      list = []
      if len(self.v) == 3:
        vertex1 = self.v[0]
        vertex2 = self.v[1]
        vertex3 = self.v[2]
        e1 = (vertex1, vertex2)
        e2 = (vertex2, vertex3)
        e3 = (vertex3, vertex1)
        for e in e1,e2,e3:
      elif len(self.v) == 4:
        vertex1 = self.v[0]
        vertex2 = self.v[1]
        vertex3 = self.v[2]
        vertex4 = self.v[3]
        e1 = (vertex1, vertex2)
        e2 = (vertex2, vertex3)
        e3 = (vertex3, vertex4)
        e4 = (vertex4, vertex1)
        for e in e1,e2,e3,e4:
      #ensure edges are listed as lowest -> highest vertex index
      #for consistency...
      for e in list:
        i = list.index(e)
        if e[0].index > e[1].index:
          list[i] = (e[1],e[0])
      return list
    def GetFaceNormal(self):
      """ Returns the face normal.
        Code derived from A.D'Agostino's backface culling script for Blender.
        Modified by z3r0_d to use all verts in a quad"""
      if len(self.v) == 3:
        p = vsub(self.v[1], self.v[0])
        q = vsub(self.v[2], self.v[0])
        a = vcross(p, q)
      elif len(self.v) == 4:
        a = vcross( \
          vsub(self.v[0].co, self.v[2].co),
          vsub(self.v[1].co, self.v[3].co) )
      else: # there is no meaningful response for 2 sided faces and I don't know how to handle more sides
        a = [1, 0, 0]
      return vunit(a)
  # autosmooth.py
  # may 2004, z3r0_d (Nick Winters)
  # status: works, but not fully tested
  #   - haven't tested meshes with many holes
  #   - and haven't tested to see if autosmooth result is 
  #     EXACTLY the same as blender's, and for changes in the angle value
  # prerequisites:
  #   load this text file (autosmooth.py) into blender's text window
  #   and meshplus.py (either with or without my modifications should work)
  #   and vector.py
  #  they should all be included 
  # usage: select your objects (meshes) and press alt+p with the cursor in the text window
  import math
  #import Blender
  #import vector
  #import meshplus
  bad = 0
  # progressbar?
  nmesh_bleh = NMesh.GetRawFromObject(obj.name)
  # print nmesh_bleh.name
  nmesh = NMesh.GetRaw(nmesh_bleh.name)
  # get the ANGLE!!!
  ANGLE = nmesh.getMaxSmoothAngle() / 180.0 * 3.141592654
  angleval = math.cos(ANGLE)
  print "\t","creating mplus"
  mplus = MeshPlus(nmesh)
  # find the edges I need to make hard
  print "\t","finding edges to make hard"
  toBeHardEdges = []
  beenWarned = 0
  for edge in mplus.edge_list: # edge is a 2 vert tuple, a key in the edge list
    e2 = mplus.edge_list[edge]
    # each edge is a list of the verts it contains
    if len(e2) == 2:
      if vdot(e2[0].fnorm, e2[1].fnorm) < angleval:
      if len(e2) > 2 and beenWarned == 0:
        print "\t","UNTESTED: this is a non manifold mesh!!!!"
        beenWarned = 1

  if bad == 1:
    return nmesh
  print "\t",len(toBeHardEdges), "edges to make hard"
  print "\t","making dictionary of vert's used edges"
  vertEdges = {}
  # find the verts I will need to duplicate...
  for anEdge in toBeHardEdges:
    # add anEdge[0] and anEdge[1] to my dictionary
    if vertEdges.has_key(anEdge[0]):
      vertEdges[anEdge[0]] = [anEdge]
    # second vertex in edge
    if vertEdges.has_key(anEdge[1]):
      vertEdges[anEdge[1]] = [anEdge]
  print "\t","hardening edges now"
  # payoff is coming, or the end is near
  for vertKey in vertEdges:
    hardEdges = vertEdges[vertKey]
    #print vertKey
    #print vertEdges
    #print hardEdges
    if len(hardEdges) > 1:
      # reset each face's beendone value
      # this could be made more efficent, want to prove concept first
      for aface in mplus.faces:
        aface.beendone = 0
      firstedge = 0
      for hardEdge in hardEdges:
        #traverse faces..
        for face in mplus.edge_list[hardEdge]:
          #	face.beendone
          #except AttributeError:
          if face.beendone == 0:
            newvert = vertKey # only create a new vert after the first edge?
            if firstedge != 0:
              # copy vertKey into newVert
              newvert = NMesh.Vert()
              for i in range(3):
                newvert.co[i] = vertKey.co[i]
                newvert.no[i] = vertKey.no[i]
              newvert.uvco[0] = vertKey.uvco[0]
              newvert.uvco[1] = vertKey.uvco[1]
              newvert.sel = vertKey.sel
              #print newvert
            firstedge += 1
            # go through all faces starting with face which contain vertKey
            # stop if trying to go over an edge in hardEdges
            # don't go into faces which have been done
            faces = [face]
            face.beendone = 1
            while faces != []:
              thisface = faces.pop()
              #thisface.beendone = 1 # should already be the case
              # find edges containing vertKey
              # (do not try edges in hardEdges)
              # add contained faces that have not been done (use try)
              # into faces
              # replace vertKey with the newvert in face
              realindex = 0
              try: # is this a hack?
                vkeyindex = thisface.v.index(vertKey)
                realindex = 1
              except ValueError:
                return nmesh
              if realindex != 1:
                print "!!!!???"
              adjacent_edges = [
                thisface.edges[(vkeyindex - 1) % len(thisface.edges)],
                thisface.edges[vkeyindex] ]
              for anEdge in adjacent_edges:
                  # anEdge isn't one I want to make hard
                  for prospectFace in mplus.edge_list[anEdge]:
                    if prospectFace.beendone == 0:
                      prospectFace.beendone = 1
              thisface.v[vkeyindex] = newvert
  nmesh.update(1) # will re-calculate normals
  scn = Scene.GetCurrent()
  return nmesh

# getRenderMesh(Object.GetSelected()[0])

from Blender import *

def save_pov(filename):
  file = open(filename, 'w')
  scene = Scene.GetCurrent()
  def exportCamera():
    camera = scene.getCurrentCamera()
    matrix = camera.getMatrix('worldspace')
    rotMat = matrix.rotationPart()
    euler = rotMat.toEuler()
    print euler
    #lookatVec = apply_transform(Mathutils.Vector([0,0,-10]), matrix)
    file.write('camera {\n')
    file.write('  location  <0, 0, 0>\n')
    file.write('  look_at  <0, 0, -1>\n')
    file.write('  direction <0, 0, 1.0>\n')
    file.write('  rotate  <%s, %s, %s>\n' % (euler[0]*-1, euler[1], euler[2]*-1))
    file.write('  translate <%s, %s, %s>\n' % (matrix[3][0], matrix[3][1], matrix[3][2]))
  def exportLamps():
    # Get all lamps
    for ob in Object.Get():
      if ob.getType() != 'Lamp':
      lamp = ob.getData()
      loc = ob.getMatrix('worldspace')[3]
      file.write('light_source { <%s, %s, %s> color red %s green %s blue %s }\n' % (loc[0], loc[1], loc[2],  lamp.col[0],lamp.col[1],lamp.col[2]))

  def exportMeshs():
    # Get all meshs
    for ob in Object.Get():
      if ob.getType() != 'Mesh':
      m = getRenderMesh(ob)
      if len(m.verts) == 0: # Make sure there is somthing to write.
        continue #dont bother with this mesh.
      matrix = ob.getMatrix('worldspace')
      file.write('mesh2 {\n')
      file.write('  vertex_vectors {\n')
      file.write('    %s' % (len(m.verts))) # vert count
      for v in m.verts:
        file.write(',\n    <%s,%s,%s>' % (v.co[0], v.co[1], v.co[2])) # vert count
      file.write('\n  }\n')
      file.write('  normal_vectors {\n')
      file.write('    %s' % (len(m.verts))) # vert count
      for v in m.verts:
        file.write(',\n    <%s,%s,%s>' % (v.no[0], v.no[1], v.no[2])) # vert count
      file.write('\n  }\n')
      file.write('  face_indices {\n')
      # quads incur an extra face
      quadCount = 0
      for f in m.faces:
        if len(f.v) == 4:
          quadCount +=1
      file.write('    %s' % (len(m.faces) + quadCount)) # faces count
      for f in m.faces:
        if len(f.v) == 3:
          file.write(',\n    <%s,%s,%s>' % (m.verts.index(f.v[0]), m.verts.index(f.v[1]), m.verts.index(f.v[2]))) # vert count
        elif len(f.v) == 4:
          file.write(',\n    <%s,%s,%s>' % (m.verts.index(f.v[0]), m.verts.index(f.v[1]), m.verts.index(f.v[2]))) # vert count
          file.write(',\n    <%s,%s,%s>' % (m.verts.index(f.v[0]), m.verts.index(f.v[2]), m.verts.index(f.v[3]))) # vert count
      file.write('\n  }\n')
      file.write('  pigment {rgb 1}\n')

# save_pov('/share/povray-3.6/scenes/d.pov')

Window.FileSelector(save_pov, 'Export Povray')

# import os
# os.system('povray +P +X +D0 -V /share/povray-3.6/scenes/d.pov')

# os.system('povray +W700 +H700 +P +X +D0 -V /share/povray-3.6/scenes/d.pov' )

Posts: 33
Joined: Sat Oct 19, 2002 3:04 pm

Re: povray exporter- working alpha

Post by jms »

ideasman wrote:Hi, heres my latest attempt at a povray exporter-
Its only just useable now but it has some nice features.
- Simple meshs export - Autosmoothing applied!
you should try to export subsurf to see the real qualities of this peace of code...

Last edited by jms on Sun Sep 12, 2004 9:02 pm, edited 3 times in total.
Zoo-3D.Blender, Ze French-Speaking Community SKB My french book about Blender.

Posts: 0
Joined: Thu Nov 27, 2003 4:40 pm

Post by Joh@n »

i hope that script is going to work because we really need a good and simple script to make blender and povray work together !!!

keep on with it

Posts: 0
Joined: Thu Nov 27, 2003 4:40 pm

Post by Joh@n »

i've once try povanim and it looked like a boeing dashboard for me :D

Posts: 131
Joined: Mon Oct 14, 2002 8:24 am

Re: povray exporter- working alpha

Post by ilac »

jms wrote:
ideasman wrote:Hi, heres my latest attempt at a povray exporter-
Its only just useable now but it has some nice features.
- Simple meshs export - Autosmoothing applied!
you should try to export subsurf to see the real qualities of this peace of code...

Grow up. Try and be helpful instead of so arrogant every single time.
Yes, you write great scripts and I am as grateful for that as everybody else who is aquainted with your excellent work - but that is no reason to negatively critise everybody who tries to do something you have already done (which, given the volume of your work happens rather often). If Campbell feels inspired to try and do his version, and could learn from it, then he has every right to do so. If its a futile attempt, time does an excellent job of cruelly taking care of that.

Thank you.

Posts: 33
Joined: Sat Oct 19, 2002 3:04 pm

Post by jms »

You should read the message like this : this code for autosmooth does not
work correctly with subsurf .

But you are right when you think that I am not happy to see this
new script grow.
Zoo-3D.Blender, Ze French-Speaking Community SKB My french book about Blender.

Posts: 0
Joined: Tue Aug 31, 2004 6:08 pm
Location: Portugal

Post by rcas »

I see a lot of love in here.

Hey guys, we should join forces, not the other way around. ....
How to use a Blender:
Put your model, rig, animation and textures in the Blender, turn the Blender on and wait for it to Render, then turn the Blender off and show it to your friends.

Posts: 143
Joined: Fri Oct 18, 2002 8:35 pm

Post by Dani »

hum... I study a lot of biology and palalentology, and so I'm also a lot into all that evolutionism stuff which very globally says that the best one should win... competition cannot be bad.


Post Reply